forked from Minki/linux
Merge branch 'master' into upstream
This commit is contained in:
commit
9528454f9c
@ -259,9 +259,9 @@ sub dibusb {
|
||||
}
|
||||
|
||||
sub nxt2002 {
|
||||
my $sourcefile = "Broadband4PC_4_2_11.zip";
|
||||
my $sourcefile = "Technisat_DVB-PC_4_4_COMPACT.zip";
|
||||
my $url = "http://www.bbti.us/download/windows/$sourcefile";
|
||||
my $hash = "c6d2ea47a8f456d887ada0cfb718ff2a";
|
||||
my $hash = "476befae8c7c1bb9648954060b1eec1f";
|
||||
my $outfile = "dvb-fe-nxt2002.fw";
|
||||
my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 1);
|
||||
|
||||
@ -269,8 +269,8 @@ sub nxt2002 {
|
||||
|
||||
wgetfile($sourcefile, $url);
|
||||
unzip($sourcefile, $tmpdir);
|
||||
verify("$tmpdir/SkyNETU.sys", $hash);
|
||||
extract("$tmpdir/SkyNETU.sys", 375832, 5908, $outfile);
|
||||
verify("$tmpdir/SkyNET.sys", $hash);
|
||||
extract("$tmpdir/SkyNET.sys", 331624, 5908, $outfile);
|
||||
|
||||
$outfile;
|
||||
}
|
||||
|
@ -105,20 +105,3 @@
|
||||
on the setup, so I think that the choice on what firmware to make
|
||||
persistent should be left to userspace.
|
||||
|
||||
- Why register_firmware()+__init can be useful:
|
||||
- For boot devices needing firmware.
|
||||
- To make the transition easier:
|
||||
The firmware can be declared __init and register_firmware()
|
||||
called on module_init. Then the firmware is warranted to be
|
||||
there even if "firmware hotplug userspace" is not there yet or
|
||||
it doesn't yet provide the needed firmware.
|
||||
Once the firmware is widely available in userspace, it can be
|
||||
removed from the kernel. Or made optional (CONFIG_.*_FIRMWARE).
|
||||
|
||||
In either case, if firmware hotplug support is there, it can move the
|
||||
firmware out of kernel memory into the real filesystem for later
|
||||
usage.
|
||||
|
||||
Note: If persistence is implemented on top of initramfs,
|
||||
register_firmware() may not be appropriate.
|
||||
|
||||
|
@ -5,8 +5,6 @@
|
||||
*
|
||||
* Sample code on how to use request_firmware() from drivers.
|
||||
*
|
||||
* Note that register_firmware() is currently useless.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
@ -17,11 +15,6 @@
|
||||
|
||||
#include "linux/firmware.h"
|
||||
|
||||
#define WE_CAN_NEED_FIRMWARE_BEFORE_USERSPACE_IS_AVAILABLE
|
||||
#ifdef WE_CAN_NEED_FIRMWARE_BEFORE_USERSPACE_IS_AVAILABLE
|
||||
char __init inkernel_firmware[] = "let's say that this is firmware\n";
|
||||
#endif
|
||||
|
||||
static struct device ghost_device = {
|
||||
.bus_id = "ghost0",
|
||||
};
|
||||
@ -104,10 +97,6 @@ static void sample_probe_async(void)
|
||||
|
||||
static int sample_init(void)
|
||||
{
|
||||
#ifdef WE_CAN_NEED_FIRMWARE_BEFORE_USERSPACE_IS_AVAILABLE
|
||||
register_firmware("sample_driver_fw", inkernel_firmware,
|
||||
sizeof(inkernel_firmware));
|
||||
#endif
|
||||
device_initialize(&ghost_device);
|
||||
/* since there is no real hardware insertion I just call the
|
||||
* sample probe functions here */
|
||||
|
29
MAINTAINERS
29
MAINTAINERS
@ -40,11 +40,20 @@ trivial patch so apply some common sense.
|
||||
PLEASE document known bugs. If it doesn't work for everything
|
||||
or does something very odd once a month document it.
|
||||
|
||||
PLEASE remember that submissions must be made under the terms
|
||||
of the OSDL certificate of contribution
|
||||
(http://www.osdl.org/newsroom/press_releases/2004/2004_05_24_dco.html)
|
||||
and should include a Signed-off-by: line.
|
||||
|
||||
6. Make sure you have the right to send any changes you make. If you
|
||||
do changes at work you may find your employer owns the patch
|
||||
not you.
|
||||
|
||||
7. Happy hacking.
|
||||
7. When sending security related changes or reports to a maintainer
|
||||
please Cc: security@kernel.org, especially if the maintainer
|
||||
does not respond.
|
||||
|
||||
8. Happy hacking.
|
||||
|
||||
-----------------------------------
|
||||
|
||||
@ -969,7 +978,7 @@ S: Maintained
|
||||
EXT3 FILE SYSTEM
|
||||
P: Stephen Tweedie, Andrew Morton
|
||||
M: sct@redhat.com, akpm@osdl.org, adilger@clusterfs.com
|
||||
L: ext3-users@redhat.com
|
||||
L: ext2-devel@lists.sourceforge.net
|
||||
S: Maintained
|
||||
|
||||
F71805F HARDWARE MONITORING DRIVER
|
||||
@ -1536,12 +1545,28 @@ W: http://jfs.sourceforge.net/
|
||||
T: git kernel.org:/pub/scm/linux/kernel/git/shaggy/jfs-2.6.git
|
||||
S: Supported
|
||||
|
||||
JOURNALLING LAYER FOR BLOCK DEVICS (JBD)
|
||||
P: Stephen Tweedie, Andrew Morton
|
||||
M: sct@redhat.com, akpm@osdl.org
|
||||
L: ext2-devel@lists.sourceforge.net
|
||||
S: Maintained
|
||||
|
||||
KCONFIG
|
||||
P: Roman Zippel
|
||||
M: zippel@linux-m68k.org
|
||||
L: kbuild-devel@lists.sourceforge.net
|
||||
S: Maintained
|
||||
|
||||
KDUMP
|
||||
P: Vivek Goyal
|
||||
M: vgoyal@in.ibm.com
|
||||
P: Haren Myneni
|
||||
M: hbabu@us.ibm.com
|
||||
L: fastboot@lists.osdl.org
|
||||
L: linux-kernel@vger.kernel.org
|
||||
W: http://lse.sourceforge.net/kdump/
|
||||
S: Maintained
|
||||
|
||||
KERNEL AUTOMOUNTER (AUTOFS)
|
||||
P: H. Peter Anvin
|
||||
M: hpa@zytor.com
|
||||
|
@ -1341,6 +1341,14 @@ int __init APIC_init_uniprocessor (void)
|
||||
|
||||
connect_bsp_APIC();
|
||||
|
||||
/*
|
||||
* Hack: In case of kdump, after a crash, kernel might be booting
|
||||
* on a cpu with non-zero lapic id. But boot_cpu_physical_apicid
|
||||
* might be zero if read from MP tables. Get it from LAPIC.
|
||||
*/
|
||||
#ifdef CONFIG_CRASH_DUMP
|
||||
boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID));
|
||||
#endif
|
||||
phys_cpu_present_map = physid_mask_of_physid(boot_cpu_physical_apicid);
|
||||
|
||||
setup_local_APIC();
|
||||
|
@ -130,9 +130,8 @@ static inline int print_addr_and_symbol(unsigned long addr, char *log_lvl,
|
||||
print_symbol("%s", addr);
|
||||
|
||||
printed = (printed + 1) % CONFIG_STACK_BACKTRACE_COLS;
|
||||
|
||||
if (printed)
|
||||
printk(" ");
|
||||
printk(" ");
|
||||
else
|
||||
printk("\n");
|
||||
|
||||
@ -212,7 +211,6 @@ static void show_stack_log_lvl(struct task_struct *task, unsigned long *esp,
|
||||
}
|
||||
|
||||
stack = esp;
|
||||
printk(log_lvl);
|
||||
for(i = 0; i < kstack_depth_to_print; i++) {
|
||||
if (kstack_end(stack))
|
||||
break;
|
||||
|
@ -651,7 +651,7 @@ void __init mem_init(void)
|
||||
* Specifically, in the case of x86, we will always add
|
||||
* memory to the highmem for now.
|
||||
*/
|
||||
#ifdef CONFIG_HOTPLUG_MEMORY
|
||||
#ifdef CONFIG_MEMORY_HOTPLUG
|
||||
#ifndef CONFIG_NEED_MULTIPLE_NODES
|
||||
int add_memory(u64 start, u64 size)
|
||||
{
|
||||
|
@ -92,7 +92,7 @@ void __restore_processor_state(struct saved_context *ctxt)
|
||||
write_cr4(ctxt->cr4);
|
||||
write_cr3(ctxt->cr3);
|
||||
write_cr2(ctxt->cr2);
|
||||
write_cr2(ctxt->cr0);
|
||||
write_cr0(ctxt->cr0);
|
||||
|
||||
/*
|
||||
* now restore the descriptor tables to their proper values
|
||||
|
@ -338,6 +338,8 @@ SYSCALL(symlinkat)
|
||||
SYSCALL(readlinkat)
|
||||
SYSCALL(fchmodat)
|
||||
SYSCALL(faccessat)
|
||||
COMPAT_SYS(get_robust_list)
|
||||
COMPAT_SYS(set_robust_list)
|
||||
|
||||
/*
|
||||
* please add new calls to arch/powerpc/platforms/cell/spu_callbacks.c
|
||||
|
@ -258,6 +258,7 @@ void *spu_syscall_table[] = {
|
||||
[__NR_futex] sys_futex,
|
||||
[__NR_sched_setaffinity] sys_sched_setaffinity,
|
||||
[__NR_sched_getaffinity] sys_sched_getaffinity,
|
||||
[224] sys_ni_syscall,
|
||||
[__NR_tuxcall] sys_ni_syscall,
|
||||
[226] sys_ni_syscall,
|
||||
[__NR_io_setup] sys_io_setup,
|
||||
@ -332,19 +333,21 @@ void *spu_syscall_table[] = {
|
||||
[__NR_readlinkat] sys_readlinkat,
|
||||
[__NR_fchmodat] sys_fchmodat,
|
||||
[__NR_faccessat] sys_faccessat,
|
||||
[__NR_get_robust_list] sys_get_robust_list,
|
||||
[__NR_set_robust_list] sys_set_robust_list,
|
||||
};
|
||||
|
||||
long spu_sys_callback(struct spu_syscall_block *s)
|
||||
{
|
||||
long (*syscall)(u64 a1, u64 a2, u64 a3, u64 a4, u64 a5, u64 a6);
|
||||
|
||||
syscall = spu_syscall_table[s->nr_ret];
|
||||
|
||||
if (s->nr_ret >= ARRAY_SIZE(spu_syscall_table)) {
|
||||
pr_debug("%s: invalid syscall #%ld", __FUNCTION__, s->nr_ret);
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
syscall = spu_syscall_table[s->nr_ret];
|
||||
|
||||
#ifdef DEBUG
|
||||
print_symbol(KERN_DEBUG "SPU-syscall %s:", (unsigned long)syscall);
|
||||
printk("syscall%ld(%lx, %lx, %lx, %lx, %lx, %lx)\n",
|
||||
|
@ -272,7 +272,7 @@ static inline void stop_hz_timer(void)
|
||||
next = next_timer_interrupt();
|
||||
do {
|
||||
seq = read_seqbegin_irqsave(&xtime_lock, flags);
|
||||
timer = (__u64)(next - jiffies) + jiffies_64;
|
||||
timer = (__u64 next) - (__u64 jiffies) + jiffies_64;
|
||||
} while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
|
||||
todval = -1ULL;
|
||||
/* Be careful about overflows. */
|
||||
|
@ -79,6 +79,7 @@ sys_call_table:
|
||||
/*285*/ .long sys_mkdirat, sys_mknodat, sys_fchownat, sys_futimesat, sys_fstatat64
|
||||
/*290*/ .long sys_unlinkat, sys_renameat, sys_linkat, sys_symlinkat, sys_readlinkat
|
||||
/*295*/ .long sys_fchmodat, sys_faccessat, sys_pselect6, sys_ppoll, sys_unshare
|
||||
/*300*/ .long sys_set_robust_list, sys_get_robust_list
|
||||
|
||||
#ifdef CONFIG_SUNOS_EMUL
|
||||
/* Now the SunOS syscall table. */
|
||||
@ -190,6 +191,6 @@ sunos_sys_table:
|
||||
/*290*/ .long sunos_nosys, sunos_nosys, sunos_nosys
|
||||
.long sunos_nosys, sunos_nosys, sunos_nosys
|
||||
.long sunos_nosys, sunos_nosys, sunos_nosys
|
||||
.long sunos_nosys
|
||||
.long sunos_nosys, sunos_nosys, sunos_nosys
|
||||
|
||||
#endif
|
||||
|
@ -218,7 +218,7 @@ static inline void iommu_free_ctx(struct pci_iommu *iommu, int ctx)
|
||||
* DMA for PCI device PDEV. Return non-NULL cpu-side address if
|
||||
* successful and set *DMA_ADDRP to the PCI side dma address.
|
||||
*/
|
||||
static void *pci_4u_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr_t *dma_addrp)
|
||||
static void *pci_4u_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr_t *dma_addrp, gfp_t gfp)
|
||||
{
|
||||
struct pcidev_cookie *pcp;
|
||||
struct pci_iommu *iommu;
|
||||
@ -232,7 +232,7 @@ static void *pci_4u_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr
|
||||
if (order >= 10)
|
||||
return NULL;
|
||||
|
||||
first_page = __get_free_pages(GFP_ATOMIC, order);
|
||||
first_page = __get_free_pages(gfp, order);
|
||||
if (first_page == 0UL)
|
||||
return NULL;
|
||||
memset((char *)first_page, 0, PAGE_SIZE << order);
|
||||
|
@ -154,7 +154,7 @@ static void pci_arena_free(struct pci_iommu_arena *arena, unsigned long base, un
|
||||
__clear_bit(i, arena->map);
|
||||
}
|
||||
|
||||
static void *pci_4v_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr_t *dma_addrp)
|
||||
static void *pci_4v_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr_t *dma_addrp, gfp_t gfp)
|
||||
{
|
||||
struct pcidev_cookie *pcp;
|
||||
struct pci_iommu *iommu;
|
||||
@ -169,7 +169,7 @@ static void *pci_4v_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr
|
||||
|
||||
npages = size >> IO_PAGE_SHIFT;
|
||||
|
||||
first_page = __get_free_pages(GFP_ATOMIC, order);
|
||||
first_page = __get_free_pages(gfp, order);
|
||||
if (unlikely(first_page == 0UL))
|
||||
return NULL;
|
||||
|
||||
|
@ -78,8 +78,9 @@ sys_call_table32:
|
||||
.word compat_sys_mq_timedsend, compat_sys_mq_timedreceive, compat_sys_mq_notify, compat_sys_mq_getsetattr, compat_sys_waitid
|
||||
/*280*/ .word sys32_tee, sys_add_key, sys_request_key, sys_keyctl, compat_sys_openat
|
||||
.word sys_mkdirat, sys_mknodat, sys_fchownat, compat_sys_futimesat, compat_sys_fstatat64
|
||||
/*285*/ .word sys_unlinkat, sys_renameat, sys_linkat, sys_symlinkat, sys_readlinkat
|
||||
/*290*/ .word sys_unlinkat, sys_renameat, sys_linkat, sys_symlinkat, sys_readlinkat
|
||||
.word sys_fchmodat, sys_faccessat, compat_sys_pselect6, compat_sys_ppoll, sys_unshare
|
||||
/*300*/ .word compat_sys_set_robust_list, compat_sys_get_robust_list
|
||||
|
||||
#endif /* CONFIG_COMPAT */
|
||||
|
||||
@ -147,8 +148,9 @@ sys_call_table:
|
||||
.word sys_mq_timedsend, sys_mq_timedreceive, sys_mq_notify, sys_mq_getsetattr, sys_waitid
|
||||
/*280*/ .word sys_tee, sys_add_key, sys_request_key, sys_keyctl, sys_openat
|
||||
.word sys_mkdirat, sys_mknodat, sys_fchownat, sys_futimesat, sys_fstatat64
|
||||
/*285*/ .word sys_unlinkat, sys_renameat, sys_linkat, sys_symlinkat, sys_readlinkat
|
||||
/*290*/ .word sys_unlinkat, sys_renameat, sys_linkat, sys_symlinkat, sys_readlinkat
|
||||
.word sys_fchmodat, sys_faccessat, sys_pselect6, sys_ppoll, sys_unshare
|
||||
/*300*/ .word sys_set_robust_list, sys_get_robust_list
|
||||
|
||||
#if defined(CONFIG_SUNOS_EMUL) || defined(CONFIG_SOLARIS_EMUL) || \
|
||||
defined(CONFIG_SOLARIS_EMUL_MODULE)
|
||||
@ -261,5 +263,5 @@ sunos_sys_table:
|
||||
/*290*/ .word sunos_nosys, sunos_nosys, sunos_nosys
|
||||
.word sunos_nosys, sunos_nosys, sunos_nosys
|
||||
.word sunos_nosys, sunos_nosys, sunos_nosys
|
||||
.word sunos_nosys
|
||||
.word sunos_nosys, sunos_nosys, sunos_nosys
|
||||
#endif
|
||||
|
@ -514,13 +514,13 @@ static void __kprobes resume_execution(struct kprobe *p,
|
||||
*tos = orig_rip + (*tos - copy_rip);
|
||||
break;
|
||||
case 0xff:
|
||||
if ((*insn & 0x30) == 0x10) {
|
||||
if ((insn[1] & 0x30) == 0x10) {
|
||||
/* call absolute, indirect */
|
||||
/* Fix return addr; rip is correct. */
|
||||
next_rip = regs->rip;
|
||||
*tos = orig_rip + (*tos - copy_rip);
|
||||
} else if (((*insn & 0x31) == 0x20) || /* jmp near, absolute indirect */
|
||||
((*insn & 0x31) == 0x21)) { /* jmp far, absolute indirect */
|
||||
} else if (((insn[1] & 0x31) == 0x20) || /* jmp near, absolute indirect */
|
||||
((insn[1] & 0x31) == 0x21)) { /* jmp far, absolute indirect */
|
||||
/* rip is correct. */
|
||||
next_rip = regs->rip;
|
||||
}
|
||||
|
@ -3452,7 +3452,12 @@ void end_that_request_last(struct request *req, int uptodate)
|
||||
if (unlikely(laptop_mode) && blk_fs_request(req))
|
||||
laptop_io_completion();
|
||||
|
||||
if (disk && blk_fs_request(req)) {
|
||||
/*
|
||||
* Account IO completion. bar_rq isn't accounted as a normal
|
||||
* IO on queueing nor completion. Accounting the containing
|
||||
* request is enough.
|
||||
*/
|
||||
if (disk && blk_fs_request(req) && req != &req->q->bar_rq) {
|
||||
unsigned long duration = jiffies - req->start_time;
|
||||
const int rw = rq_data_dir(req);
|
||||
|
||||
|
@ -86,18 +86,9 @@ firmware_timeout_store(struct class *class, const char *buf, size_t count)
|
||||
static CLASS_ATTR(timeout, 0644, firmware_timeout_show, firmware_timeout_store);
|
||||
|
||||
static void fw_class_dev_release(struct class_device *class_dev);
|
||||
int firmware_class_uevent(struct class_device *dev, char **envp,
|
||||
int num_envp, char *buffer, int buffer_size);
|
||||
|
||||
static struct class firmware_class = {
|
||||
.name = "firmware",
|
||||
.uevent = firmware_class_uevent,
|
||||
.release = fw_class_dev_release,
|
||||
};
|
||||
|
||||
int
|
||||
firmware_class_uevent(struct class_device *class_dev, char **envp,
|
||||
int num_envp, char *buffer, int buffer_size)
|
||||
static int firmware_class_uevent(struct class_device *class_dev, char **envp,
|
||||
int num_envp, char *buffer, int buffer_size)
|
||||
{
|
||||
struct firmware_priv *fw_priv = class_get_devdata(class_dev);
|
||||
int i = 0, len = 0;
|
||||
@ -116,6 +107,12 @@ firmware_class_uevent(struct class_device *class_dev, char **envp,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct class firmware_class = {
|
||||
.name = "firmware",
|
||||
.uevent = firmware_class_uevent,
|
||||
.release = fw_class_dev_release,
|
||||
};
|
||||
|
||||
static ssize_t
|
||||
firmware_loading_show(struct class_device *class_dev, char *buf)
|
||||
{
|
||||
@ -493,25 +490,6 @@ release_firmware(const struct firmware *fw)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* register_firmware: - provide a firmware image for later usage
|
||||
* @name: name of firmware image file
|
||||
* @data: buffer pointer for the firmware image
|
||||
* @size: size of the data buffer area
|
||||
*
|
||||
* Make sure that @data will be available by requesting firmware @name.
|
||||
*
|
||||
* Note: This will not be possible until some kind of persistence
|
||||
* is available.
|
||||
**/
|
||||
void
|
||||
register_firmware(const char *name, const u8 *data, size_t size)
|
||||
{
|
||||
/* This is meaningless without firmware caching, so until we
|
||||
* decide if firmware caching is reasonable just leave it as a
|
||||
* noop */
|
||||
}
|
||||
|
||||
/* Async support */
|
||||
struct firmware_work {
|
||||
struct work_struct work;
|
||||
@ -630,4 +608,3 @@ module_exit(firmware_class_exit);
|
||||
EXPORT_SYMBOL(release_firmware);
|
||||
EXPORT_SYMBOL(request_firmware);
|
||||
EXPORT_SYMBOL(request_firmware_nowait);
|
||||
EXPORT_SYMBOL(register_firmware);
|
||||
|
@ -398,7 +398,7 @@ int tty_insert_flip_string_flags(struct tty_struct *tty,
|
||||
while (unlikely(size > copied));
|
||||
return copied;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tty_insert_flip_string_flags);
|
||||
EXPORT_SYMBOL(tty_insert_flip_string_flags);
|
||||
|
||||
void tty_schedule_flip(struct tty_struct *tty)
|
||||
{
|
||||
|
@ -553,6 +553,8 @@ pmac_ide_init_hwif_ports(hw_regs_t *hw,
|
||||
|
||||
if (irq != NULL)
|
||||
*irq = pmac_ide[ix].irq;
|
||||
|
||||
hw->dev = &pmac_ide[ix].mdev->ofdev.dev;
|
||||
}
|
||||
|
||||
#define PMAC_IDE_REG(x) ((void __iomem *)(IDE_DATA_REG+(x)))
|
||||
|
@ -2880,7 +2880,7 @@ isdn_tty_cmd_ATand(char **p, modem_info * info)
|
||||
p[0]++;
|
||||
i = 0;
|
||||
while (*p[0] && (strchr("0123456789,-*[]?;", *p[0])) &&
|
||||
(i < ISDN_LMSNLEN))
|
||||
(i < ISDN_LMSNLEN - 1))
|
||||
m->lmsn[i++] = *p[0]++;
|
||||
m->lmsn[i] = '\0';
|
||||
break;
|
||||
|
@ -2252,7 +2252,7 @@ action_store(mddev_t *mddev, const char *page, size_t len)
|
||||
} else {
|
||||
if (cmd_match(page, "check"))
|
||||
set_bit(MD_RECOVERY_CHECK, &mddev->recovery);
|
||||
else if (cmd_match(page, "repair"))
|
||||
else if (!cmd_match(page, "repair"))
|
||||
return -EINVAL;
|
||||
set_bit(MD_RECOVERY_REQUESTED, &mddev->recovery);
|
||||
set_bit(MD_RECOVERY_SYNC, &mddev->recovery);
|
||||
|
@ -331,13 +331,14 @@ static int raid0_run (mddev_t *mddev)
|
||||
goto out_free_conf;
|
||||
size = conf->strip_zone[cur].size;
|
||||
|
||||
for (i=0; i< nb_zone; i++) {
|
||||
conf->hash_table[i] = conf->strip_zone + cur;
|
||||
conf->hash_table[0] = conf->strip_zone + cur;
|
||||
for (i=1; i< nb_zone; i++) {
|
||||
while (size <= conf->hash_spacing) {
|
||||
cur++;
|
||||
size += conf->strip_zone[cur].size;
|
||||
}
|
||||
size -= conf->hash_spacing;
|
||||
conf->hash_table[i] = conf->strip_zone + cur;
|
||||
}
|
||||
if (conf->preshift) {
|
||||
conf->hash_spacing >>= conf->preshift;
|
||||
|
@ -8,22 +8,54 @@ config VIDEO_DEV
|
||||
tristate "Video For Linux"
|
||||
---help---
|
||||
Support for audio/video capture and overlay devices and FM radio
|
||||
cards. The exact capabilities of each device vary. User tools for
|
||||
this are available from
|
||||
<ftp://ftp.uk.linux.org/pub/linux/video4linux/>.
|
||||
cards. The exact capabilities of each device vary.
|
||||
|
||||
This kernel includes support for the new Video for Linux Two API,
|
||||
(V4L2) as well as the original system. Drivers and applications
|
||||
need to be rewritten to use V4L2, but drivers for popular cards
|
||||
and applications for most video capture functions already exist.
|
||||
|
||||
Documentation for the original API is included in the file
|
||||
<file:Documentation/video4linux/API.html>. Documentation for V4L2 is
|
||||
available on the web at <http://bytesex.org/v4l/>.
|
||||
Additional info and docs are available on the web at
|
||||
<http://linuxtv.org>
|
||||
|
||||
Documentation for V4L2 is also available on the web at
|
||||
<http://bytesex.org/v4l/>.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called videodev.
|
||||
|
||||
config VIDEO_V4L1
|
||||
boolean "Enable Video For Linux API 1 (DEPRECATED)"
|
||||
depends on VIDEO_DEV
|
||||
select VIDEO_V4L1_COMPAT
|
||||
default y
|
||||
---help---
|
||||
Enables a compatibility API used by most V4L2 devices to allow
|
||||
its usage with legacy applications that supports only V4L1 api.
|
||||
|
||||
If you are unsure as to whether this is required, answer Y.
|
||||
|
||||
config VIDEO_V4L1_COMPAT
|
||||
boolean "Enable Video For Linux API 1 compatible Layer"
|
||||
depends on VIDEO_DEV
|
||||
default y
|
||||
---help---
|
||||
This api were developed to be used at Kernel 2.2 and 2.4, but
|
||||
lacks support for several video standards. There are several
|
||||
drivers at kernel that still depends on it.
|
||||
|
||||
Documentation for the original API is included in the file
|
||||
<Documentation/video4linux/API.html>.
|
||||
|
||||
User tools for this are available from
|
||||
<ftp://ftp.uk.linux.org/pub/linux/video4linux/>.
|
||||
|
||||
If you are unsure as to whether this is required, answer Y.
|
||||
|
||||
config VIDEO_V4L2
|
||||
tristate
|
||||
default y
|
||||
|
||||
source "drivers/media/video/Kconfig"
|
||||
|
||||
source "drivers/media/radio/Kconfig"
|
||||
@ -65,4 +97,3 @@ config USB_DABUSB
|
||||
module will be called dabusb.
|
||||
|
||||
endmenu
|
||||
|
||||
|
@ -4,6 +4,7 @@ config VIDEO_SAA7146
|
||||
|
||||
config VIDEO_SAA7146_VV
|
||||
tristate
|
||||
select VIDEO_V4L2
|
||||
select VIDEO_BUF
|
||||
select VIDEO_VIDEOBUF
|
||||
select VIDEO_SAA7146
|
||||
|
@ -7,6 +7,7 @@ config DVB_BT8XX
|
||||
select DVB_CX24110
|
||||
select DVB_OR51211
|
||||
select DVB_LGDT330X
|
||||
select DVB_ZL10353
|
||||
select FW_LOADER
|
||||
help
|
||||
Support for PCI cards based on the Bt8xx PCI bridge. Examples are
|
||||
|
@ -902,7 +902,10 @@ static int cinergyt2_probe (struct usb_interface *intf,
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
dvb_register_adapter(&cinergyt2->adapter, DRIVER_NAME, THIS_MODULE);
|
||||
if ((err = dvb_register_adapter(&cinergyt2->adapter, DRIVER_NAME, THIS_MODULE)) < 0) {
|
||||
kfree(cinergyt2);
|
||||
return err;
|
||||
}
|
||||
|
||||
cinergyt2->demux.priv = cinergyt2;
|
||||
cinergyt2->demux.filternum = 256;
|
||||
|
@ -106,6 +106,8 @@ struct dvb_frontend_private {
|
||||
unsigned long tune_mode_flags;
|
||||
unsigned int delay;
|
||||
unsigned int reinitialise;
|
||||
int tone;
|
||||
int voltage;
|
||||
|
||||
/* swzigzag values */
|
||||
unsigned int state;
|
||||
@ -537,6 +539,12 @@ static int dvb_frontend_thread(void *data)
|
||||
|
||||
if (fepriv->reinitialise) {
|
||||
dvb_frontend_init(fe);
|
||||
if (fepriv->tone != -1) {
|
||||
fe->ops->set_tone(fe, fepriv->tone);
|
||||
}
|
||||
if (fepriv->voltage != -1) {
|
||||
fe->ops->set_voltage(fe, fepriv->voltage);
|
||||
}
|
||||
fepriv->reinitialise = 0;
|
||||
}
|
||||
|
||||
@ -788,6 +796,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
|
||||
case FE_SET_TONE:
|
||||
if (fe->ops->set_tone) {
|
||||
err = fe->ops->set_tone(fe, (fe_sec_tone_mode_t) parg);
|
||||
fepriv->tone = (fe_sec_tone_mode_t) parg;
|
||||
fepriv->state = FESTATE_DISEQC;
|
||||
fepriv->status = 0;
|
||||
}
|
||||
@ -796,6 +805,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
|
||||
case FE_SET_VOLTAGE:
|
||||
if (fe->ops->set_voltage) {
|
||||
err = fe->ops->set_voltage(fe, (fe_sec_voltage_t) parg);
|
||||
fepriv->voltage = (fe_sec_voltage_t) parg;
|
||||
fepriv->state = FESTATE_DISEQC;
|
||||
fepriv->status = 0;
|
||||
}
|
||||
@ -995,6 +1005,8 @@ static int dvb_frontend_open(struct inode *inode, struct file *file)
|
||||
|
||||
/* normal tune mode when opened R/W */
|
||||
fepriv->tune_mode_flags &= ~FE_TUNE_MODE_ONESHOT;
|
||||
fepriv->tone = -1;
|
||||
fepriv->voltage = -1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -219,8 +219,6 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
mutex_unlock(&dvbdev_register_lock);
|
||||
|
||||
memcpy(dvbdev, template, sizeof(struct dvb_device));
|
||||
dvbdev->type = type;
|
||||
dvbdev->id = id;
|
||||
@ -231,6 +229,8 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
|
||||
|
||||
list_add_tail (&dvbdev->list_head, &adap->device_list);
|
||||
|
||||
mutex_unlock(&dvbdev_register_lock);
|
||||
|
||||
devfs_mk_cdev(MKDEV(DVB_MAJOR, nums2minor(adap->num, type, id)),
|
||||
S_IFCHR | S_IRUSR | S_IWUSR,
|
||||
"dvb/adapter%d/%s%d", adap->num, dnames[type], id);
|
||||
|
@ -150,6 +150,15 @@ static int cxusb_power_ctrl(struct dvb_usb_device *d, int onoff)
|
||||
return cxusb_ctrl_msg(d, CMD_POWER_OFF, &b, 1, NULL, 0);
|
||||
}
|
||||
|
||||
static int cxusb_bluebird_power_ctrl(struct dvb_usb_device *d, int onoff)
|
||||
{
|
||||
u8 b = 0;
|
||||
if (onoff)
|
||||
return cxusb_ctrl_msg(d, CMD_POWER_ON, &b, 1, NULL, 0);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cxusb_streaming_ctrl(struct dvb_usb_device *d, int onoff)
|
||||
{
|
||||
u8 buf[2] = { 0x03, 0x00 };
|
||||
@ -544,7 +553,7 @@ static struct dvb_usb_properties cxusb_bluebird_lgh064f_properties = {
|
||||
.size_of_priv = sizeof(struct cxusb_state),
|
||||
|
||||
.streaming_ctrl = cxusb_streaming_ctrl,
|
||||
.power_ctrl = cxusb_power_ctrl,
|
||||
.power_ctrl = cxusb_bluebird_power_ctrl,
|
||||
.frontend_attach = cxusb_lgdt3303_frontend_attach,
|
||||
.tuner_attach = cxusb_lgh064f_tuner_attach,
|
||||
|
||||
@ -589,7 +598,7 @@ static struct dvb_usb_properties cxusb_bluebird_dee1601_properties = {
|
||||
.size_of_priv = sizeof(struct cxusb_state),
|
||||
|
||||
.streaming_ctrl = cxusb_streaming_ctrl,
|
||||
.power_ctrl = cxusb_power_ctrl,
|
||||
.power_ctrl = cxusb_bluebird_power_ctrl,
|
||||
.frontend_attach = cxusb_dee1601_frontend_attach,
|
||||
.tuner_attach = cxusb_dee1601_tuner_attach,
|
||||
|
||||
@ -638,7 +647,7 @@ static struct dvb_usb_properties cxusb_bluebird_lgz201_properties = {
|
||||
.size_of_priv = sizeof(struct cxusb_state),
|
||||
|
||||
.streaming_ctrl = cxusb_streaming_ctrl,
|
||||
.power_ctrl = cxusb_power_ctrl,
|
||||
.power_ctrl = cxusb_bluebird_power_ctrl,
|
||||
.frontend_attach = cxusb_mt352_frontend_attach,
|
||||
.tuner_attach = cxusb_lgz201_tuner_attach,
|
||||
|
||||
@ -683,7 +692,7 @@ static struct dvb_usb_properties cxusb_bluebird_dtt7579_properties = {
|
||||
.size_of_priv = sizeof(struct cxusb_state),
|
||||
|
||||
.streaming_ctrl = cxusb_streaming_ctrl,
|
||||
.power_ctrl = cxusb_power_ctrl,
|
||||
.power_ctrl = cxusb_bluebird_power_ctrl,
|
||||
.frontend_attach = cxusb_mt352_frontend_attach,
|
||||
.tuner_attach = cxusb_dtt7579_tuner_attach,
|
||||
|
||||
|
@ -29,6 +29,9 @@
|
||||
#include "dvb_frontend.h"
|
||||
#include "cx24123.h"
|
||||
|
||||
#define XTAL 10111000
|
||||
|
||||
static int force_band;
|
||||
static int debug;
|
||||
#define dprintk(args...) \
|
||||
do { \
|
||||
@ -52,6 +55,7 @@ struct cx24123_state
|
||||
u32 VGAarg;
|
||||
u32 bandselectarg;
|
||||
u32 pllarg;
|
||||
u32 FILTune;
|
||||
|
||||
/* The Demod/Tuner can't easily provide these, we cache them */
|
||||
u32 currentfreq;
|
||||
@ -63,43 +67,33 @@ static struct
|
||||
{
|
||||
u32 symbolrate_low;
|
||||
u32 symbolrate_high;
|
||||
u32 VCAslope;
|
||||
u32 VCAoffset;
|
||||
u32 VGA1offset;
|
||||
u32 VGA2offset;
|
||||
u32 VCAprogdata;
|
||||
u32 VGAprogdata;
|
||||
u32 FILTune;
|
||||
} cx24123_AGC_vals[] =
|
||||
{
|
||||
{
|
||||
.symbolrate_low = 1000000,
|
||||
.symbolrate_high = 4999999,
|
||||
.VCAslope = 0x07,
|
||||
.VCAoffset = 0x0f,
|
||||
.VGA1offset = 0x1f8,
|
||||
.VGA2offset = 0x1f8,
|
||||
.VGAprogdata = (2 << 18) | (0x1f8 << 9) | 0x1f8,
|
||||
.VCAprogdata = (4 << 18) | (0x07 << 9) | 0x07,
|
||||
/* the specs recommend other values for VGA offsets,
|
||||
but tests show they are wrong */
|
||||
.VGAprogdata = (1 << 19) | (0x180 << 9) | 0x1e0,
|
||||
.VCAprogdata = (2 << 19) | (0x07 << 9) | 0x07,
|
||||
.FILTune = 0x27f /* 0.41 V */
|
||||
},
|
||||
{
|
||||
.symbolrate_low = 5000000,
|
||||
.symbolrate_high = 14999999,
|
||||
.VCAslope = 0x1f,
|
||||
.VCAoffset = 0x1f,
|
||||
.VGA1offset = 0x1e0,
|
||||
.VGA2offset = 0x180,
|
||||
.VGAprogdata = (2 << 18) | (0x180 << 9) | 0x1e0,
|
||||
.VCAprogdata = (4 << 18) | (0x07 << 9) | 0x1f,
|
||||
.VGAprogdata = (1 << 19) | (0x180 << 9) | 0x1e0,
|
||||
.VCAprogdata = (2 << 19) | (0x07 << 9) | 0x1f,
|
||||
.FILTune = 0x317 /* 0.90 V */
|
||||
},
|
||||
{
|
||||
.symbolrate_low = 15000000,
|
||||
.symbolrate_high = 45000000,
|
||||
.VCAslope = 0x3f,
|
||||
.VCAoffset = 0x3f,
|
||||
.VGA1offset = 0x180,
|
||||
.VGA2offset = 0x100,
|
||||
.VGAprogdata = (2 << 18) | (0x100 << 9) | 0x180,
|
||||
.VCAprogdata = (4 << 18) | (0x07 << 9) | 0x3f,
|
||||
.VGAprogdata = (1 << 19) | (0x100 << 9) | 0x180,
|
||||
.VCAprogdata = (2 << 19) | (0x07 << 9) | 0x3f,
|
||||
.FILTune = 0x145 /* 2.70 V */
|
||||
},
|
||||
};
|
||||
|
||||
@ -112,91 +106,80 @@ static struct
|
||||
{
|
||||
u32 freq_low;
|
||||
u32 freq_high;
|
||||
u32 bandselect;
|
||||
u32 VCOdivider;
|
||||
u32 VCOnumber;
|
||||
u32 progdata;
|
||||
} cx24123_bandselect_vals[] =
|
||||
{
|
||||
/* band 1 */
|
||||
{
|
||||
.freq_low = 950000,
|
||||
.freq_high = 1018999,
|
||||
.bandselect = 0x40,
|
||||
.VCOdivider = 4,
|
||||
.VCOnumber = 7,
|
||||
.progdata = (0 << 18) | (0 << 9) | 0x40,
|
||||
},
|
||||
{
|
||||
.freq_low = 1019000,
|
||||
.freq_high = 1074999,
|
||||
.bandselect = 0x80,
|
||||
.VCOdivider = 4,
|
||||
.VCOnumber = 8,
|
||||
.progdata = (0 << 18) | (0 << 9) | 0x80,
|
||||
.progdata = (0 << 19) | (0 << 9) | 0x40,
|
||||
},
|
||||
|
||||
/* band 2 */
|
||||
{
|
||||
.freq_low = 1075000,
|
||||
.freq_high = 1227999,
|
||||
.bandselect = 0x01,
|
||||
.VCOdivider = 2,
|
||||
.VCOnumber = 1,
|
||||
.progdata = (0 << 18) | (1 << 9) | 0x01,
|
||||
.freq_high = 1177999,
|
||||
.VCOdivider = 4,
|
||||
.progdata = (0 << 19) | (0 << 9) | 0x80,
|
||||
},
|
||||
|
||||
/* band 3 */
|
||||
{
|
||||
.freq_low = 1228000,
|
||||
.freq_high = 1349999,
|
||||
.bandselect = 0x02,
|
||||
.freq_low = 1178000,
|
||||
.freq_high = 1295999,
|
||||
.VCOdivider = 2,
|
||||
.VCOnumber = 2,
|
||||
.progdata = (0 << 18) | (1 << 9) | 0x02,
|
||||
.progdata = (0 << 19) | (1 << 9) | 0x01,
|
||||
},
|
||||
|
||||
/* band 4 */
|
||||
{
|
||||
.freq_low = 1350000,
|
||||
.freq_high = 1481999,
|
||||
.bandselect = 0x04,
|
||||
.freq_low = 1296000,
|
||||
.freq_high = 1431999,
|
||||
.VCOdivider = 2,
|
||||
.VCOnumber = 3,
|
||||
.progdata = (0 << 18) | (1 << 9) | 0x04,
|
||||
.progdata = (0 << 19) | (1 << 9) | 0x02,
|
||||
},
|
||||
|
||||
/* band 5 */
|
||||
{
|
||||
.freq_low = 1482000,
|
||||
.freq_high = 1595999,
|
||||
.bandselect = 0x08,
|
||||
.freq_low = 1432000,
|
||||
.freq_high = 1575999,
|
||||
.VCOdivider = 2,
|
||||
.VCOnumber = 4,
|
||||
.progdata = (0 << 18) | (1 << 9) | 0x08,
|
||||
.progdata = (0 << 19) | (1 << 9) | 0x04,
|
||||
},
|
||||
|
||||
/* band 6 */
|
||||
{
|
||||
.freq_low = 1596000,
|
||||
.freq_low = 1576000,
|
||||
.freq_high = 1717999,
|
||||
.bandselect = 0x10,
|
||||
.VCOdivider = 2,
|
||||
.VCOnumber = 5,
|
||||
.progdata = (0 << 18) | (1 << 9) | 0x10,
|
||||
.progdata = (0 << 19) | (1 << 9) | 0x08,
|
||||
},
|
||||
|
||||
/* band 7 */
|
||||
{
|
||||
.freq_low = 1718000,
|
||||
.freq_high = 1855999,
|
||||
.bandselect = 0x20,
|
||||
.VCOdivider = 2,
|
||||
.VCOnumber = 6,
|
||||
.progdata = (0 << 18) | (1 << 9) | 0x20,
|
||||
.progdata = (0 << 19) | (1 << 9) | 0x10,
|
||||
},
|
||||
|
||||
/* band 8 */
|
||||
{
|
||||
.freq_low = 1856000,
|
||||
.freq_high = 2035999,
|
||||
.bandselect = 0x40,
|
||||
.VCOdivider = 2,
|
||||
.VCOnumber = 7,
|
||||
.progdata = (0 << 18) | (1 << 9) | 0x40,
|
||||
.progdata = (0 << 19) | (1 << 9) | 0x20,
|
||||
},
|
||||
|
||||
/* band 9 */
|
||||
{
|
||||
.freq_low = 2036000,
|
||||
.freq_high = 2149999,
|
||||
.bandselect = 0x80,
|
||||
.freq_high = 2150000,
|
||||
.VCOdivider = 2,
|
||||
.VCOnumber = 8,
|
||||
.progdata = (0 << 18) | (1 << 9) | 0x80,
|
||||
.progdata = (0 << 19) | (1 << 9) | 0x40,
|
||||
},
|
||||
};
|
||||
|
||||
@ -207,49 +190,44 @@ static struct {
|
||||
{
|
||||
{0x00, 0x03}, /* Reset system */
|
||||
{0x00, 0x00}, /* Clear reset */
|
||||
{0x01, 0x3b}, /* Apply sensible defaults, from an i2c sniffer */
|
||||
{0x03, 0x07},
|
||||
{0x04, 0x10},
|
||||
{0x05, 0x04},
|
||||
{0x06, 0x31},
|
||||
{0x0d, 0x02},
|
||||
{0x0e, 0x03},
|
||||
{0x0f, 0xfe},
|
||||
{0x10, 0x01},
|
||||
{0x14, 0x01},
|
||||
{0x15, 0x98},
|
||||
{0x16, 0x00},
|
||||
{0x17, 0x01},
|
||||
{0x1b, 0x05},
|
||||
{0x1c, 0x80},
|
||||
{0x1d, 0x00},
|
||||
{0x1e, 0x00},
|
||||
{0x20, 0x41},
|
||||
{0x21, 0x15},
|
||||
{0x27, 0x14},
|
||||
{0x28, 0x46},
|
||||
{0x29, 0x00},
|
||||
{0x2a, 0xb0},
|
||||
{0x2b, 0x73},
|
||||
{0x2c, 0x00},
|
||||
{0x03, 0x07}, /* QPSK, DVB, Auto Acquisition (default) */
|
||||
{0x04, 0x10}, /* MPEG */
|
||||
{0x05, 0x04}, /* MPEG */
|
||||
{0x06, 0x31}, /* MPEG (default) */
|
||||
{0x0b, 0x00}, /* Freq search start point (default) */
|
||||
{0x0c, 0x00}, /* Demodulator sample gain (default) */
|
||||
{0x0d, 0x02}, /* Frequency search range = Fsymbol / 4 (default) */
|
||||
{0x0e, 0x03}, /* Default non-inverted, FEC 3/4 (default) */
|
||||
{0x0f, 0xfe}, /* FEC search mask (all supported codes) */
|
||||
{0x10, 0x01}, /* Default search inversion, no repeat (default) */
|
||||
{0x16, 0x00}, /* Enable reading of frequency */
|
||||
{0x17, 0x01}, /* Enable EsNO Ready Counter */
|
||||
{0x1c, 0x80}, /* Enable error counter */
|
||||
{0x20, 0x00}, /* Tuner burst clock rate = 500KHz */
|
||||
{0x21, 0x15}, /* Tuner burst mode, word length = 0x15 */
|
||||
{0x28, 0x00}, /* Enable FILTERV with positive pol., DiSEqC 2.x off */
|
||||
{0x29, 0x00}, /* DiSEqC LNB_DC off */
|
||||
{0x2a, 0xb0}, /* DiSEqC Parameters (default) */
|
||||
{0x2b, 0x73}, /* DiSEqC Tone Frequency (default) */
|
||||
{0x2c, 0x00}, /* DiSEqC Message (0x2c - 0x31) */
|
||||
{0x2d, 0x00},
|
||||
{0x2e, 0x00},
|
||||
{0x2f, 0x00},
|
||||
{0x30, 0x00},
|
||||
{0x31, 0x00},
|
||||
{0x32, 0x8c},
|
||||
{0x33, 0x00},
|
||||
{0x32, 0x8c}, /* DiSEqC Parameters (default) */
|
||||
{0x33, 0x00}, /* Interrupts off (0x33 - 0x34) */
|
||||
{0x34, 0x00},
|
||||
{0x35, 0x03},
|
||||
{0x36, 0x02},
|
||||
{0x37, 0x3a},
|
||||
{0x3a, 0x00}, /* Enable AGC accumulator */
|
||||
{0x44, 0x00},
|
||||
{0x45, 0x00},
|
||||
{0x46, 0x05},
|
||||
{0x56, 0x41},
|
||||
{0x57, 0xff},
|
||||
{0x67, 0x83},
|
||||
{0x35, 0x03}, /* DiSEqC Tone Amplitude (default) */
|
||||
{0x36, 0x02}, /* DiSEqC Parameters (default) */
|
||||
{0x37, 0x3a}, /* DiSEqC Parameters (default) */
|
||||
{0x3a, 0x00}, /* Enable AGC accumulator (for signal strength) */
|
||||
{0x44, 0x00}, /* Constellation (default) */
|
||||
{0x45, 0x00}, /* Symbol count (default) */
|
||||
{0x46, 0x0d}, /* Symbol rate estimator on (default) */
|
||||
{0x56, 0x41}, /* Various (default) */
|
||||
{0x57, 0xff}, /* Error Counter Window (default) */
|
||||
{0x67, 0x83}, /* Non-DCII symbol clock */
|
||||
};
|
||||
|
||||
static int cx24123_writereg(struct cx24123_state* state, int reg, int data)
|
||||
@ -258,6 +236,10 @@ static int cx24123_writereg(struct cx24123_state* state, int reg, int data)
|
||||
struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 };
|
||||
int err;
|
||||
|
||||
if (debug>1)
|
||||
printk("cx24123: %s: write reg 0x%02x, value 0x%02x\n",
|
||||
__FUNCTION__,reg, data);
|
||||
|
||||
if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
|
||||
printk("%s: writereg error(err == %i, reg == 0x%02x,"
|
||||
" data == 0x%02x)\n", __FUNCTION__, err, reg, data);
|
||||
@ -274,6 +256,10 @@ static int cx24123_writelnbreg(struct cx24123_state* state, int reg, int data)
|
||||
struct i2c_msg msg = { .addr = 0x08, .flags = 0, .buf = buf, .len = 2 };
|
||||
int err;
|
||||
|
||||
if (debug>1)
|
||||
printk("cx24123: %s: writeln addr=0x08, reg 0x%02x, value 0x%02x\n",
|
||||
__FUNCTION__,reg, data);
|
||||
|
||||
if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
|
||||
printk("%s: writelnbreg error (err == %i, reg == 0x%02x,"
|
||||
" data == 0x%02x)\n", __FUNCTION__, err, reg, data);
|
||||
@ -303,6 +289,9 @@ static int cx24123_readreg(struct cx24123_state* state, u8 reg)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (debug>1)
|
||||
printk("cx24123: read reg 0x%02x, value 0x%02x\n",reg, ret);
|
||||
|
||||
return b1[0];
|
||||
}
|
||||
|
||||
@ -313,17 +302,23 @@ static int cx24123_readlnbreg(struct cx24123_state* state, u8 reg)
|
||||
|
||||
static int cx24123_set_inversion(struct cx24123_state* state, fe_spectral_inversion_t inversion)
|
||||
{
|
||||
u8 nom_reg = cx24123_readreg(state, 0x0e);
|
||||
u8 auto_reg = cx24123_readreg(state, 0x10);
|
||||
|
||||
switch (inversion) {
|
||||
case INVERSION_OFF:
|
||||
cx24123_writereg(state, 0x0e, cx24123_readreg(state, 0x0e) & 0x7f);
|
||||
cx24123_writereg(state, 0x10, cx24123_readreg(state, 0x10) | 0x80);
|
||||
dprintk("%s: inversion off\n",__FUNCTION__);
|
||||
cx24123_writereg(state, 0x0e, nom_reg & ~0x80);
|
||||
cx24123_writereg(state, 0x10, auto_reg | 0x80);
|
||||
break;
|
||||
case INVERSION_ON:
|
||||
cx24123_writereg(state, 0x0e, cx24123_readreg(state, 0x0e) | 0x80);
|
||||
cx24123_writereg(state, 0x10, cx24123_readreg(state, 0x10) | 0x80);
|
||||
dprintk("%s: inversion on\n",__FUNCTION__);
|
||||
cx24123_writereg(state, 0x0e, nom_reg | 0x80);
|
||||
cx24123_writereg(state, 0x10, auto_reg | 0x80);
|
||||
break;
|
||||
case INVERSION_AUTO:
|
||||
cx24123_writereg(state, 0x10, cx24123_readreg(state, 0x10) & 0x7f);
|
||||
dprintk("%s: inversion auto\n",__FUNCTION__);
|
||||
cx24123_writereg(state, 0x10, auto_reg & ~0x80);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
@ -338,92 +333,191 @@ static int cx24123_get_inversion(struct cx24123_state* state, fe_spectral_invers
|
||||
|
||||
val = cx24123_readreg(state, 0x1b) >> 7;
|
||||
|
||||
if (val == 0)
|
||||
if (val == 0) {
|
||||
dprintk("%s: read inversion off\n",__FUNCTION__);
|
||||
*inversion = INVERSION_OFF;
|
||||
else
|
||||
} else {
|
||||
dprintk("%s: read inversion on\n",__FUNCTION__);
|
||||
*inversion = INVERSION_ON;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cx24123_set_fec(struct cx24123_state* state, fe_code_rate_t fec)
|
||||
{
|
||||
u8 nom_reg = cx24123_readreg(state, 0x0e) & ~0x07;
|
||||
|
||||
if ( (fec < FEC_NONE) || (fec > FEC_AUTO) )
|
||||
fec = FEC_AUTO;
|
||||
|
||||
/* Hardware has 5/11 and 3/5 but are never unused */
|
||||
switch (fec) {
|
||||
case FEC_NONE:
|
||||
return cx24123_writereg(state, 0x0f, 0x01);
|
||||
case FEC_1_2:
|
||||
return cx24123_writereg(state, 0x0f, 0x02);
|
||||
dprintk("%s: set FEC to 1/2\n",__FUNCTION__);
|
||||
cx24123_writereg(state, 0x0e, nom_reg | 0x01);
|
||||
cx24123_writereg(state, 0x0f, 0x02);
|
||||
break;
|
||||
case FEC_2_3:
|
||||
return cx24123_writereg(state, 0x0f, 0x04);
|
||||
dprintk("%s: set FEC to 2/3\n",__FUNCTION__);
|
||||
cx24123_writereg(state, 0x0e, nom_reg | 0x02);
|
||||
cx24123_writereg(state, 0x0f, 0x04);
|
||||
break;
|
||||
case FEC_3_4:
|
||||
return cx24123_writereg(state, 0x0f, 0x08);
|
||||
dprintk("%s: set FEC to 3/4\n",__FUNCTION__);
|
||||
cx24123_writereg(state, 0x0e, nom_reg | 0x03);
|
||||
cx24123_writereg(state, 0x0f, 0x08);
|
||||
break;
|
||||
case FEC_4_5:
|
||||
dprintk("%s: set FEC to 4/5\n",__FUNCTION__);
|
||||
cx24123_writereg(state, 0x0e, nom_reg | 0x04);
|
||||
cx24123_writereg(state, 0x0f, 0x10);
|
||||
break;
|
||||
case FEC_5_6:
|
||||
return cx24123_writereg(state, 0x0f, 0x20);
|
||||
dprintk("%s: set FEC to 5/6\n",__FUNCTION__);
|
||||
cx24123_writereg(state, 0x0e, nom_reg | 0x05);
|
||||
cx24123_writereg(state, 0x0f, 0x20);
|
||||
break;
|
||||
case FEC_6_7:
|
||||
dprintk("%s: set FEC to 6/7\n",__FUNCTION__);
|
||||
cx24123_writereg(state, 0x0e, nom_reg | 0x06);
|
||||
cx24123_writereg(state, 0x0f, 0x40);
|
||||
break;
|
||||
case FEC_7_8:
|
||||
return cx24123_writereg(state, 0x0f, 0x80);
|
||||
dprintk("%s: set FEC to 7/8\n",__FUNCTION__);
|
||||
cx24123_writereg(state, 0x0e, nom_reg | 0x07);
|
||||
cx24123_writereg(state, 0x0f, 0x80);
|
||||
break;
|
||||
case FEC_AUTO:
|
||||
return cx24123_writereg(state, 0x0f, 0xae);
|
||||
dprintk("%s: set FEC to auto\n",__FUNCTION__);
|
||||
cx24123_writereg(state, 0x0f, 0xfe);
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
}
|
||||
|
||||
static int cx24123_get_fec(struct cx24123_state* state, fe_code_rate_t *fec)
|
||||
{
|
||||
int ret;
|
||||
u8 val;
|
||||
|
||||
ret = cx24123_readreg (state, 0x1b);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
val = ret & 0x07;
|
||||
switch (val) {
|
||||
case 1:
|
||||
*fec = FEC_1_2;
|
||||
break;
|
||||
case 3:
|
||||
*fec = FEC_2_3;
|
||||
break;
|
||||
case 4:
|
||||
*fec = FEC_3_4;
|
||||
break;
|
||||
case 5:
|
||||
*fec = FEC_4_5;
|
||||
break;
|
||||
case 6:
|
||||
*fec = FEC_5_6;
|
||||
break;
|
||||
case 7:
|
||||
*fec = FEC_7_8;
|
||||
break;
|
||||
case 2: /* *fec = FEC_3_5; break; */
|
||||
case 0: /* *fec = FEC_5_11; break; */
|
||||
*fec = FEC_AUTO;
|
||||
break;
|
||||
default:
|
||||
*fec = FEC_NONE; // can't happen
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* fixme: Symbol rates < 3MSps may not work because of precision loss */
|
||||
static int cx24123_get_fec(struct cx24123_state* state, fe_code_rate_t *fec)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = cx24123_readreg (state, 0x1b);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = ret & 0x07;
|
||||
|
||||
switch (ret) {
|
||||
case 1:
|
||||
*fec = FEC_1_2;
|
||||
break;
|
||||
case 2:
|
||||
*fec = FEC_2_3;
|
||||
break;
|
||||
case 3:
|
||||
*fec = FEC_3_4;
|
||||
break;
|
||||
case 4:
|
||||
*fec = FEC_4_5;
|
||||
break;
|
||||
case 5:
|
||||
*fec = FEC_5_6;
|
||||
break;
|
||||
case 6:
|
||||
*fec = FEC_6_7;
|
||||
break;
|
||||
case 7:
|
||||
*fec = FEC_7_8;
|
||||
break;
|
||||
default:
|
||||
/* this can happen when there's no lock */
|
||||
*fec = FEC_NONE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Approximation of closest integer of log2(a/b). It actually gives the
|
||||
lowest integer i such that 2^i >= round(a/b) */
|
||||
static u32 cx24123_int_log2(u32 a, u32 b)
|
||||
{
|
||||
u32 exp, nearest = 0;
|
||||
u32 div = a / b;
|
||||
if(a % b >= b / 2) ++div;
|
||||
if(div < (1 << 31))
|
||||
{
|
||||
for(exp = 1; div > exp; nearest++)
|
||||
exp += exp;
|
||||
}
|
||||
return nearest;
|
||||
}
|
||||
|
||||
static int cx24123_set_symbolrate(struct cx24123_state* state, u32 srate)
|
||||
{
|
||||
u32 val;
|
||||
u32 tmp, sample_rate, ratio, sample_gain;
|
||||
u8 pll_mult;
|
||||
|
||||
val = (srate / 1185) * 100;
|
||||
/* check if symbol rate is within limits */
|
||||
if ((srate > state->ops.info.symbol_rate_max) ||
|
||||
(srate < state->ops.info.symbol_rate_min))
|
||||
return -EOPNOTSUPP;;
|
||||
|
||||
/* Compensate for scaling up, by removing 17 symbols per 1Msps */
|
||||
val = val - (17 * (srate / 1000000));
|
||||
/* choose the sampling rate high enough for the required operation,
|
||||
while optimizing the power consumed by the demodulator */
|
||||
if (srate < (XTAL*2)/2)
|
||||
pll_mult = 2;
|
||||
else if (srate < (XTAL*3)/2)
|
||||
pll_mult = 3;
|
||||
else if (srate < (XTAL*4)/2)
|
||||
pll_mult = 4;
|
||||
else if (srate < (XTAL*5)/2)
|
||||
pll_mult = 5;
|
||||
else if (srate < (XTAL*6)/2)
|
||||
pll_mult = 6;
|
||||
else if (srate < (XTAL*7)/2)
|
||||
pll_mult = 7;
|
||||
else if (srate < (XTAL*8)/2)
|
||||
pll_mult = 8;
|
||||
else
|
||||
pll_mult = 9;
|
||||
|
||||
cx24123_writereg(state, 0x08, (val >> 16) & 0xff );
|
||||
cx24123_writereg(state, 0x09, (val >> 8) & 0xff );
|
||||
cx24123_writereg(state, 0x0a, (val ) & 0xff );
|
||||
|
||||
sample_rate = pll_mult * XTAL;
|
||||
|
||||
/*
|
||||
SYSSymbolRate[21:0] = (srate << 23) / sample_rate
|
||||
|
||||
We have to use 32 bit unsigned arithmetic without precision loss.
|
||||
The maximum srate is 45000000 or 0x02AEA540. This number has
|
||||
only 6 clear bits on top, hence we can shift it left only 6 bits
|
||||
at a time. Borrowed from cx24110.c
|
||||
*/
|
||||
|
||||
tmp = srate << 6;
|
||||
ratio = tmp / sample_rate;
|
||||
|
||||
tmp = (tmp % sample_rate) << 6;
|
||||
ratio = (ratio << 6) + (tmp / sample_rate);
|
||||
|
||||
tmp = (tmp % sample_rate) << 6;
|
||||
ratio = (ratio << 6) + (tmp / sample_rate);
|
||||
|
||||
tmp = (tmp % sample_rate) << 5;
|
||||
ratio = (ratio << 5) + (tmp / sample_rate);
|
||||
|
||||
|
||||
cx24123_writereg(state, 0x01, pll_mult * 6);
|
||||
|
||||
cx24123_writereg(state, 0x08, (ratio >> 16) & 0x3f );
|
||||
cx24123_writereg(state, 0x09, (ratio >> 8) & 0xff );
|
||||
cx24123_writereg(state, 0x0a, (ratio ) & 0xff );
|
||||
|
||||
/* also set the demodulator sample gain */
|
||||
sample_gain = cx24123_int_log2(sample_rate, srate);
|
||||
tmp = cx24123_readreg(state, 0x0c) & ~0xe0;
|
||||
cx24123_writereg(state, 0x0c, tmp | sample_gain << 5);
|
||||
|
||||
dprintk("%s: srate=%d, ratio=0x%08x, sample_rate=%i sample_gain=%d\n", __FUNCTION__, srate, ratio, sample_rate, sample_gain);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -437,6 +531,9 @@ static int cx24123_pll_calculate(struct dvb_frontend* fe, struct dvb_frontend_pa
|
||||
struct cx24123_state *state = fe->demodulator_priv;
|
||||
u32 ndiv = 0, adiv = 0, vco_div = 0;
|
||||
int i = 0;
|
||||
int pump = 2;
|
||||
int band = 0;
|
||||
int num_bands = sizeof(cx24123_bandselect_vals) / sizeof(cx24123_bandselect_vals[0]);
|
||||
|
||||
/* Defaults for low freq, low rate */
|
||||
state->VCAarg = cx24123_AGC_vals[0].VCAprogdata;
|
||||
@ -444,38 +541,49 @@ static int cx24123_pll_calculate(struct dvb_frontend* fe, struct dvb_frontend_pa
|
||||
state->bandselectarg = cx24123_bandselect_vals[0].progdata;
|
||||
vco_div = cx24123_bandselect_vals[0].VCOdivider;
|
||||
|
||||
/* For the given symbolerate, determine the VCA and VGA programming bits */
|
||||
/* For the given symbol rate, determine the VCA, VGA and FILTUNE programming bits */
|
||||
for (i = 0; i < sizeof(cx24123_AGC_vals) / sizeof(cx24123_AGC_vals[0]); i++)
|
||||
{
|
||||
if ((cx24123_AGC_vals[i].symbolrate_low <= p->u.qpsk.symbol_rate) &&
|
||||
(cx24123_AGC_vals[i].symbolrate_high >= p->u.qpsk.symbol_rate) ) {
|
||||
(cx24123_AGC_vals[i].symbolrate_high >= p->u.qpsk.symbol_rate) ) {
|
||||
state->VCAarg = cx24123_AGC_vals[i].VCAprogdata;
|
||||
state->VGAarg = cx24123_AGC_vals[i].VGAprogdata;
|
||||
state->FILTune = cx24123_AGC_vals[i].FILTune;
|
||||
}
|
||||
}
|
||||
|
||||
/* For the given frequency, determine the bandselect programming bits */
|
||||
for (i = 0; i < sizeof(cx24123_bandselect_vals) / sizeof(cx24123_bandselect_vals[0]); i++)
|
||||
/* determine the band to use */
|
||||
if(force_band < 1 || force_band > num_bands)
|
||||
{
|
||||
if ((cx24123_bandselect_vals[i].freq_low <= p->frequency) &&
|
||||
(cx24123_bandselect_vals[i].freq_high >= p->frequency) ) {
|
||||
state->bandselectarg = cx24123_bandselect_vals[i].progdata;
|
||||
vco_div = cx24123_bandselect_vals[i].VCOdivider;
|
||||
for (i = 0; i < num_bands; i++)
|
||||
{
|
||||
if ((cx24123_bandselect_vals[i].freq_low <= p->frequency) &&
|
||||
(cx24123_bandselect_vals[i].freq_high >= p->frequency) )
|
||||
band = i;
|
||||
}
|
||||
}
|
||||
else
|
||||
band = force_band - 1;
|
||||
|
||||
state->bandselectarg = cx24123_bandselect_vals[band].progdata;
|
||||
vco_div = cx24123_bandselect_vals[band].VCOdivider;
|
||||
|
||||
/* determine the charge pump current */
|
||||
if ( p->frequency < (cx24123_bandselect_vals[band].freq_low + cx24123_bandselect_vals[band].freq_high)/2 )
|
||||
pump = 0x01;
|
||||
else
|
||||
pump = 0x02;
|
||||
|
||||
/* Determine the N/A dividers for the requested lband freq (in kHz). */
|
||||
/* Note: 10111 (kHz) is the Crystal Freq and divider of 10. */
|
||||
ndiv = ( ((p->frequency * vco_div) / (10111 / 10) / 2) / 32) & 0x1ff;
|
||||
adiv = ( ((p->frequency * vco_div) / (10111 / 10) / 2) % 32) & 0x1f;
|
||||
/* Note: the reference divider R=10, frequency is in KHz, XTAL is in Hz */
|
||||
ndiv = ( ((p->frequency * vco_div * 10) / (2 * XTAL / 1000)) / 32) & 0x1ff;
|
||||
adiv = ( ((p->frequency * vco_div * 10) / (2 * XTAL / 1000)) % 32) & 0x1f;
|
||||
|
||||
if (adiv == 0)
|
||||
adiv++;
|
||||
ndiv++;
|
||||
|
||||
/* determine the correct pll frequency values. */
|
||||
/* Command 11, refdiv 11, cpump polarity 1, cpump current 3mA 10. */
|
||||
state->pllarg = (3 << 19) | (3 << 17) | (1 << 16) | (2 << 14);
|
||||
state->pllarg |= (ndiv << 5) | adiv;
|
||||
/* control bits 11, refdiv 11, charge pump polarity 1, charge pump current, ndiv, adiv */
|
||||
state->pllarg = (3 << 19) | (3 << 17) | (1 << 16) | (pump << 14) | (ndiv << 5) | adiv;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -489,6 +597,8 @@ static int cx24123_pll_writereg(struct dvb_frontend* fe, struct dvb_frontend_par
|
||||
struct cx24123_state *state = fe->demodulator_priv;
|
||||
unsigned long timeout;
|
||||
|
||||
dprintk("%s: pll writereg called, data=0x%08x\n",__FUNCTION__,data);
|
||||
|
||||
/* align the 21 bytes into to bit23 boundary */
|
||||
data = data << 3;
|
||||
|
||||
@ -538,6 +648,9 @@ static int cx24123_pll_writereg(struct dvb_frontend* fe, struct dvb_frontend_par
|
||||
static int cx24123_pll_tune(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
|
||||
{
|
||||
struct cx24123_state *state = fe->demodulator_priv;
|
||||
u8 val;
|
||||
|
||||
dprintk("frequency=%i\n", p->frequency);
|
||||
|
||||
if (cx24123_pll_calculate(fe, p) != 0) {
|
||||
printk("%s: cx24123_pll_calcutate failed\n",__FUNCTION__);
|
||||
@ -552,6 +665,14 @@ static int cx24123_pll_tune(struct dvb_frontend* fe, struct dvb_frontend_paramet
|
||||
cx24123_pll_writereg(fe, p, state->bandselectarg);
|
||||
cx24123_pll_writereg(fe, p, state->pllarg);
|
||||
|
||||
/* set the FILTUNE voltage */
|
||||
val = cx24123_readreg(state, 0x28) & ~0x3;
|
||||
cx24123_writereg(state, 0x27, state->FILTune >> 2);
|
||||
cx24123_writereg(state, 0x28, val | (state->FILTune & 0x3));
|
||||
|
||||
dprintk("%s: pll tune VCA=%d, band=%d, pll=%d\n",__FUNCTION__,state->VCAarg,
|
||||
state->bandselectarg,state->pllarg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -560,6 +681,8 @@ static int cx24123_initfe(struct dvb_frontend* fe)
|
||||
struct cx24123_state *state = fe->demodulator_priv;
|
||||
int i;
|
||||
|
||||
dprintk("%s: init frontend\n",__FUNCTION__);
|
||||
|
||||
/* Configure the demod to a good set of defaults */
|
||||
for (i = 0; i < sizeof(cx24123_regdata) / sizeof(cx24123_regdata[0]); i++)
|
||||
cx24123_writereg(state, cx24123_regdata[i].reg, cx24123_regdata[i].data);
|
||||
@ -587,10 +710,13 @@ static int cx24123_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage
|
||||
|
||||
switch (voltage) {
|
||||
case SEC_VOLTAGE_13:
|
||||
dprintk("%s: isl6421 voltage = 13V\n",__FUNCTION__);
|
||||
return cx24123_writelnbreg(state, 0x0, val & 0x32); /* V 13v */
|
||||
case SEC_VOLTAGE_18:
|
||||
dprintk("%s: isl6421 voltage = 18V\n",__FUNCTION__);
|
||||
return cx24123_writelnbreg(state, 0x0, val | 0x04); /* H 18v */
|
||||
case SEC_VOLTAGE_OFF:
|
||||
dprintk("%s: isl5421 voltage off\n",__FUNCTION__);
|
||||
return cx24123_writelnbreg(state, 0x0, val & 0x30);
|
||||
default:
|
||||
return -EINVAL;
|
||||
@ -624,13 +750,93 @@ static int cx24123_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cx24123_send_diseqc_msg(struct dvb_frontend* fe,
|
||||
struct dvb_diseqc_master_cmd *cmd)
|
||||
/* wait for diseqc queue to become ready (or timeout) */
|
||||
static void cx24123_wait_for_diseqc(struct cx24123_state *state)
|
||||
{
|
||||
/* fixme: Implement diseqc */
|
||||
printk("%s: No support yet\n",__FUNCTION__);
|
||||
unsigned long timeout = jiffies + msecs_to_jiffies(200);
|
||||
while (!(cx24123_readreg(state, 0x29) & 0x40)) {
|
||||
if(time_after(jiffies, timeout)) {
|
||||
printk("%s: diseqc queue not ready, command may be lost.\n", __FUNCTION__);
|
||||
break;
|
||||
}
|
||||
msleep(10);
|
||||
}
|
||||
}
|
||||
|
||||
return -ENOTSUPP;
|
||||
static int cx24123_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd *cmd)
|
||||
{
|
||||
struct cx24123_state *state = fe->demodulator_priv;
|
||||
int i, val;
|
||||
|
||||
dprintk("%s:\n",__FUNCTION__);
|
||||
|
||||
/* check if continuous tone has been stopped */
|
||||
if (state->config->use_isl6421)
|
||||
val = cx24123_readlnbreg(state, 0x00) & 0x10;
|
||||
else
|
||||
val = cx24123_readreg(state, 0x29) & 0x10;
|
||||
|
||||
|
||||
if (val) {
|
||||
printk("%s: ERROR: attempt to send diseqc command before tone is off\n", __FUNCTION__);
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
/* wait for diseqc queue ready */
|
||||
cx24123_wait_for_diseqc(state);
|
||||
|
||||
/* select tone mode */
|
||||
cx24123_writereg(state, 0x2a, cx24123_readreg(state, 0x2a) & 0xf8);
|
||||
|
||||
for (i = 0; i < cmd->msg_len; i++)
|
||||
cx24123_writereg(state, 0x2C + i, cmd->msg[i]);
|
||||
|
||||
val = cx24123_readreg(state, 0x29);
|
||||
cx24123_writereg(state, 0x29, ((val & 0x90) | 0x40) | ((cmd->msg_len-3) & 3));
|
||||
|
||||
/* wait for diseqc message to finish sending */
|
||||
cx24123_wait_for_diseqc(state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cx24123_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t burst)
|
||||
{
|
||||
struct cx24123_state *state = fe->demodulator_priv;
|
||||
int val;
|
||||
|
||||
dprintk("%s:\n", __FUNCTION__);
|
||||
|
||||
/* check if continuous tone has been stoped */
|
||||
if (state->config->use_isl6421)
|
||||
val = cx24123_readlnbreg(state, 0x00) & 0x10;
|
||||
else
|
||||
val = cx24123_readreg(state, 0x29) & 0x10;
|
||||
|
||||
|
||||
if (val) {
|
||||
printk("%s: ERROR: attempt to send diseqc command before tone is off\n", __FUNCTION__);
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
cx24123_wait_for_diseqc(state);
|
||||
|
||||
/* select tone mode */
|
||||
val = cx24123_readreg(state, 0x2a) & 0xf8;
|
||||
cx24123_writereg(state, 0x2a, val | 0x04);
|
||||
|
||||
val = cx24123_readreg(state, 0x29);
|
||||
|
||||
if (burst == SEC_MINI_A)
|
||||
cx24123_writereg(state, 0x29, ((val & 0x90) | 0x40 | 0x00));
|
||||
else if (burst == SEC_MINI_B)
|
||||
cx24123_writereg(state, 0x29, ((val & 0x90) | 0x40 | 0x08));
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
cx24123_wait_for_diseqc(state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cx24123_read_status(struct dvb_frontend* fe, fe_status_t* status)
|
||||
@ -642,13 +848,15 @@ static int cx24123_read_status(struct dvb_frontend* fe, fe_status_t* status)
|
||||
|
||||
*status = 0;
|
||||
if (lock & 0x01)
|
||||
*status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
|
||||
*status |= FE_HAS_SIGNAL;
|
||||
if (sync & 0x02)
|
||||
*status |= FE_HAS_CARRIER;
|
||||
if (sync & 0x04)
|
||||
*status |= FE_HAS_VITERBI;
|
||||
if (sync & 0x08)
|
||||
*status |= FE_HAS_CARRIER;
|
||||
*status |= FE_HAS_SYNC;
|
||||
if (sync & 0x80)
|
||||
*status |= FE_HAS_SYNC | FE_HAS_LOCK;
|
||||
*status |= FE_HAS_LOCK;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -681,6 +889,8 @@ static int cx24123_read_ber(struct dvb_frontend* fe, u32* ber)
|
||||
else
|
||||
state->snr = 0;
|
||||
|
||||
dprintk("%s: BER = %d, S/N index = %d\n",__FUNCTION__,state->lastber, state->snr);
|
||||
|
||||
*ber = state->lastber;
|
||||
|
||||
return 0;
|
||||
@ -691,6 +901,8 @@ static int cx24123_read_signal_strength(struct dvb_frontend* fe, u16* signal_str
|
||||
struct cx24123_state *state = fe->demodulator_priv;
|
||||
*signal_strength = cx24123_readreg(state, 0x3b) << 8; /* larger = better */
|
||||
|
||||
dprintk("%s: Signal strength = %d\n",__FUNCTION__,*signal_strength);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -699,6 +911,8 @@ static int cx24123_read_snr(struct dvb_frontend* fe, u16* snr)
|
||||
struct cx24123_state *state = fe->demodulator_priv;
|
||||
*snr = state->snr;
|
||||
|
||||
dprintk("%s: read S/N index = %d\n",__FUNCTION__,*snr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -707,6 +921,8 @@ static int cx24123_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
|
||||
struct cx24123_state *state = fe->demodulator_priv;
|
||||
*ucblocks = state->lastber;
|
||||
|
||||
dprintk("%s: ucblocks (ber) = %d\n",__FUNCTION__,*ucblocks);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -714,6 +930,8 @@ static int cx24123_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
|
||||
{
|
||||
struct cx24123_state *state = fe->demodulator_priv;
|
||||
|
||||
dprintk("%s: set_frontend\n",__FUNCTION__);
|
||||
|
||||
if (state->config->set_ts_params)
|
||||
state->config->set_ts_params(fe, 0);
|
||||
|
||||
@ -737,6 +955,8 @@ static int cx24123_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
|
||||
{
|
||||
struct cx24123_state *state = fe->demodulator_priv;
|
||||
|
||||
dprintk("%s: get_frontend\n",__FUNCTION__);
|
||||
|
||||
if (cx24123_get_inversion(state, &p->inversion) != 0) {
|
||||
printk("%s: Failed to get inversion status\n",__FUNCTION__);
|
||||
return -EREMOTEIO;
|
||||
@ -763,8 +983,10 @@ static int cx24123_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
|
||||
|
||||
switch (tone) {
|
||||
case SEC_TONE_ON:
|
||||
dprintk("%s: isl6421 sec tone on\n",__FUNCTION__);
|
||||
return cx24123_writelnbreg(state, 0x0, val | 0x10);
|
||||
case SEC_TONE_OFF:
|
||||
dprintk("%s: isl6421 sec tone off\n",__FUNCTION__);
|
||||
return cx24123_writelnbreg(state, 0x0, val & 0x2f);
|
||||
default:
|
||||
printk("%s: CASE reached default with tone=%d\n", __FUNCTION__, tone);
|
||||
@ -855,12 +1077,13 @@ static struct dvb_frontend_ops cx24123_ops = {
|
||||
.frequency_min = 950000,
|
||||
.frequency_max = 2150000,
|
||||
.frequency_stepsize = 1011, /* kHz for QPSK frontends */
|
||||
.frequency_tolerance = 29500,
|
||||
.frequency_tolerance = 5000,
|
||||
.symbol_rate_min = 1000000,
|
||||
.symbol_rate_max = 45000000,
|
||||
.caps = FE_CAN_INVERSION_AUTO |
|
||||
FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
|
||||
FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
|
||||
FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |
|
||||
FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
|
||||
FE_CAN_QPSK | FE_CAN_RECOVER
|
||||
},
|
||||
|
||||
@ -875,12 +1098,16 @@ static struct dvb_frontend_ops cx24123_ops = {
|
||||
.read_snr = cx24123_read_snr,
|
||||
.read_ucblocks = cx24123_read_ucblocks,
|
||||
.diseqc_send_master_cmd = cx24123_send_diseqc_msg,
|
||||
.diseqc_send_burst = cx24123_diseqc_send_burst,
|
||||
.set_tone = cx24123_set_tone,
|
||||
.set_voltage = cx24123_set_voltage,
|
||||
};
|
||||
|
||||
module_param(debug, int, 0644);
|
||||
MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
|
||||
MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)");
|
||||
|
||||
module_param(force_band, int, 0644);
|
||||
MODULE_PARM_DESC(force_band, "Force a specific band select (1-9, default:off).");
|
||||
|
||||
MODULE_DESCRIPTION("DVB Frontend module for Conexant cx24123/cx24109 hardware");
|
||||
MODULE_AUTHOR("Steven Toth");
|
||||
|
@ -235,8 +235,8 @@ struct dvb_pll_desc dvb_pll_tdvs_tua6034 = {
|
||||
.max = 863000000,
|
||||
.count = 3,
|
||||
.entries = {
|
||||
{ 160000000, 44000000, 62500, 0xce, 0x01 },
|
||||
{ 455000000, 44000000, 62500, 0xce, 0x02 },
|
||||
{ 165000000, 44000000, 62500, 0xce, 0x01 },
|
||||
{ 450000000, 44000000, 62500, 0xce, 0x02 },
|
||||
{ 999999999, 44000000, 62500, 0xce, 0x04 },
|
||||
},
|
||||
};
|
||||
|
@ -1,3 +1,3 @@
|
||||
obj-$(CONFIG_DVB_PLUTO2) = pluto2.o
|
||||
obj-$(CONFIG_DVB_PLUTO2) += pluto2.o
|
||||
|
||||
EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
|
||||
|
@ -1,8 +1,7 @@
|
||||
config DVB_AV7110
|
||||
tristate "AV7110 cards"
|
||||
depends on DVB_CORE && PCI
|
||||
depends on DVB_CORE && PCI && VIDEO_V4L1
|
||||
select FW_LOADER
|
||||
select VIDEO_DEV
|
||||
select VIDEO_SAA7146_VV
|
||||
select DVB_VES1820
|
||||
select DVB_VES1X93
|
||||
@ -59,7 +58,7 @@ config DVB_AV7110_OSD
|
||||
|
||||
config DVB_BUDGET
|
||||
tristate "Budget cards"
|
||||
depends on DVB_CORE && PCI
|
||||
depends on DVB_CORE && PCI && VIDEO_V4L1
|
||||
select VIDEO_SAA7146
|
||||
select DVB_STV0299
|
||||
select DVB_VES1X93
|
||||
@ -80,7 +79,7 @@ config DVB_BUDGET
|
||||
|
||||
config DVB_BUDGET_CI
|
||||
tristate "Budget cards with onboard CI connector"
|
||||
depends on DVB_CORE && PCI
|
||||
depends on DVB_CORE && PCI && VIDEO_V4L1
|
||||
select VIDEO_SAA7146
|
||||
select DVB_STV0297
|
||||
select DVB_STV0299
|
||||
@ -100,8 +99,7 @@ config DVB_BUDGET_CI
|
||||
|
||||
config DVB_BUDGET_AV
|
||||
tristate "Budget cards with analog video inputs"
|
||||
depends on DVB_CORE && PCI
|
||||
select VIDEO_DEV
|
||||
depends on DVB_CORE && PCI && VIDEO_V4L1
|
||||
select VIDEO_SAA7146_VV
|
||||
select DVB_STV0299
|
||||
select DVB_TDA1004X
|
||||
@ -119,7 +117,7 @@ config DVB_BUDGET_AV
|
||||
|
||||
config DVB_BUDGET_PATCH
|
||||
tristate "AV7110 cards with Budget Patch"
|
||||
depends on DVB_CORE && DVB_BUDGET
|
||||
depends on DVB_CORE && DVB_BUDGET && VIDEO_V4L1
|
||||
select DVB_AV7110
|
||||
select DVB_STV0299
|
||||
select DVB_VES1X93
|
||||
|
@ -1190,8 +1190,6 @@ static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio
|
||||
SAA7146_HPS_SYNC_PORT_A);
|
||||
|
||||
saa7113_setinput(budget_av, 0);
|
||||
} else {
|
||||
ciintf_init(budget_av);
|
||||
}
|
||||
|
||||
/* fixme: find some sane values here... */
|
||||
@ -1211,6 +1209,10 @@ static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio
|
||||
budget_av->budget.dvb_adapter.priv = budget_av;
|
||||
frontend_init(budget_av);
|
||||
|
||||
if (!budget_av->has_saa7113) {
|
||||
ciintf_init(budget_av);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -71,6 +71,7 @@ struct budget_ci {
|
||||
struct tasklet_struct msp430_irq_tasklet;
|
||||
struct tasklet_struct ciintf_irq_tasklet;
|
||||
int slot_status;
|
||||
int ci_irq;
|
||||
struct dvb_ca_en50221 ca;
|
||||
char ir_dev_name[50];
|
||||
u8 tuner_pll_address; /* used for philips_tdm1316l configs */
|
||||
@ -276,8 +277,10 @@ static int ciintf_slot_reset(struct dvb_ca_en50221 *ca, int slot)
|
||||
if (slot != 0)
|
||||
return -EINVAL;
|
||||
|
||||
// trigger on RISING edge during reset so we know when READY is re-asserted
|
||||
saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI);
|
||||
if (budget_ci->ci_irq) {
|
||||
// trigger on RISING edge during reset so we know when READY is re-asserted
|
||||
saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI);
|
||||
}
|
||||
budget_ci->slot_status = SLOTSTATUS_RESET;
|
||||
ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 0, 1, 0);
|
||||
msleep(1);
|
||||
@ -370,11 +373,50 @@ static void ciintf_interrupt(unsigned long data)
|
||||
}
|
||||
}
|
||||
|
||||
static int ciintf_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open)
|
||||
{
|
||||
struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
|
||||
unsigned int flags;
|
||||
|
||||
// ensure we don't get spurious IRQs during initialisation
|
||||
if (!budget_ci->budget.ci_present)
|
||||
return -EINVAL;
|
||||
|
||||
// read the CAM status
|
||||
flags = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);
|
||||
if (flags & CICONTROL_CAMDETECT) {
|
||||
// mark it as present if it wasn't before
|
||||
if (budget_ci->slot_status & SLOTSTATUS_NONE) {
|
||||
budget_ci->slot_status = SLOTSTATUS_PRESENT;
|
||||
}
|
||||
|
||||
// during a RESET, we check if we can read from IO memory to see when CAM is ready
|
||||
if (budget_ci->slot_status & SLOTSTATUS_RESET) {
|
||||
if (ciintf_read_attribute_mem(ca, slot, 0) == 0x1d) {
|
||||
budget_ci->slot_status = SLOTSTATUS_READY;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
budget_ci->slot_status = SLOTSTATUS_NONE;
|
||||
}
|
||||
|
||||
if (budget_ci->slot_status != SLOTSTATUS_NONE) {
|
||||
if (budget_ci->slot_status & SLOTSTATUS_READY) {
|
||||
return DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY;
|
||||
}
|
||||
return DVB_CA_EN50221_POLL_CAM_PRESENT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ciintf_init(struct budget_ci *budget_ci)
|
||||
{
|
||||
struct saa7146_dev *saa = budget_ci->budget.dev;
|
||||
int flags;
|
||||
int result;
|
||||
int ci_version;
|
||||
int ca_flags;
|
||||
|
||||
memset(&budget_ci->ca, 0, sizeof(struct dvb_ca_en50221));
|
||||
|
||||
@ -382,16 +424,29 @@ static int ciintf_init(struct budget_ci *budget_ci)
|
||||
saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16) | 0x800);
|
||||
|
||||
// test if it is there
|
||||
if ((ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CIVERSION, 1, 1, 0) & 0xa0) != 0xa0) {
|
||||
ci_version = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CIVERSION, 1, 1, 0);
|
||||
if ((ci_version & 0xa0) != 0xa0) {
|
||||
result = -ENODEV;
|
||||
goto error;
|
||||
}
|
||||
|
||||
// determine whether a CAM is present or not
|
||||
flags = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);
|
||||
budget_ci->slot_status = SLOTSTATUS_NONE;
|
||||
if (flags & CICONTROL_CAMDETECT)
|
||||
budget_ci->slot_status = SLOTSTATUS_PRESENT;
|
||||
|
||||
// version 0xa2 of the CI firmware doesn't generate interrupts
|
||||
if (ci_version == 0xa2) {
|
||||
ca_flags = 0;
|
||||
budget_ci->ci_irq = 0;
|
||||
} else {
|
||||
ca_flags = DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE |
|
||||
DVB_CA_EN50221_FLAG_IRQ_FR |
|
||||
DVB_CA_EN50221_FLAG_IRQ_DA;
|
||||
budget_ci->ci_irq = 1;
|
||||
}
|
||||
|
||||
// register CI interface
|
||||
budget_ci->ca.owner = THIS_MODULE;
|
||||
budget_ci->ca.read_attribute_mem = ciintf_read_attribute_mem;
|
||||
@ -401,23 +456,27 @@ static int ciintf_init(struct budget_ci *budget_ci)
|
||||
budget_ci->ca.slot_reset = ciintf_slot_reset;
|
||||
budget_ci->ca.slot_shutdown = ciintf_slot_shutdown;
|
||||
budget_ci->ca.slot_ts_enable = ciintf_slot_ts_enable;
|
||||
budget_ci->ca.poll_slot_status = ciintf_poll_slot_status;
|
||||
budget_ci->ca.data = budget_ci;
|
||||
if ((result = dvb_ca_en50221_init(&budget_ci->budget.dvb_adapter,
|
||||
&budget_ci->ca,
|
||||
DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE |
|
||||
DVB_CA_EN50221_FLAG_IRQ_FR |
|
||||
DVB_CA_EN50221_FLAG_IRQ_DA, 1)) != 0) {
|
||||
ca_flags, 1)) != 0) {
|
||||
printk("budget_ci: CI interface detected, but initialisation failed.\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
// Setup CI slot IRQ
|
||||
tasklet_init(&budget_ci->ciintf_irq_tasklet, ciintf_interrupt, (unsigned long) budget_ci);
|
||||
if (budget_ci->slot_status != SLOTSTATUS_NONE) {
|
||||
saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQLO);
|
||||
} else {
|
||||
saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI);
|
||||
if (budget_ci->ci_irq) {
|
||||
tasklet_init(&budget_ci->ciintf_irq_tasklet, ciintf_interrupt, (unsigned long) budget_ci);
|
||||
if (budget_ci->slot_status != SLOTSTATUS_NONE) {
|
||||
saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQLO);
|
||||
} else {
|
||||
saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI);
|
||||
}
|
||||
saa7146_write(saa, IER, saa7146_read(saa, IER) | MASK_03);
|
||||
}
|
||||
saa7146_write(saa, IER, saa7146_read(saa, IER) | MASK_03);
|
||||
|
||||
// enable interface
|
||||
ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
|
||||
CICONTROL_RESET, 1, 0);
|
||||
|
||||
@ -426,10 +485,12 @@ static int ciintf_init(struct budget_ci *budget_ci)
|
||||
budget_ci->budget.ci_present = 1;
|
||||
|
||||
// forge a fake CI IRQ so the CAM state is setup correctly
|
||||
flags = DVB_CA_EN50221_CAMCHANGE_REMOVED;
|
||||
if (budget_ci->slot_status != SLOTSTATUS_NONE)
|
||||
flags = DVB_CA_EN50221_CAMCHANGE_INSERTED;
|
||||
dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0, flags);
|
||||
if (budget_ci->ci_irq) {
|
||||
flags = DVB_CA_EN50221_CAMCHANGE_REMOVED;
|
||||
if (budget_ci->slot_status != SLOTSTATUS_NONE)
|
||||
flags = DVB_CA_EN50221_CAMCHANGE_INSERTED;
|
||||
dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0, flags);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@ -443,9 +504,13 @@ static void ciintf_deinit(struct budget_ci *budget_ci)
|
||||
struct saa7146_dev *saa = budget_ci->budget.dev;
|
||||
|
||||
// disable CI interrupts
|
||||
saa7146_write(saa, IER, saa7146_read(saa, IER) & ~MASK_03);
|
||||
saa7146_setgpio(saa, 0, SAA7146_GPIO_INPUT);
|
||||
tasklet_kill(&budget_ci->ciintf_irq_tasklet);
|
||||
if (budget_ci->ci_irq) {
|
||||
saa7146_write(saa, IER, saa7146_read(saa, IER) & ~MASK_03);
|
||||
saa7146_setgpio(saa, 0, SAA7146_GPIO_INPUT);
|
||||
tasklet_kill(&budget_ci->ciintf_irq_tasklet);
|
||||
}
|
||||
|
||||
// reset interface
|
||||
ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 0, 1, 0);
|
||||
msleep(1);
|
||||
ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
|
||||
@ -473,7 +538,7 @@ static void budget_ci_irq(struct saa7146_dev *dev, u32 * isr)
|
||||
if (*isr & MASK_10)
|
||||
ttpci_budget_irq10_handler(dev, isr);
|
||||
|
||||
if ((*isr & MASK_03) && (budget_ci->budget.ci_present))
|
||||
if ((*isr & MASK_03) && (budget_ci->budget.ci_present) && (budget_ci->ci_irq))
|
||||
tasklet_schedule(&budget_ci->ciintf_irq_tasklet);
|
||||
}
|
||||
|
||||
|
@ -1507,7 +1507,11 @@ static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *i
|
||||
|
||||
mutex_unlock(&ttusb->semi2c);
|
||||
|
||||
dvb_register_adapter(&ttusb->adapter, "Technotrend/Hauppauge Nova-USB", THIS_MODULE);
|
||||
if ((result = dvb_register_adapter(&ttusb->adapter, "Technotrend/Hauppauge Nova-USB", THIS_MODULE)) < 0) {
|
||||
ttusb_free_iso_urbs(ttusb);
|
||||
kfree(ttusb);
|
||||
return result;
|
||||
}
|
||||
ttusb->adapter.priv = ttusb;
|
||||
|
||||
/* i2c */
|
||||
|
@ -7,7 +7,7 @@ menu "Radio Adapters"
|
||||
|
||||
config RADIO_CADET
|
||||
tristate "ADS Cadet AM/FM Tuner"
|
||||
depends on ISA && VIDEO_DEV
|
||||
depends on ISA && VIDEO_V4L1
|
||||
---help---
|
||||
Choose Y here if you have one of these AM/FM radio cards, and then
|
||||
fill in the port address below.
|
||||
@ -25,7 +25,7 @@ config RADIO_CADET
|
||||
|
||||
config RADIO_RTRACK
|
||||
tristate "AIMSlab RadioTrack (aka RadioReveal) support"
|
||||
depends on ISA && VIDEO_DEV
|
||||
depends on ISA && VIDEO_V4L1
|
||||
---help---
|
||||
Choose Y here if you have one of these FM radio cards, and then fill
|
||||
in the port address below.
|
||||
@ -59,7 +59,7 @@ config RADIO_RTRACK_PORT
|
||||
|
||||
config RADIO_RTRACK2
|
||||
tristate "AIMSlab RadioTrack II support"
|
||||
depends on ISA && VIDEO_DEV
|
||||
depends on ISA && VIDEO_V4L1
|
||||
---help---
|
||||
Choose Y here if you have this FM radio card, and then fill in the
|
||||
port address below.
|
||||
@ -82,7 +82,7 @@ config RADIO_RTRACK2_PORT
|
||||
|
||||
config RADIO_AZTECH
|
||||
tristate "Aztech/Packard Bell Radio"
|
||||
depends on ISA && VIDEO_DEV
|
||||
depends on ISA && VIDEO_V4L1
|
||||
---help---
|
||||
Choose Y here if you have one of these FM radio cards, and then fill
|
||||
in the port address below.
|
||||
@ -106,7 +106,7 @@ config RADIO_AZTECH_PORT
|
||||
|
||||
config RADIO_GEMTEK
|
||||
tristate "GemTek Radio Card support"
|
||||
depends on ISA && VIDEO_DEV
|
||||
depends on ISA && VIDEO_V4L1
|
||||
---help---
|
||||
Choose Y here if you have this FM radio card, and then fill in the
|
||||
port address below.
|
||||
@ -131,7 +131,7 @@ config RADIO_GEMTEK_PORT
|
||||
|
||||
config RADIO_GEMTEK_PCI
|
||||
tristate "GemTek PCI Radio Card support"
|
||||
depends on VIDEO_DEV && PCI
|
||||
depends on VIDEO_V4L1 && PCI
|
||||
---help---
|
||||
Choose Y here if you have this PCI FM radio card.
|
||||
|
||||
@ -145,7 +145,7 @@ config RADIO_GEMTEK_PCI
|
||||
|
||||
config RADIO_MAXIRADIO
|
||||
tristate "Guillemot MAXI Radio FM 2000 radio"
|
||||
depends on VIDEO_DEV && PCI
|
||||
depends on VIDEO_V4L1 && PCI
|
||||
---help---
|
||||
Choose Y here if you have this radio card. This card may also be
|
||||
found as Gemtek PCI FM.
|
||||
@ -160,7 +160,7 @@ config RADIO_MAXIRADIO
|
||||
|
||||
config RADIO_MAESTRO
|
||||
tristate "Maestro on board radio"
|
||||
depends on VIDEO_DEV
|
||||
depends on VIDEO_V4L1
|
||||
---help---
|
||||
Say Y here to directly support the on-board radio tuner on the
|
||||
Maestro 2 or 2E sound card.
|
||||
@ -175,7 +175,7 @@ config RADIO_MAESTRO
|
||||
|
||||
config RADIO_MIROPCM20
|
||||
tristate "miroSOUND PCM20 radio"
|
||||
depends on ISA && VIDEO_DEV && SOUND_ACI_MIXER
|
||||
depends on ISA && VIDEO_V4L1 && SOUND_ACI_MIXER
|
||||
---help---
|
||||
Choose Y here if you have this FM radio card. You also need to say Y
|
||||
to "ACI mixer (miroSOUND PCM1-pro/PCM12/PCM20 radio)" (in "Sound")
|
||||
@ -208,7 +208,7 @@ config RADIO_MIROPCM20_RDS
|
||||
|
||||
config RADIO_SF16FMI
|
||||
tristate "SF16FMI Radio"
|
||||
depends on ISA && VIDEO_DEV
|
||||
depends on ISA && VIDEO_V4L1
|
||||
---help---
|
||||
Choose Y here if you have one of these FM radio cards. If you
|
||||
compile the driver into the kernel and your card is not PnP one, you
|
||||
@ -225,7 +225,7 @@ config RADIO_SF16FMI
|
||||
|
||||
config RADIO_SF16FMR2
|
||||
tristate "SF16FMR2 Radio"
|
||||
depends on ISA && VIDEO_DEV
|
||||
depends on ISA && VIDEO_V4L1
|
||||
---help---
|
||||
Choose Y here if you have one of these FM radio cards.
|
||||
|
||||
@ -239,7 +239,7 @@ config RADIO_SF16FMR2
|
||||
|
||||
config RADIO_TERRATEC
|
||||
tristate "TerraTec ActiveRadio ISA Standalone"
|
||||
depends on ISA && VIDEO_DEV
|
||||
depends on ISA && VIDEO_V4L1
|
||||
---help---
|
||||
Choose Y here if you have this FM radio card, and then fill in the
|
||||
port address below. (TODO)
|
||||
@ -268,7 +268,7 @@ config RADIO_TERRATEC_PORT
|
||||
|
||||
config RADIO_TRUST
|
||||
tristate "Trust FM radio card"
|
||||
depends on ISA && VIDEO_DEV
|
||||
depends on ISA && VIDEO_V4L1
|
||||
help
|
||||
This is a driver for the Trust FM radio cards. Say Y if you have
|
||||
such a card and want to use it under Linux.
|
||||
@ -286,7 +286,7 @@ config RADIO_TRUST_PORT
|
||||
|
||||
config RADIO_TYPHOON
|
||||
tristate "Typhoon Radio (a.k.a. EcoRadio)"
|
||||
depends on ISA && VIDEO_DEV
|
||||
depends on ISA && VIDEO_V4L1
|
||||
---help---
|
||||
Choose Y here if you have one of these FM radio cards, and then fill
|
||||
in the port address and the frequency used for muting below.
|
||||
@ -330,7 +330,7 @@ config RADIO_TYPHOON_MUTEFREQ
|
||||
|
||||
config RADIO_ZOLTRIX
|
||||
tristate "Zoltrix Radio"
|
||||
depends on ISA && VIDEO_DEV
|
||||
depends on ISA && VIDEO_V4L1
|
||||
---help---
|
||||
Choose Y here if you have one of these FM radio cards, and then fill
|
||||
in the port address below.
|
||||
|
@ -2,10 +2,10 @@
|
||||
# Multimedia Video device configuration
|
||||
#
|
||||
|
||||
menu "Video For Linux"
|
||||
menu "Video Capture Adapters"
|
||||
depends on VIDEO_DEV
|
||||
|
||||
comment "Video Adapters"
|
||||
comment "Video Capture Adapters"
|
||||
|
||||
config VIDEO_ADV_DEBUG
|
||||
bool "Enable advanced debug functionality"
|
||||
@ -16,11 +16,23 @@ config VIDEO_ADV_DEBUG
|
||||
V4L devices.
|
||||
In doubt, say N.
|
||||
|
||||
config VIDEO_VIVI
|
||||
tristate "Virtual Video Driver"
|
||||
depends on VIDEO_V4L2 && !SPARC32 && !SPARC64
|
||||
select VIDEO_BUF
|
||||
default n
|
||||
---help---
|
||||
Enables a virtual video driver. This device shows a color bar
|
||||
and a timestamp, as a real device would generate by using V4L2
|
||||
api.
|
||||
Say Y here if you want to test video apps or debug V4L devices.
|
||||
In doubt, say N.
|
||||
|
||||
source "drivers/media/video/bt8xx/Kconfig"
|
||||
|
||||
config VIDEO_SAA6588
|
||||
tristate "SAA6588 Radio Chip RDS decoder support on BT848 cards"
|
||||
depends on VIDEO_DEV && I2C && VIDEO_BT848
|
||||
depends on I2C && VIDEO_BT848
|
||||
|
||||
help
|
||||
Support for Radio Data System (RDS) decoder. This allows seeing
|
||||
@ -32,7 +44,7 @@ config VIDEO_SAA6588
|
||||
|
||||
config VIDEO_PMS
|
||||
tristate "Mediavision Pro Movie Studio Video For Linux"
|
||||
depends on VIDEO_DEV && ISA
|
||||
depends on ISA && VIDEO_V4L1
|
||||
help
|
||||
Say Y if you have such a thing.
|
||||
|
||||
@ -41,7 +53,7 @@ config VIDEO_PMS
|
||||
|
||||
config VIDEO_PLANB
|
||||
tristate "PlanB Video-In on PowerMac"
|
||||
depends on PPC_PMAC && VIDEO_DEV && BROKEN
|
||||
depends on PPC_PMAC && VIDEO_V4L1 && BROKEN
|
||||
help
|
||||
PlanB is the V4L driver for the PowerMac 7x00/8x00 series video
|
||||
input hardware. If you want to experiment with this, say Y.
|
||||
@ -52,7 +64,7 @@ config VIDEO_PLANB
|
||||
|
||||
config VIDEO_BWQCAM
|
||||
tristate "Quickcam BW Video For Linux"
|
||||
depends on VIDEO_DEV && PARPORT
|
||||
depends on PARPORT && VIDEO_V4L1
|
||||
help
|
||||
Say Y have if you the black and white version of the QuickCam
|
||||
camera. See the next option for the color version.
|
||||
@ -62,7 +74,7 @@ config VIDEO_BWQCAM
|
||||
|
||||
config VIDEO_CQCAM
|
||||
tristate "QuickCam Colour Video For Linux (EXPERIMENTAL)"
|
||||
depends on EXPERIMENTAL && VIDEO_DEV && PARPORT
|
||||
depends on EXPERIMENTAL && PARPORT && VIDEO_V4L1
|
||||
help
|
||||
This is the video4linux driver for the colour version of the
|
||||
Connectix QuickCam. If you have one of these cameras, say Y here,
|
||||
@ -73,7 +85,7 @@ config VIDEO_CQCAM
|
||||
|
||||
config VIDEO_W9966
|
||||
tristate "W9966CF Webcam (FlyCam Supra and others) Video For Linux"
|
||||
depends on PARPORT_1284 && VIDEO_DEV && PARPORT
|
||||
depends on PARPORT_1284 && PARPORT && VIDEO_V4L1
|
||||
help
|
||||
Video4linux driver for Winbond's w9966 based Webcams.
|
||||
Currently tested with the LifeView FlyCam Supra.
|
||||
@ -86,7 +98,7 @@ config VIDEO_W9966
|
||||
|
||||
config VIDEO_CPIA
|
||||
tristate "CPiA Video For Linux"
|
||||
depends on VIDEO_DEV
|
||||
depends on VIDEO_V4L1
|
||||
---help---
|
||||
This is the video4linux driver for cameras based on Vision's CPiA
|
||||
(Colour Processor Interface ASIC), such as the Creative Labs Video
|
||||
@ -123,7 +135,7 @@ source "drivers/media/video/cpia2/Kconfig"
|
||||
|
||||
config VIDEO_SAA5246A
|
||||
tristate "SAA5246A, SAA5281 Teletext processor"
|
||||
depends on VIDEO_DEV && I2C
|
||||
depends on I2C && VIDEO_V4L1
|
||||
help
|
||||
Support for I2C bus based teletext using the SAA5246A or SAA5281
|
||||
chip. Useful only if you live in Europe.
|
||||
@ -150,7 +162,7 @@ config TUNER_3036
|
||||
|
||||
config VIDEO_VINO
|
||||
tristate "SGI Vino Video For Linux (EXPERIMENTAL)"
|
||||
depends on VIDEO_DEV && I2C && SGI_IP22 && EXPERIMENTAL
|
||||
depends on I2C && SGI_IP22 && EXPERIMENTAL && VIDEO_V4L1
|
||||
select I2C_ALGO_SGI
|
||||
help
|
||||
Say Y here to build in support for the Vino video input system found
|
||||
@ -158,7 +170,7 @@ config VIDEO_VINO
|
||||
|
||||
config VIDEO_STRADIS
|
||||
tristate "Stradis 4:2:2 MPEG-2 video driver (EXPERIMENTAL)"
|
||||
depends on EXPERIMENTAL && VIDEO_DEV && PCI
|
||||
depends on EXPERIMENTAL && PCI && VIDEO_V4L1
|
||||
help
|
||||
Say Y here to enable support for the Stradis 4:2:2 MPEG-2 video
|
||||
driver for PCI. There is a product page at
|
||||
@ -166,7 +178,7 @@ config VIDEO_STRADIS
|
||||
|
||||
config VIDEO_ZORAN
|
||||
tristate "Zoran ZR36057/36067 Video For Linux"
|
||||
depends on VIDEO_DEV && PCI && I2C_ALGOBIT
|
||||
depends on PCI && I2C_ALGOBIT && VIDEO_V4L1
|
||||
help
|
||||
Say Y for support for MJPEG capture cards based on the Zoran
|
||||
36057/36067 PCI controller chipset. This includes the Iomega
|
||||
@ -214,7 +226,7 @@ config VIDEO_ZORAN_LML33R10
|
||||
|
||||
config VIDEO_ZR36120
|
||||
tristate "Zoran ZR36120/36125 Video For Linux"
|
||||
depends on VIDEO_DEV && PCI && I2C && BROKEN
|
||||
depends on PCI && I2C && VIDEO_V4L1 && BROKEN
|
||||
help
|
||||
Support for ZR36120/ZR36125 based frame grabber/overlay boards.
|
||||
This includes the Victor II, WaveWatcher, Video Wonder, Maxi-TV,
|
||||
@ -226,7 +238,7 @@ config VIDEO_ZR36120
|
||||
|
||||
config VIDEO_MEYE
|
||||
tristate "Sony Vaio Picturebook Motion Eye Video For Linux"
|
||||
depends on VIDEO_DEV && PCI && SONYPI
|
||||
depends on PCI && SONYPI && VIDEO_V4L1
|
||||
---help---
|
||||
This is the video4linux driver for the Motion Eye camera found
|
||||
in the Vaio Picturebook laptops. Please read the material in
|
||||
@ -242,7 +254,7 @@ source "drivers/media/video/saa7134/Kconfig"
|
||||
|
||||
config VIDEO_MXB
|
||||
tristate "Siemens-Nixdorf 'Multimedia eXtension Board'"
|
||||
depends on VIDEO_DEV && PCI
|
||||
depends on PCI && VIDEO_V4L1
|
||||
select VIDEO_SAA7146_VV
|
||||
select VIDEO_TUNER
|
||||
---help---
|
||||
@ -254,8 +266,9 @@ config VIDEO_MXB
|
||||
|
||||
config VIDEO_DPC
|
||||
tristate "Philips-Semiconductors 'dpc7146 demonstration board'"
|
||||
depends on VIDEO_DEV && PCI
|
||||
depends on PCI && VIDEO_V4L1
|
||||
select VIDEO_SAA7146_VV
|
||||
select VIDEO_V4L2
|
||||
---help---
|
||||
This is a video4linux driver for the 'dpc7146 demonstration
|
||||
board' by Philips-Semiconductors. It's the reference design
|
||||
@ -268,8 +281,9 @@ config VIDEO_DPC
|
||||
|
||||
config VIDEO_HEXIUM_ORION
|
||||
tristate "Hexium HV-PCI6 and Orion frame grabber"
|
||||
depends on VIDEO_DEV && PCI
|
||||
depends on PCI && VIDEO_V4L1
|
||||
select VIDEO_SAA7146_VV
|
||||
select VIDEO_V4L2
|
||||
---help---
|
||||
This is a video4linux driver for the Hexium HV-PCI6 and
|
||||
Orion frame grabber cards by Hexium.
|
||||
@ -279,8 +293,9 @@ config VIDEO_HEXIUM_ORION
|
||||
|
||||
config VIDEO_HEXIUM_GEMINI
|
||||
tristate "Hexium Gemini frame grabber"
|
||||
depends on VIDEO_DEV && PCI
|
||||
depends on PCI && VIDEO_V4L1
|
||||
select VIDEO_SAA7146_VV
|
||||
select VIDEO_V4L2
|
||||
---help---
|
||||
This is a video4linux driver for the Hexium Gemini frame
|
||||
grabber card by Hexium. Please note that the Gemini Dual
|
||||
@ -293,7 +308,7 @@ source "drivers/media/video/cx88/Kconfig"
|
||||
|
||||
config VIDEO_OVCAMCHIP
|
||||
tristate "OmniVision Camera Chip support"
|
||||
depends on VIDEO_DEV && I2C
|
||||
depends on I2C && VIDEO_V4L1
|
||||
---help---
|
||||
Support for the OmniVision OV6xxx and OV7xxx series of camera chips.
|
||||
This driver is intended to be used with the ov511 and w9968cf USB
|
||||
@ -304,7 +319,7 @@ config VIDEO_OVCAMCHIP
|
||||
|
||||
config VIDEO_M32R_AR
|
||||
tristate "AR devices"
|
||||
depends on M32R
|
||||
depends on M32R && VIDEO_V4L1
|
||||
---help---
|
||||
This is a video4linux driver for the Renesas AR (Artificial Retina)
|
||||
camera module.
|
||||
@ -365,17 +380,17 @@ config VIDEO_WM8739
|
||||
source "drivers/media/video/cx25840/Kconfig"
|
||||
|
||||
config VIDEO_SAA711X
|
||||
tristate "Philips SAA7113/4/5 video decoders"
|
||||
depends on VIDEO_DEV && I2C && EXPERIMENTAL
|
||||
tristate "Philips SAA7113/4/5 video decoders (OBSOLETED)"
|
||||
depends on VIDEO_V4L1 && I2C && EXPERIMENTAL
|
||||
---help---
|
||||
Support for the Philips SAA7113/4/5 video decoders.
|
||||
Old support for the Philips SAA7113/4 video decoders.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called saa7115.
|
||||
|
||||
config VIDEO_SAA7127
|
||||
tristate "Philips SAA7127/9 digital video encoders"
|
||||
depends on VIDEO_DEV && I2C && EXPERIMENTAL
|
||||
depends on VIDEO_V4L2 && I2C && EXPERIMENTAL
|
||||
---help---
|
||||
Support for the Philips SAA7127/9 digital video encoders.
|
||||
|
||||
@ -384,7 +399,7 @@ config VIDEO_SAA7127
|
||||
|
||||
config VIDEO_UPD64031A
|
||||
tristate "NEC Electronics uPD64031A Ghost Reduction"
|
||||
depends on VIDEO_DEV && I2C && EXPERIMENTAL
|
||||
depends on VIDEO_V4L2 && I2C && EXPERIMENTAL
|
||||
---help---
|
||||
Support for the NEC Electronics uPD64031A Ghost Reduction
|
||||
video chip. It is most often found in NTSC TV cards made for
|
||||
@ -396,7 +411,7 @@ config VIDEO_UPD64031A
|
||||
|
||||
config VIDEO_UPD64083
|
||||
tristate "NEC Electronics uPD64083 3-Dimensional Y/C separation"
|
||||
depends on VIDEO_DEV && I2C && EXPERIMENTAL
|
||||
depends on VIDEO_V4L2 && I2C && EXPERIMENTAL
|
||||
---help---
|
||||
Support for the NEC Electronics uPD64083 3-Dimensional Y/C
|
||||
separation video chip. It is used to improve the quality of
|
||||
@ -418,7 +433,7 @@ source "drivers/media/video/em28xx/Kconfig"
|
||||
|
||||
config USB_DSBR
|
||||
tristate "D-Link USB FM radio support (EXPERIMENTAL)"
|
||||
depends on USB && VIDEO_DEV && EXPERIMENTAL
|
||||
depends on USB && VIDEO_V4L1 && EXPERIMENTAL
|
||||
---help---
|
||||
Say Y here if you want to connect this type of radio to your
|
||||
computer's USB port. Note that the audio is not digital, and
|
||||
@ -434,7 +449,7 @@ source "drivers/media/video/et61x251/Kconfig"
|
||||
|
||||
config USB_OV511
|
||||
tristate "USB OV511 Camera support"
|
||||
depends on USB && VIDEO_DEV
|
||||
depends on USB && VIDEO_V4L1
|
||||
---help---
|
||||
Say Y here if you want to connect this type of camera to your
|
||||
computer's USB port. See <file:Documentation/video4linux/ov511.txt>
|
||||
@ -445,7 +460,7 @@ config USB_OV511
|
||||
|
||||
config USB_SE401
|
||||
tristate "USB SE401 Camera support"
|
||||
depends on USB && VIDEO_DEV
|
||||
depends on USB && VIDEO_V4L1
|
||||
---help---
|
||||
Say Y here if you want to connect this type of camera to your
|
||||
computer's USB port. See <file:Documentation/video4linux/se401.txt>
|
||||
@ -458,7 +473,7 @@ source "drivers/media/video/sn9c102/Kconfig"
|
||||
|
||||
config USB_STV680
|
||||
tristate "USB STV680 (Pencam) Camera support"
|
||||
depends on USB && VIDEO_DEV
|
||||
depends on USB && VIDEO_V4L1
|
||||
---help---
|
||||
Say Y here if you want to connect this type of camera to your
|
||||
computer's USB port. This includes the Pencam line of cameras.
|
||||
@ -470,7 +485,7 @@ config USB_STV680
|
||||
|
||||
config USB_W9968CF
|
||||
tristate "USB W996[87]CF JPEG Dual Mode Camera support"
|
||||
depends on USB && VIDEO_DEV && I2C
|
||||
depends on USB && VIDEO_V4L1 && I2C
|
||||
select VIDEO_OVCAMCHIP
|
||||
---help---
|
||||
Say Y here if you want support for cameras based on OV681 or
|
||||
|
@ -10,7 +10,8 @@ tuner-objs := tuner-core.o tuner-types.o tuner-simple.o \
|
||||
|
||||
msp3400-objs := msp3400-driver.o msp3400-kthreads.o
|
||||
|
||||
obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-common.o v4l1-compat.o compat_ioctl32.o
|
||||
obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-common.o compat_ioctl32.o
|
||||
obj-$(CONFIG_VIDEO_V4L1_COMPAT) += v4l1-compat.o
|
||||
|
||||
obj-$(CONFIG_VIDEO_BT848) += bt8xx/
|
||||
obj-$(CONFIG_VIDEO_BT848) += tvaudio.o tda7432.o tda9875.o ir-kbd-i2c.o
|
||||
@ -84,4 +85,8 @@ obj-$(CONFIG_USB_IBMCAM) += usbvideo/
|
||||
obj-$(CONFIG_USB_KONICAWC) += usbvideo/
|
||||
obj-$(CONFIG_USB_VICAM) += usbvideo/
|
||||
|
||||
obj-$(CONFIG_VIDEO_VIVI) += vivi.o
|
||||
|
||||
EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
|
||||
extra-cflags-$(CONFIG_VIDEO_V4L1_COMPAT) += -DCONFIG_VIDEO_V4L1_COMPAT
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
config VIDEO_BT848
|
||||
tristate "BT848 Video For Linux"
|
||||
depends on VIDEO_DEV && PCI && I2C
|
||||
depends on VIDEO_DEV && PCI && I2C && VIDEO_V4L2
|
||||
select I2C_ALGOBIT
|
||||
select FW_LOADER
|
||||
select VIDEO_BTCX
|
||||
|
@ -8,5 +8,5 @@ bttv-objs := bttv-driver.o bttv-cards.o bttv-if.o \
|
||||
|
||||
obj-$(CONFIG_VIDEO_BT848) += bttv.o
|
||||
|
||||
EXTRA_CFLAGS += -I$(src)/..
|
||||
EXTRA_CFLAGS += -Idrivers/media/video
|
||||
EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
|
||||
|
@ -2991,13 +2991,13 @@ void __devinit bttv_idcard(struct bttv *btv)
|
||||
|
||||
if (UNSET != audiomux[0]) {
|
||||
gpiobits = 0;
|
||||
for (i = 0; i < 5; i++) {
|
||||
for (i = 0; i < 4; i++) {
|
||||
bttv_tvcards[btv->c.type].gpiomux[i] = audiomux[i];
|
||||
gpiobits |= audiomux[i];
|
||||
}
|
||||
} else {
|
||||
gpiobits = audioall;
|
||||
for (i = 0; i < 5; i++) {
|
||||
for (i = 0; i < 4; i++) {
|
||||
bttv_tvcards[btv->c.type].gpiomux[i] = audioall;
|
||||
}
|
||||
}
|
||||
|
@ -233,7 +233,7 @@ bttv_risc_overlay(struct bttv *btv, struct btcx_riscmem *risc,
|
||||
const struct bttv_format *fmt, struct bttv_overlay *ov,
|
||||
int skip_even, int skip_odd)
|
||||
{
|
||||
int instructions,rc,line,maxy,start,end,skip,nskips;
|
||||
int dwords,rc,line,maxy,start,end,skip,nskips;
|
||||
struct btcx_skiplist *skips;
|
||||
u32 *rp,ri,ra;
|
||||
u32 addr;
|
||||
@ -242,12 +242,12 @@ bttv_risc_overlay(struct bttv *btv, struct btcx_riscmem *risc,
|
||||
if (NULL == (skips = kmalloc(sizeof(*skips) * ov->nclips,GFP_KERNEL)))
|
||||
return -ENOMEM;
|
||||
|
||||
/* estimate risc mem: worst case is (clip+1) * lines instructions
|
||||
/* estimate risc mem: worst case is (1.5*clip+1) * lines instructions
|
||||
+ sync + jump (all 2 dwords) */
|
||||
instructions = (ov->nclips + 1) *
|
||||
((skip_even || skip_odd) ? ov->w.height>>1 : ov->w.height);
|
||||
instructions += 2;
|
||||
if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,instructions*8)) < 0) {
|
||||
dwords = (3 * ov->nclips + 2) *
|
||||
((skip_even || skip_odd) ? (ov->w.height+1)>>1 : ov->w.height);
|
||||
dwords += 4;
|
||||
if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,dwords*4)) < 0) {
|
||||
kfree(skips);
|
||||
return rc;
|
||||
}
|
||||
@ -276,8 +276,6 @@ bttv_risc_overlay(struct bttv *btv, struct btcx_riscmem *risc,
|
||||
if (line > maxy)
|
||||
btcx_calc_skips(line, ov->w.width, &maxy,
|
||||
skips, &nskips, ov->clips, ov->nclips);
|
||||
else
|
||||
nskips = 0;
|
||||
|
||||
/* write out risc code */
|
||||
for (start = 0, skip = 0; start < ov->w.width; start = end) {
|
||||
|
@ -39,29 +39,12 @@
|
||||
|
||||
#define FWDEV(x) &((x)->adapter->dev)
|
||||
|
||||
static int fastfw = 1;
|
||||
static char *firmware = FWFILE;
|
||||
|
||||
module_param(fastfw, bool, 0444);
|
||||
module_param(firmware, charp, 0444);
|
||||
|
||||
MODULE_PARM_DESC(fastfw, "Load firmware fast [0=100MHz 1=333MHz (default)]");
|
||||
MODULE_PARM_DESC(firmware, "Firmware image [default: " FWFILE "]");
|
||||
|
||||
static void set_i2c_delay(struct i2c_client *client, int delay)
|
||||
{
|
||||
struct i2c_algo_bit_data *algod = client->adapter->algo_data;
|
||||
|
||||
/* We aren't guaranteed to be using algo_bit,
|
||||
* so avoid the null pointer dereference
|
||||
* and disable the 'fast firmware load' */
|
||||
if (algod) {
|
||||
algod->udelay = delay;
|
||||
} else {
|
||||
fastfw = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void start_fw_load(struct i2c_client *client)
|
||||
{
|
||||
/* DL_ADDR_LB=0 DL_ADDR_HB=0 */
|
||||
@ -71,16 +54,10 @@ static void start_fw_load(struct i2c_client *client)
|
||||
cx25840_write(client, 0x803, 0x0b);
|
||||
/* AUTO_INC_DIS=1 */
|
||||
cx25840_write(client, 0x000, 0x20);
|
||||
|
||||
if (fastfw)
|
||||
set_i2c_delay(client, 3);
|
||||
}
|
||||
|
||||
static void end_fw_load(struct i2c_client *client)
|
||||
{
|
||||
if (fastfw)
|
||||
set_i2c_delay(client, 10);
|
||||
|
||||
/* AUTO_INC_DIS=0 */
|
||||
cx25840_write(client, 0x000, 0x00);
|
||||
/* DL_ENABLE=0 */
|
||||
@ -107,30 +84,8 @@ static int fw_write(struct i2c_client *client, u8 * data, int size)
|
||||
int sent;
|
||||
|
||||
if ((sent = i2c_master_send(client, data, size)) < size) {
|
||||
|
||||
if (fastfw) {
|
||||
v4l_err(client, "333MHz i2c firmware load failed\n");
|
||||
fastfw = 0;
|
||||
set_i2c_delay(client, 10);
|
||||
|
||||
if (sent > 2) {
|
||||
u16 dl_addr = cx25840_read(client, 0x801) << 8;
|
||||
dl_addr |= cx25840_read(client, 0x800);
|
||||
dl_addr -= sent - 2;
|
||||
cx25840_write(client, 0x801, dl_addr >> 8);
|
||||
cx25840_write(client, 0x800, dl_addr & 0xff);
|
||||
}
|
||||
|
||||
if (i2c_master_send(client, data, size) < size) {
|
||||
v4l_err(client, "100MHz i2c firmware load failed\n");
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
} else {
|
||||
v4l_err(client, "firmware load i2c failure\n");
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
v4l_err(client, "firmware load i2c failure\n");
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -564,7 +564,7 @@ struct cx88_board cx88_boards[] = {
|
||||
},
|
||||
[CX88_BOARD_PCHDTV_HD3000] = {
|
||||
.name = "pcHDTV HD3000 HDTV",
|
||||
.tuner_type = TUNER_THOMSON_DTT7610,
|
||||
.tuner_type = TUNER_THOMSON_DTT761X,
|
||||
.radio_type = UNSET,
|
||||
.tuner_addr = ADDR_UNSET,
|
||||
.radio_addr = ADDR_UNSET,
|
||||
|
@ -146,9 +146,11 @@ int cx88_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
|
||||
fields++;
|
||||
|
||||
/* estimate risc mem: worst case is one write per page border +
|
||||
one write per scan line + syncs + jump (all 2 dwords) */
|
||||
instructions = (bpl * lines * fields) / PAGE_SIZE + lines * fields;
|
||||
instructions += 3 + 4;
|
||||
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 */
|
||||
instructions = fields * (1 + ((bpl + padding) * lines) / PAGE_SIZE + lines);
|
||||
instructions += 2;
|
||||
if ((rc = btcx_riscmem_alloc(pci,risc,instructions*8)) < 0)
|
||||
return rc;
|
||||
|
||||
@ -176,9 +178,11 @@ int cx88_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc,
|
||||
int rc;
|
||||
|
||||
/* estimate risc mem: worst case is one write per page border +
|
||||
one write per scan line + syncs + jump (all 2 dwords) */
|
||||
instructions = (bpl * lines) / PAGE_SIZE + lines;
|
||||
instructions += 3 + 4;
|
||||
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 */
|
||||
instructions = 1 + (bpl * lines) / PAGE_SIZE + lines;
|
||||
instructions += 1;
|
||||
if ((rc = btcx_riscmem_alloc(pci,risc,instructions*8)) < 0)
|
||||
return rc;
|
||||
|
||||
|
@ -372,7 +372,7 @@ static int or51132_set_ts_param(struct dvb_frontend* fe,
|
||||
static struct or51132_config pchdtv_hd3000 = {
|
||||
.demod_address = 0x15,
|
||||
.pll_address = 0x61,
|
||||
.pll_desc = &dvb_pll_thomson_dtt7610,
|
||||
.pll_desc = &dvb_pll_thomson_dtt761x,
|
||||
.set_ts_params = or51132_set_ts_param,
|
||||
};
|
||||
#endif
|
||||
|
@ -35,8 +35,10 @@
|
||||
#include "cx88.h"
|
||||
#include <media/v4l2-common.h>
|
||||
|
||||
#ifdef CONFIG_VIDEO_V4L1_COMPAT
|
||||
/* Include V4L1 specific functions. Should be removed soon */
|
||||
#include <linux/videodev.h>
|
||||
#endif
|
||||
|
||||
MODULE_DESCRIPTION("v4l2 driver module for cx2388x based TV cards");
|
||||
MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
|
||||
|
@ -1,6 +1,6 @@
|
||||
config VIDEO_EM28XX
|
||||
tristate "Empia EM2800/2820/2840 USB video capture support"
|
||||
depends on VIDEO_DEV && USB && I2C
|
||||
depends on VIDEO_V4L1 && USB && I2C
|
||||
select VIDEO_BUF
|
||||
select VIDEO_TUNER
|
||||
select VIDEO_TVEEPROM
|
||||
|
@ -1576,8 +1576,8 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
|
||||
errCode = em28xx_config(dev);
|
||||
if (errCode) {
|
||||
em28xx_errdev("error configuring device\n");
|
||||
kfree(dev);
|
||||
em28xx_devused&=~(1<<dev->devno);
|
||||
kfree(dev);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
@ -1603,8 +1603,8 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
|
||||
dev->vdev = video_device_alloc();
|
||||
if (NULL == dev->vdev) {
|
||||
em28xx_errdev("cannot allocate video_device.\n");
|
||||
kfree(dev);
|
||||
em28xx_devused&=~(1<<dev->devno);
|
||||
kfree(dev);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
@ -1612,8 +1612,8 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
|
||||
if (NULL == dev->vbi_dev) {
|
||||
em28xx_errdev("cannot allocate video_device.\n");
|
||||
kfree(dev->vdev);
|
||||
kfree(dev);
|
||||
em28xx_devused&=~(1<<dev->devno);
|
||||
kfree(dev);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
@ -1650,8 +1650,8 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
|
||||
mutex_unlock(&dev->lock);
|
||||
list_del(&dev->devlist);
|
||||
video_device_release(dev->vdev);
|
||||
kfree(dev);
|
||||
em28xx_devused&=~(1<<dev->devno);
|
||||
kfree(dev);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
@ -1662,8 +1662,8 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
|
||||
list_del(&dev->devlist);
|
||||
video_device_release(dev->vbi_dev);
|
||||
video_device_release(dev->vdev);
|
||||
kfree(dev);
|
||||
em28xx_devused&=~(1<<dev->devno);
|
||||
kfree(dev);
|
||||
return -ENODEV;
|
||||
} else {
|
||||
printk("registered VBI\n");
|
||||
|
@ -1,6 +1,6 @@
|
||||
config USB_ET61X251
|
||||
tristate "USB ET61X[12]51 PC Camera Controller support"
|
||||
depends on USB && VIDEO_DEV
|
||||
depends on USB && VIDEO_V4L1
|
||||
---help---
|
||||
Say Y here if you want support for cameras based on Etoms ET61X151
|
||||
or ET61X251 PC Camera Controllers.
|
||||
|
@ -1,6 +1,6 @@
|
||||
config USB_PWC
|
||||
tristate "USB Philips Cameras"
|
||||
depends on USB && VIDEO_DEV
|
||||
depends on USB && VIDEO_V4L1
|
||||
---help---
|
||||
Say Y or M here if you want to use one of these Philips & OEM
|
||||
webcams:
|
||||
|
@ -1,20 +1,3 @@
|
||||
ifneq ($(KERNELRELEASE),)
|
||||
|
||||
pwc-objs := pwc-if.o pwc-misc.o pwc-ctrl.o pwc-uncompress.o pwc-timon.o pwc-kiara.o
|
||||
|
||||
obj-$(CONFIG_USB_PWC) += pwc.o
|
||||
|
||||
else
|
||||
|
||||
KDIR := /lib/modules/$(shell uname -r)/build
|
||||
PWD := $(shell pwd)
|
||||
|
||||
default:
|
||||
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
|
||||
|
||||
endif
|
||||
|
||||
clean:
|
||||
rm -f *.[oas] .*.flags *.ko .*.cmd .*.d .*.tmp *.mod.c
|
||||
rm -rf .tmp_versions
|
||||
|
||||
|
@ -142,6 +142,7 @@ struct i2c_reg_value {
|
||||
static const struct i2c_reg_value saa7129_init_config_extra[] = {
|
||||
{ SAA7127_REG_OUTPUT_PORT_CONTROL, 0x38 },
|
||||
{ SAA7127_REG_VTRIG, 0xfa },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static const struct i2c_reg_value saa7127_init_config_common[] = {
|
||||
|
@ -3504,6 +3504,7 @@ int saa7134_board_init1(struct saa7134_dev *dev)
|
||||
/* power-up tuner chip */
|
||||
saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x00040000, 0x00040000);
|
||||
saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x00040000, 0x00000000);
|
||||
break;
|
||||
case SAA7134_BOARD_PINNACLE_300I_DVBT_PAL:
|
||||
/* this turns the remote control chip off to work around a bug in it */
|
||||
saa_writeb(SAA7134_GPIO_GPMODE1, 0x80);
|
||||
|
@ -548,6 +548,8 @@ static irqreturn_t saa7134_irq(int irq, void *dev_id, struct pt_regs *regs)
|
||||
if (report & SAA7134_IRQ_REPORT_GPIO16) {
|
||||
switch (dev->has_remote) {
|
||||
case SAA7134_REMOTE_GPIO:
|
||||
if (!dev->remote)
|
||||
break;
|
||||
if (dev->remote->mask_keydown & 0x10000) {
|
||||
saa7134_input_irq(dev);
|
||||
}
|
||||
@ -564,6 +566,8 @@ static irqreturn_t saa7134_irq(int irq, void *dev_id, struct pt_regs *regs)
|
||||
if (report & SAA7134_IRQ_REPORT_GPIO18) {
|
||||
switch (dev->has_remote) {
|
||||
case SAA7134_REMOTE_GPIO:
|
||||
if (!dev->remote)
|
||||
break;
|
||||
if ((dev->remote->mask_keydown & 0x40000) ||
|
||||
(dev->remote->mask_keyup & 0x40000)) {
|
||||
saa7134_input_irq(dev);
|
||||
@ -676,7 +680,7 @@ static int saa7134_hwinit2(struct saa7134_dev *dev)
|
||||
SAA7134_IRQ2_INTE_PE |
|
||||
SAA7134_IRQ2_INTE_AR;
|
||||
|
||||
if (dev->has_remote == SAA7134_REMOTE_GPIO) {
|
||||
if (dev->has_remote == SAA7134_REMOTE_GPIO && dev->remote) {
|
||||
if (dev->remote->mask_keydown & 0x10000)
|
||||
irq2_mask |= SAA7134_IRQ2_INTE_GPIO16;
|
||||
else if (dev->remote->mask_keydown & 0x40000)
|
||||
|
@ -31,8 +31,10 @@
|
||||
#include "saa7134.h"
|
||||
#include <media/v4l2-common.h>
|
||||
|
||||
#ifdef CONFIG_VIDEO_V4L1_COMPAT
|
||||
/* Include V4L1 specific functions. Should be removed soon */
|
||||
#include <linux/videodev.h>
|
||||
#endif
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
config USB_SN9C102
|
||||
tristate "USB SN9C10x PC Camera Controller support"
|
||||
depends on USB && VIDEO_DEV
|
||||
depends on USB && VIDEO_V4L1
|
||||
---help---
|
||||
Say Y here if you want support for cameras based on SONiX SN9C101,
|
||||
SN9C102 or SN9C103 PC Camera Controllers.
|
||||
|
@ -877,8 +877,8 @@ static struct tuner_params tuner_philips_fmd1216me_mk3_params[] = {
|
||||
/* ------------ TUNER_LG_TDVS_H062F - INFINEON ATSC ------------ */
|
||||
|
||||
static struct tuner_range tuner_tua6034_ntsc_ranges[] = {
|
||||
{ 16 * 160.00 /*MHz*/, 0x8e, 0x01 },
|
||||
{ 16 * 455.00 /*MHz*/, 0x8e, 0x02 },
|
||||
{ 16 * 165.00 /*MHz*/, 0x8e, 0x01 },
|
||||
{ 16 * 450.00 /*MHz*/, 0x8e, 0x02 },
|
||||
{ 16 * 999.99 , 0x8e, 0x04 },
|
||||
};
|
||||
|
||||
|
@ -218,7 +218,7 @@ hauppauge_tuner[] =
|
||||
/* 110-119 */
|
||||
{ TUNER_ABSENT, "Thompson DTT75105"},
|
||||
{ TUNER_ABSENT, "Conexant_CX24109"},
|
||||
{ TUNER_ABSENT, "TCL M2523_5N_E"},
|
||||
{ TUNER_TCL_2002N, "TCL M2523_5N_E"},
|
||||
{ TUNER_ABSENT, "TCL M2523_3DB_E"},
|
||||
{ TUNER_ABSENT, "Philips 8275A"},
|
||||
{ TUNER_ABSENT, "Microtune MT2060"},
|
||||
|
@ -3,7 +3,7 @@ config VIDEO_USBVIDEO
|
||||
|
||||
config USB_VICAM
|
||||
tristate "USB 3com HomeConnect (aka vicam) support (EXPERIMENTAL)"
|
||||
depends on USB && VIDEO_DEV && EXPERIMENTAL
|
||||
depends on USB && VIDEO_V4L1 && EXPERIMENTAL
|
||||
select VIDEO_USBVIDEO
|
||||
---help---
|
||||
Say Y here if you have 3com homeconnect camera (vicam).
|
||||
@ -13,7 +13,7 @@ config USB_VICAM
|
||||
|
||||
config USB_IBMCAM
|
||||
tristate "USB IBM (Xirlink) C-it Camera support"
|
||||
depends on USB && VIDEO_DEV
|
||||
depends on USB && VIDEO_V4L1
|
||||
select VIDEO_USBVIDEO
|
||||
---help---
|
||||
Say Y here if you want to connect a IBM "C-It" camera, also known as
|
||||
@ -28,7 +28,7 @@ config USB_IBMCAM
|
||||
|
||||
config USB_KONICAWC
|
||||
tristate "USB Konica Webcam support"
|
||||
depends on USB && VIDEO_DEV
|
||||
depends on USB && VIDEO_V4L1
|
||||
select VIDEO_USBVIDEO
|
||||
---help---
|
||||
Say Y here if you want support for webcams based on a Konica
|
||||
|
@ -26,6 +26,11 @@
|
||||
#include <linux/random.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/videodev2.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#ifdef CONFIG_VIDEO_V4L1_COMPAT
|
||||
/* Include V4L1 specific functions. Should be removed soon */
|
||||
#include <linux/videodev.h>
|
||||
#endif
|
||||
#include <linux/interrupt.h>
|
||||
#include <media/video-buf.h>
|
||||
#include <media/v4l2-common.h>
|
||||
|
@ -1,6 +1,6 @@
|
||||
config USB_ZC0301
|
||||
tristate "USB ZC0301 Image Processor and Control Chip support"
|
||||
depends on USB && VIDEO_DEV
|
||||
depends on USB && VIDEO_V4L1
|
||||
---help---
|
||||
Say Y here if you want support for cameras based on the ZC0301
|
||||
Image Processor and Control Chip.
|
||||
|
@ -55,8 +55,8 @@
|
||||
|
||||
#define DRV_MODULE_NAME "bnx2"
|
||||
#define PFX DRV_MODULE_NAME ": "
|
||||
#define DRV_MODULE_VERSION "1.4.39"
|
||||
#define DRV_MODULE_RELDATE "March 22, 2006"
|
||||
#define DRV_MODULE_VERSION "1.4.40"
|
||||
#define DRV_MODULE_RELDATE "May 22, 2006"
|
||||
|
||||
#define RUN_AT(x) (jiffies + (x))
|
||||
|
||||
@ -2945,7 +2945,7 @@ bnx2_nvram_write(struct bnx2 *bp, u32 offset, u8 *data_buf,
|
||||
int buf_size)
|
||||
{
|
||||
u32 written, offset32, len32;
|
||||
u8 *buf, start[4], end[4];
|
||||
u8 *buf, start[4], end[4], *flash_buffer = NULL;
|
||||
int rc = 0;
|
||||
int align_start, align_end;
|
||||
|
||||
@ -2985,12 +2985,19 @@ bnx2_nvram_write(struct bnx2 *bp, u32 offset, u8 *data_buf,
|
||||
memcpy(buf + align_start, data_buf, buf_size);
|
||||
}
|
||||
|
||||
if (bp->flash_info->buffered == 0) {
|
||||
flash_buffer = kmalloc(264, GFP_KERNEL);
|
||||
if (flash_buffer == NULL) {
|
||||
rc = -ENOMEM;
|
||||
goto nvram_write_end;
|
||||
}
|
||||
}
|
||||
|
||||
written = 0;
|
||||
while ((written < len32) && (rc == 0)) {
|
||||
u32 page_start, page_end, data_start, data_end;
|
||||
u32 addr, cmd_flags;
|
||||
int i;
|
||||
u8 flash_buffer[264];
|
||||
|
||||
/* Find the page_start addr */
|
||||
page_start = offset32 + written;
|
||||
@ -3061,7 +3068,7 @@ bnx2_nvram_write(struct bnx2 *bp, u32 offset, u8 *data_buf,
|
||||
}
|
||||
|
||||
/* Loop to write the new data from data_start to data_end */
|
||||
for (addr = data_start; addr < data_end; addr += 4, i++) {
|
||||
for (addr = data_start; addr < data_end; addr += 4, i += 4) {
|
||||
if ((addr == page_end - 4) ||
|
||||
((bp->flash_info->buffered) &&
|
||||
(addr == data_end - 4))) {
|
||||
@ -3109,6 +3116,9 @@ bnx2_nvram_write(struct bnx2 *bp, u32 offset, u8 *data_buf,
|
||||
}
|
||||
|
||||
nvram_write_end:
|
||||
if (bp->flash_info->buffered == 0)
|
||||
kfree(flash_buffer);
|
||||
|
||||
if (align_start || align_end)
|
||||
kfree(buf);
|
||||
return rc;
|
||||
|
@ -106,6 +106,7 @@
|
||||
* 0.51: 20 Jan 2006: Add 64bit consistent memory allocation for rings.
|
||||
* 0.52: 20 Jan 2006: Add MSI/MSIX support.
|
||||
* 0.53: 19 Mar 2006: Fix init from low power mode and add hw reset.
|
||||
* 0.54: 21 Mar 2006: Fix spin locks for multi irqs and cleanup.
|
||||
*
|
||||
* Known bugs:
|
||||
* We suspect that on some hardware no TX done interrupts are generated.
|
||||
@ -117,7 +118,7 @@
|
||||
* DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few
|
||||
* superfluous timer interrupts from the nic.
|
||||
*/
|
||||
#define FORCEDETH_VERSION "0.53"
|
||||
#define FORCEDETH_VERSION "0.54"
|
||||
#define DRV_NAME "forcedeth"
|
||||
|
||||
#include <linux/module.h>
|
||||
@ -710,6 +711,72 @@ static void setup_hw_rings(struct net_device *dev, int rxtx_flags)
|
||||
}
|
||||
}
|
||||
|
||||
static int using_multi_irqs(struct net_device *dev)
|
||||
{
|
||||
struct fe_priv *np = get_nvpriv(dev);
|
||||
|
||||
if (!(np->msi_flags & NV_MSI_X_ENABLED) ||
|
||||
((np->msi_flags & NV_MSI_X_ENABLED) &&
|
||||
((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1)))
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void nv_enable_irq(struct net_device *dev)
|
||||
{
|
||||
struct fe_priv *np = get_nvpriv(dev);
|
||||
|
||||
if (!using_multi_irqs(dev)) {
|
||||
if (np->msi_flags & NV_MSI_X_ENABLED)
|
||||
enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector);
|
||||
else
|
||||
enable_irq(dev->irq);
|
||||
} else {
|
||||
enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector);
|
||||
enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector);
|
||||
enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector);
|
||||
}
|
||||
}
|
||||
|
||||
static void nv_disable_irq(struct net_device *dev)
|
||||
{
|
||||
struct fe_priv *np = get_nvpriv(dev);
|
||||
|
||||
if (!using_multi_irqs(dev)) {
|
||||
if (np->msi_flags & NV_MSI_X_ENABLED)
|
||||
disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector);
|
||||
else
|
||||
disable_irq(dev->irq);
|
||||
} else {
|
||||
disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector);
|
||||
disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector);
|
||||
disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector);
|
||||
}
|
||||
}
|
||||
|
||||
/* In MSIX mode, a write to irqmask behaves as XOR */
|
||||
static void nv_enable_hw_interrupts(struct net_device *dev, u32 mask)
|
||||
{
|
||||
u8 __iomem *base = get_hwbase(dev);
|
||||
|
||||
writel(mask, base + NvRegIrqMask);
|
||||
}
|
||||
|
||||
static void nv_disable_hw_interrupts(struct net_device *dev, u32 mask)
|
||||
{
|
||||
struct fe_priv *np = get_nvpriv(dev);
|
||||
u8 __iomem *base = get_hwbase(dev);
|
||||
|
||||
if (np->msi_flags & NV_MSI_X_ENABLED) {
|
||||
writel(mask, base + NvRegIrqMask);
|
||||
} else {
|
||||
if (np->msi_flags & NV_MSI_ENABLED)
|
||||
writel(0, base + NvRegMSIIrqMask);
|
||||
writel(0, base + NvRegIrqMask);
|
||||
}
|
||||
}
|
||||
|
||||
#define MII_READ (-1)
|
||||
/* mii_rw: read/write a register on the PHY.
|
||||
*
|
||||
@ -1019,24 +1086,25 @@ static void nv_do_rx_refill(unsigned long data)
|
||||
struct net_device *dev = (struct net_device *) data;
|
||||
struct fe_priv *np = netdev_priv(dev);
|
||||
|
||||
|
||||
if (!(np->msi_flags & NV_MSI_X_ENABLED) ||
|
||||
((np->msi_flags & NV_MSI_X_ENABLED) &&
|
||||
((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1))) {
|
||||
disable_irq(dev->irq);
|
||||
if (!using_multi_irqs(dev)) {
|
||||
if (np->msi_flags & NV_MSI_X_ENABLED)
|
||||
disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector);
|
||||
else
|
||||
disable_irq(dev->irq);
|
||||
} else {
|
||||
disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector);
|
||||
}
|
||||
if (nv_alloc_rx(dev)) {
|
||||
spin_lock(&np->lock);
|
||||
spin_lock_irq(&np->lock);
|
||||
if (!np->in_shutdown)
|
||||
mod_timer(&np->oom_kick, jiffies + OOM_REFILL);
|
||||
spin_unlock(&np->lock);
|
||||
spin_unlock_irq(&np->lock);
|
||||
}
|
||||
if (!(np->msi_flags & NV_MSI_X_ENABLED) ||
|
||||
((np->msi_flags & NV_MSI_X_ENABLED) &&
|
||||
((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1))) {
|
||||
enable_irq(dev->irq);
|
||||
if (!using_multi_irqs(dev)) {
|
||||
if (np->msi_flags & NV_MSI_X_ENABLED)
|
||||
enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector);
|
||||
else
|
||||
enable_irq(dev->irq);
|
||||
} else {
|
||||
enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector);
|
||||
}
|
||||
@ -1668,15 +1736,7 @@ static int nv_change_mtu(struct net_device *dev, int new_mtu)
|
||||
* guessed, there is probably a simpler approach.
|
||||
* Changing the MTU is a rare event, it shouldn't matter.
|
||||
*/
|
||||
if (!(np->msi_flags & NV_MSI_X_ENABLED) ||
|
||||
((np->msi_flags & NV_MSI_X_ENABLED) &&
|
||||
((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1))) {
|
||||
disable_irq(dev->irq);
|
||||
} else {
|
||||
disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector);
|
||||
disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector);
|
||||
disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector);
|
||||
}
|
||||
nv_disable_irq(dev);
|
||||
spin_lock_bh(&dev->xmit_lock);
|
||||
spin_lock(&np->lock);
|
||||
/* stop engines */
|
||||
@ -1709,15 +1769,7 @@ static int nv_change_mtu(struct net_device *dev, int new_mtu)
|
||||
nv_start_tx(dev);
|
||||
spin_unlock(&np->lock);
|
||||
spin_unlock_bh(&dev->xmit_lock);
|
||||
if (!(np->msi_flags & NV_MSI_X_ENABLED) ||
|
||||
((np->msi_flags & NV_MSI_X_ENABLED) &&
|
||||
((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1))) {
|
||||
enable_irq(dev->irq);
|
||||
} else {
|
||||
enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector);
|
||||
enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector);
|
||||
enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector);
|
||||
}
|
||||
nv_enable_irq(dev);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -2108,16 +2160,16 @@ static irqreturn_t nv_nic_irq_tx(int foo, void *data, struct pt_regs *regs)
|
||||
if (!(events & np->irqmask))
|
||||
break;
|
||||
|
||||
spin_lock(&np->lock);
|
||||
spin_lock_irq(&np->lock);
|
||||
nv_tx_done(dev);
|
||||
spin_unlock(&np->lock);
|
||||
spin_unlock_irq(&np->lock);
|
||||
|
||||
if (events & (NVREG_IRQ_TX_ERR)) {
|
||||
dprintk(KERN_DEBUG "%s: received irq with events 0x%x. Probably TX fail.\n",
|
||||
dev->name, events);
|
||||
}
|
||||
if (i > max_interrupt_work) {
|
||||
spin_lock(&np->lock);
|
||||
spin_lock_irq(&np->lock);
|
||||
/* disable interrupts on the nic */
|
||||
writel(NVREG_IRQ_TX_ALL, base + NvRegIrqMask);
|
||||
pci_push(base);
|
||||
@ -2127,7 +2179,7 @@ static irqreturn_t nv_nic_irq_tx(int foo, void *data, struct pt_regs *regs)
|
||||
mod_timer(&np->nic_poll, jiffies + POLL_WAIT);
|
||||
}
|
||||
printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq_tx.\n", dev->name, i);
|
||||
spin_unlock(&np->lock);
|
||||
spin_unlock_irq(&np->lock);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -2157,14 +2209,14 @@ static irqreturn_t nv_nic_irq_rx(int foo, void *data, struct pt_regs *regs)
|
||||
|
||||
nv_rx_process(dev);
|
||||
if (nv_alloc_rx(dev)) {
|
||||
spin_lock(&np->lock);
|
||||
spin_lock_irq(&np->lock);
|
||||
if (!np->in_shutdown)
|
||||
mod_timer(&np->oom_kick, jiffies + OOM_REFILL);
|
||||
spin_unlock(&np->lock);
|
||||
spin_unlock_irq(&np->lock);
|
||||
}
|
||||
|
||||
if (i > max_interrupt_work) {
|
||||
spin_lock(&np->lock);
|
||||
spin_lock_irq(&np->lock);
|
||||
/* disable interrupts on the nic */
|
||||
writel(NVREG_IRQ_RX_ALL, base + NvRegIrqMask);
|
||||
pci_push(base);
|
||||
@ -2174,7 +2226,7 @@ static irqreturn_t nv_nic_irq_rx(int foo, void *data, struct pt_regs *regs)
|
||||
mod_timer(&np->nic_poll, jiffies + POLL_WAIT);
|
||||
}
|
||||
printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq_rx.\n", dev->name, i);
|
||||
spin_unlock(&np->lock);
|
||||
spin_unlock_irq(&np->lock);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -2203,14 +2255,14 @@ static irqreturn_t nv_nic_irq_other(int foo, void *data, struct pt_regs *regs)
|
||||
break;
|
||||
|
||||
if (events & NVREG_IRQ_LINK) {
|
||||
spin_lock(&np->lock);
|
||||
spin_lock_irq(&np->lock);
|
||||
nv_link_irq(dev);
|
||||
spin_unlock(&np->lock);
|
||||
spin_unlock_irq(&np->lock);
|
||||
}
|
||||
if (np->need_linktimer && time_after(jiffies, np->link_timeout)) {
|
||||
spin_lock(&np->lock);
|
||||
spin_lock_irq(&np->lock);
|
||||
nv_linkchange(dev);
|
||||
spin_unlock(&np->lock);
|
||||
spin_unlock_irq(&np->lock);
|
||||
np->link_timeout = jiffies + LINK_TIMEOUT;
|
||||
}
|
||||
if (events & (NVREG_IRQ_UNKNOWN)) {
|
||||
@ -2218,7 +2270,7 @@ static irqreturn_t nv_nic_irq_other(int foo, void *data, struct pt_regs *regs)
|
||||
dev->name, events);
|
||||
}
|
||||
if (i > max_interrupt_work) {
|
||||
spin_lock(&np->lock);
|
||||
spin_lock_irq(&np->lock);
|
||||
/* disable interrupts on the nic */
|
||||
writel(NVREG_IRQ_OTHER, base + NvRegIrqMask);
|
||||
pci_push(base);
|
||||
@ -2228,7 +2280,7 @@ static irqreturn_t nv_nic_irq_other(int foo, void *data, struct pt_regs *regs)
|
||||
mod_timer(&np->nic_poll, jiffies + POLL_WAIT);
|
||||
}
|
||||
printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq_other.\n", dev->name, i);
|
||||
spin_unlock(&np->lock);
|
||||
spin_unlock_irq(&np->lock);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -2251,10 +2303,11 @@ static void nv_do_nic_poll(unsigned long data)
|
||||
* nv_nic_irq because that may decide to do otherwise
|
||||
*/
|
||||
|
||||
if (!(np->msi_flags & NV_MSI_X_ENABLED) ||
|
||||
((np->msi_flags & NV_MSI_X_ENABLED) &&
|
||||
((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1))) {
|
||||
disable_irq(dev->irq);
|
||||
if (!using_multi_irqs(dev)) {
|
||||
if (np->msi_flags & NV_MSI_X_ENABLED)
|
||||
disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector);
|
||||
else
|
||||
disable_irq(dev->irq);
|
||||
mask = np->irqmask;
|
||||
} else {
|
||||
if (np->nic_poll_irq & NVREG_IRQ_RX_ALL) {
|
||||
@ -2277,11 +2330,12 @@ static void nv_do_nic_poll(unsigned long data)
|
||||
writel(mask, base + NvRegIrqMask);
|
||||
pci_push(base);
|
||||
|
||||
if (!(np->msi_flags & NV_MSI_X_ENABLED) ||
|
||||
((np->msi_flags & NV_MSI_X_ENABLED) &&
|
||||
((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1))) {
|
||||
if (!using_multi_irqs(dev)) {
|
||||
nv_nic_irq((int) 0, (void *) data, (struct pt_regs *) NULL);
|
||||
enable_irq(dev->irq);
|
||||
if (np->msi_flags & NV_MSI_X_ENABLED)
|
||||
enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector);
|
||||
else
|
||||
enable_irq(dev->irq);
|
||||
} else {
|
||||
if (np->nic_poll_irq & NVREG_IRQ_RX_ALL) {
|
||||
nv_nic_irq_rx((int) 0, (void *) data, (struct pt_regs *) NULL);
|
||||
@ -2628,6 +2682,113 @@ static void set_msix_vector_map(struct net_device *dev, u32 vector, u32 irqmask)
|
||||
writel(readl(base + NvRegMSIXMap1) | msixmap, base + NvRegMSIXMap1);
|
||||
}
|
||||
|
||||
static int nv_request_irq(struct net_device *dev)
|
||||
{
|
||||
struct fe_priv *np = get_nvpriv(dev);
|
||||
u8 __iomem *base = get_hwbase(dev);
|
||||
int ret = 1;
|
||||
int i;
|
||||
|
||||
if (np->msi_flags & NV_MSI_X_CAPABLE) {
|
||||
for (i = 0; i < (np->msi_flags & NV_MSI_X_VECTORS_MASK); i++) {
|
||||
np->msi_x_entry[i].entry = i;
|
||||
}
|
||||
if ((ret = pci_enable_msix(np->pci_dev, np->msi_x_entry, (np->msi_flags & NV_MSI_X_VECTORS_MASK))) == 0) {
|
||||
np->msi_flags |= NV_MSI_X_ENABLED;
|
||||
if (optimization_mode == NV_OPTIMIZATION_MODE_THROUGHPUT) {
|
||||
/* Request irq for rx handling */
|
||||
if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector, &nv_nic_irq_rx, SA_SHIRQ, dev->name, dev) != 0) {
|
||||
printk(KERN_INFO "forcedeth: request_irq failed for rx %d\n", ret);
|
||||
pci_disable_msix(np->pci_dev);
|
||||
np->msi_flags &= ~NV_MSI_X_ENABLED;
|
||||
goto out_err;
|
||||
}
|
||||
/* Request irq for tx handling */
|
||||
if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector, &nv_nic_irq_tx, SA_SHIRQ, dev->name, dev) != 0) {
|
||||
printk(KERN_INFO "forcedeth: request_irq failed for tx %d\n", ret);
|
||||
pci_disable_msix(np->pci_dev);
|
||||
np->msi_flags &= ~NV_MSI_X_ENABLED;
|
||||
goto out_free_rx;
|
||||
}
|
||||
/* Request irq for link and timer handling */
|
||||
if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector, &nv_nic_irq_other, SA_SHIRQ, dev->name, dev) != 0) {
|
||||
printk(KERN_INFO "forcedeth: request_irq failed for link %d\n", ret);
|
||||
pci_disable_msix(np->pci_dev);
|
||||
np->msi_flags &= ~NV_MSI_X_ENABLED;
|
||||
goto out_free_tx;
|
||||
}
|
||||
/* map interrupts to their respective vector */
|
||||
writel(0, base + NvRegMSIXMap0);
|
||||
writel(0, base + NvRegMSIXMap1);
|
||||
set_msix_vector_map(dev, NV_MSI_X_VECTOR_RX, NVREG_IRQ_RX_ALL);
|
||||
set_msix_vector_map(dev, NV_MSI_X_VECTOR_TX, NVREG_IRQ_TX_ALL);
|
||||
set_msix_vector_map(dev, NV_MSI_X_VECTOR_OTHER, NVREG_IRQ_OTHER);
|
||||
} else {
|
||||
/* Request irq for all interrupts */
|
||||
if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector, &nv_nic_irq, SA_SHIRQ, dev->name, dev) != 0) {
|
||||
printk(KERN_INFO "forcedeth: request_irq failed %d\n", ret);
|
||||
pci_disable_msix(np->pci_dev);
|
||||
np->msi_flags &= ~NV_MSI_X_ENABLED;
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
/* map interrupts to vector 0 */
|
||||
writel(0, base + NvRegMSIXMap0);
|
||||
writel(0, base + NvRegMSIXMap1);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ret != 0 && np->msi_flags & NV_MSI_CAPABLE) {
|
||||
if ((ret = pci_enable_msi(np->pci_dev)) == 0) {
|
||||
np->msi_flags |= NV_MSI_ENABLED;
|
||||
if (request_irq(np->pci_dev->irq, &nv_nic_irq, SA_SHIRQ, dev->name, dev) != 0) {
|
||||
printk(KERN_INFO "forcedeth: request_irq failed %d\n", ret);
|
||||
pci_disable_msi(np->pci_dev);
|
||||
np->msi_flags &= ~NV_MSI_ENABLED;
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
/* map interrupts to vector 0 */
|
||||
writel(0, base + NvRegMSIMap0);
|
||||
writel(0, base + NvRegMSIMap1);
|
||||
/* enable msi vector 0 */
|
||||
writel(NVREG_MSI_VECTOR_0_ENABLED, base + NvRegMSIIrqMask);
|
||||
}
|
||||
}
|
||||
if (ret != 0) {
|
||||
if (request_irq(np->pci_dev->irq, &nv_nic_irq, SA_SHIRQ, dev->name, dev) != 0)
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
out_free_tx:
|
||||
free_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector, dev);
|
||||
out_free_rx:
|
||||
free_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector, dev);
|
||||
out_err:
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void nv_free_irq(struct net_device *dev)
|
||||
{
|
||||
struct fe_priv *np = get_nvpriv(dev);
|
||||
int i;
|
||||
|
||||
if (np->msi_flags & NV_MSI_X_ENABLED) {
|
||||
for (i = 0; i < (np->msi_flags & NV_MSI_X_VECTORS_MASK); i++) {
|
||||
free_irq(np->msi_x_entry[i].vector, dev);
|
||||
}
|
||||
pci_disable_msix(np->pci_dev);
|
||||
np->msi_flags &= ~NV_MSI_X_ENABLED;
|
||||
} else {
|
||||
free_irq(np->pci_dev->irq, dev);
|
||||
if (np->msi_flags & NV_MSI_ENABLED) {
|
||||
pci_disable_msi(np->pci_dev);
|
||||
np->msi_flags &= ~NV_MSI_ENABLED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int nv_open(struct net_device *dev)
|
||||
{
|
||||
struct fe_priv *np = netdev_priv(dev);
|
||||
@ -2720,86 +2881,18 @@ static int nv_open(struct net_device *dev)
|
||||
udelay(10);
|
||||
writel(readl(base + NvRegPowerState) | NVREG_POWERSTATE_VALID, base + NvRegPowerState);
|
||||
|
||||
writel(0, base + NvRegIrqMask);
|
||||
nv_disable_hw_interrupts(dev, np->irqmask);
|
||||
pci_push(base);
|
||||
writel(NVREG_MIISTAT_MASK2, base + NvRegMIIStatus);
|
||||
writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus);
|
||||
pci_push(base);
|
||||
|
||||
if (np->msi_flags & NV_MSI_X_CAPABLE) {
|
||||
for (i = 0; i < (np->msi_flags & NV_MSI_X_VECTORS_MASK); i++) {
|
||||
np->msi_x_entry[i].entry = i;
|
||||
}
|
||||
if ((ret = pci_enable_msix(np->pci_dev, np->msi_x_entry, (np->msi_flags & NV_MSI_X_VECTORS_MASK))) == 0) {
|
||||
np->msi_flags |= NV_MSI_X_ENABLED;
|
||||
if (optimization_mode == NV_OPTIMIZATION_MODE_THROUGHPUT) {
|
||||
/* Request irq for rx handling */
|
||||
if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector, &nv_nic_irq_rx, SA_SHIRQ, dev->name, dev) != 0) {
|
||||
printk(KERN_INFO "forcedeth: request_irq failed for rx %d\n", ret);
|
||||
pci_disable_msix(np->pci_dev);
|
||||
np->msi_flags &= ~NV_MSI_X_ENABLED;
|
||||
goto out_drain;
|
||||
}
|
||||
/* Request irq for tx handling */
|
||||
if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector, &nv_nic_irq_tx, SA_SHIRQ, dev->name, dev) != 0) {
|
||||
printk(KERN_INFO "forcedeth: request_irq failed for tx %d\n", ret);
|
||||
pci_disable_msix(np->pci_dev);
|
||||
np->msi_flags &= ~NV_MSI_X_ENABLED;
|
||||
goto out_drain;
|
||||
}
|
||||
/* Request irq for link and timer handling */
|
||||
if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector, &nv_nic_irq_other, SA_SHIRQ, dev->name, dev) != 0) {
|
||||
printk(KERN_INFO "forcedeth: request_irq failed for link %d\n", ret);
|
||||
pci_disable_msix(np->pci_dev);
|
||||
np->msi_flags &= ~NV_MSI_X_ENABLED;
|
||||
goto out_drain;
|
||||
}
|
||||
|
||||
/* map interrupts to their respective vector */
|
||||
writel(0, base + NvRegMSIXMap0);
|
||||
writel(0, base + NvRegMSIXMap1);
|
||||
set_msix_vector_map(dev, NV_MSI_X_VECTOR_RX, NVREG_IRQ_RX_ALL);
|
||||
set_msix_vector_map(dev, NV_MSI_X_VECTOR_TX, NVREG_IRQ_TX_ALL);
|
||||
set_msix_vector_map(dev, NV_MSI_X_VECTOR_OTHER, NVREG_IRQ_OTHER);
|
||||
} else {
|
||||
/* Request irq for all interrupts */
|
||||
if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector, &nv_nic_irq, SA_SHIRQ, dev->name, dev) != 0) {
|
||||
printk(KERN_INFO "forcedeth: request_irq failed %d\n", ret);
|
||||
pci_disable_msix(np->pci_dev);
|
||||
np->msi_flags &= ~NV_MSI_X_ENABLED;
|
||||
goto out_drain;
|
||||
}
|
||||
|
||||
/* map interrupts to vector 0 */
|
||||
writel(0, base + NvRegMSIXMap0);
|
||||
writel(0, base + NvRegMSIXMap1);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ret != 0 && np->msi_flags & NV_MSI_CAPABLE) {
|
||||
if ((ret = pci_enable_msi(np->pci_dev)) == 0) {
|
||||
np->msi_flags |= NV_MSI_ENABLED;
|
||||
if (request_irq(np->pci_dev->irq, &nv_nic_irq, SA_SHIRQ, dev->name, dev) != 0) {
|
||||
printk(KERN_INFO "forcedeth: request_irq failed %d\n", ret);
|
||||
pci_disable_msi(np->pci_dev);
|
||||
np->msi_flags &= ~NV_MSI_ENABLED;
|
||||
goto out_drain;
|
||||
}
|
||||
|
||||
/* map interrupts to vector 0 */
|
||||
writel(0, base + NvRegMSIMap0);
|
||||
writel(0, base + NvRegMSIMap1);
|
||||
/* enable msi vector 0 */
|
||||
writel(NVREG_MSI_VECTOR_0_ENABLED, base + NvRegMSIIrqMask);
|
||||
}
|
||||
}
|
||||
if (ret != 0) {
|
||||
if (request_irq(np->pci_dev->irq, &nv_nic_irq, SA_SHIRQ, dev->name, dev) != 0)
|
||||
goto out_drain;
|
||||
if (nv_request_irq(dev)) {
|
||||
goto out_drain;
|
||||
}
|
||||
|
||||
/* ask for interrupts */
|
||||
writel(np->irqmask, base + NvRegIrqMask);
|
||||
nv_enable_hw_interrupts(dev, np->irqmask);
|
||||
|
||||
spin_lock_irq(&np->lock);
|
||||
writel(NVREG_MCASTADDRA_FORCE, base + NvRegMulticastAddrA);
|
||||
@ -2843,7 +2936,6 @@ static int nv_close(struct net_device *dev)
|
||||
{
|
||||
struct fe_priv *np = netdev_priv(dev);
|
||||
u8 __iomem *base;
|
||||
int i;
|
||||
|
||||
spin_lock_irq(&np->lock);
|
||||
np->in_shutdown = 1;
|
||||
@ -2861,31 +2953,13 @@ static int nv_close(struct net_device *dev)
|
||||
|
||||
/* disable interrupts on the nic or we will lock up */
|
||||
base = get_hwbase(dev);
|
||||
if (np->msi_flags & NV_MSI_X_ENABLED) {
|
||||
writel(np->irqmask, base + NvRegIrqMask);
|
||||
} else {
|
||||
if (np->msi_flags & NV_MSI_ENABLED)
|
||||
writel(0, base + NvRegMSIIrqMask);
|
||||
writel(0, base + NvRegIrqMask);
|
||||
}
|
||||
nv_disable_hw_interrupts(dev, np->irqmask);
|
||||
pci_push(base);
|
||||
dprintk(KERN_INFO "%s: Irqmask is zero again\n", dev->name);
|
||||
|
||||
spin_unlock_irq(&np->lock);
|
||||
|
||||
if (np->msi_flags & NV_MSI_X_ENABLED) {
|
||||
for (i = 0; i < (np->msi_flags & NV_MSI_X_VECTORS_MASK); i++) {
|
||||
free_irq(np->msi_x_entry[i].vector, dev);
|
||||
}
|
||||
pci_disable_msix(np->pci_dev);
|
||||
np->msi_flags &= ~NV_MSI_X_ENABLED;
|
||||
} else {
|
||||
free_irq(np->pci_dev->irq, dev);
|
||||
if (np->msi_flags & NV_MSI_ENABLED) {
|
||||
pci_disable_msi(np->pci_dev);
|
||||
np->msi_flags &= ~NV_MSI_ENABLED;
|
||||
}
|
||||
}
|
||||
nv_free_irq(dev);
|
||||
|
||||
drain_ring(dev);
|
||||
|
||||
@ -2974,20 +3048,18 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
|
||||
if (id->driver_data & DEV_HAS_HIGH_DMA) {
|
||||
/* packet format 3: supports 40-bit addressing */
|
||||
np->desc_ver = DESC_VER_3;
|
||||
np->txrxctl_bits = NVREG_TXRXCTL_DESC_3;
|
||||
if (pci_set_dma_mask(pci_dev, DMA_39BIT_MASK)) {
|
||||
printk(KERN_INFO "forcedeth: 64-bit DMA failed, using 32-bit addressing for device %s.\n",
|
||||
pci_name(pci_dev));
|
||||
} else {
|
||||
if (pci_set_consistent_dma_mask(pci_dev, 0x0000007fffffffffULL)) {
|
||||
printk(KERN_INFO "forcedeth: 64-bit DMA (consistent) failed for device %s.\n",
|
||||
pci_name(pci_dev));
|
||||
goto out_relreg;
|
||||
} else {
|
||||
dev->features |= NETIF_F_HIGHDMA;
|
||||
printk(KERN_INFO "forcedeth: using HIGHDMA\n");
|
||||
}
|
||||
dev->features |= NETIF_F_HIGHDMA;
|
||||
printk(KERN_INFO "forcedeth: using HIGHDMA\n");
|
||||
}
|
||||
if (pci_set_consistent_dma_mask(pci_dev, 0x0000007fffffffffULL)) {
|
||||
printk(KERN_INFO "forcedeth: 64-bit DMA (consistent) failed for device %s.\n",
|
||||
pci_name(pci_dev));
|
||||
}
|
||||
np->txrxctl_bits = NVREG_TXRXCTL_DESC_3;
|
||||
} else if (id->driver_data & DEV_HAS_LARGEDESC) {
|
||||
/* packet format 2: supports jumbo frames */
|
||||
np->desc_ver = DESC_VER_2;
|
||||
|
@ -69,8 +69,8 @@
|
||||
|
||||
#define DRV_MODULE_NAME "tg3"
|
||||
#define PFX DRV_MODULE_NAME ": "
|
||||
#define DRV_MODULE_VERSION "3.57"
|
||||
#define DRV_MODULE_RELDATE "Apr 28, 2006"
|
||||
#define DRV_MODULE_VERSION "3.58"
|
||||
#define DRV_MODULE_RELDATE "May 22, 2006"
|
||||
|
||||
#define TG3_DEF_MAC_MODE 0
|
||||
#define TG3_DEF_RX_MODE 0
|
||||
@ -6488,6 +6488,10 @@ static void tg3_periodic_fetch_stats(struct tg3 *tp)
|
||||
TG3_STAT_ADD32(&sp->rx_frame_too_long_errors, MAC_RX_STATS_FRAME_TOO_LONG);
|
||||
TG3_STAT_ADD32(&sp->rx_jabbers, MAC_RX_STATS_JABBERS);
|
||||
TG3_STAT_ADD32(&sp->rx_undersize_packets, MAC_RX_STATS_UNDERSIZE);
|
||||
|
||||
TG3_STAT_ADD32(&sp->rxbds_empty, RCVLPC_NO_RCV_BD_CNT);
|
||||
TG3_STAT_ADD32(&sp->rx_discards, RCVLPC_IN_DISCARDS_CNT);
|
||||
TG3_STAT_ADD32(&sp->rx_errors, RCVLPC_IN_ERRORS_CNT);
|
||||
}
|
||||
|
||||
static void tg3_timer(unsigned long __opaque)
|
||||
|
@ -757,7 +757,6 @@ static void orinoco_rx_monitor(struct net_device *dev, u16 rxfid,
|
||||
if (datalen > IEEE80211_DATA_LEN + 12) {
|
||||
printk(KERN_DEBUG "%s: oversized monitor frame, "
|
||||
"data length = %d\n", dev->name, datalen);
|
||||
err = -EIO;
|
||||
stats->rx_length_errors++;
|
||||
goto update_stats;
|
||||
}
|
||||
@ -766,8 +765,7 @@ static void orinoco_rx_monitor(struct net_device *dev, u16 rxfid,
|
||||
if (!skb) {
|
||||
printk(KERN_WARNING "%s: Cannot allocate skb for monitor frame\n",
|
||||
dev->name);
|
||||
err = -ENOMEM;
|
||||
goto drop;
|
||||
goto update_stats;
|
||||
}
|
||||
|
||||
/* Copy the 802.11 header to the skb */
|
||||
|
@ -33,13 +33,10 @@ acpi_query_osc (
|
||||
acpi_status status;
|
||||
struct acpi_object_list input;
|
||||
union acpi_object in_params[4];
|
||||
struct acpi_buffer output;
|
||||
union acpi_object out_obj;
|
||||
struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL};
|
||||
union acpi_object *out_obj;
|
||||
u32 osc_dw0;
|
||||
|
||||
/* Setting up output buffer */
|
||||
output.length = sizeof(out_obj) + 3*sizeof(u32);
|
||||
output.pointer = &out_obj;
|
||||
|
||||
/* Setting up input parameters */
|
||||
input.count = 4;
|
||||
@ -61,12 +58,15 @@ acpi_query_osc (
|
||||
"Evaluate _OSC Set fails. Status = 0x%04x\n", status);
|
||||
return status;
|
||||
}
|
||||
if (out_obj.type != ACPI_TYPE_BUFFER) {
|
||||
out_obj = output.pointer;
|
||||
|
||||
if (out_obj->type != ACPI_TYPE_BUFFER) {
|
||||
printk(KERN_DEBUG
|
||||
"Evaluate _OSC returns wrong type\n");
|
||||
return AE_TYPE;
|
||||
status = AE_TYPE;
|
||||
goto query_osc_out;
|
||||
}
|
||||
osc_dw0 = *((u32 *) out_obj.buffer.pointer);
|
||||
osc_dw0 = *((u32 *) out_obj->buffer.pointer);
|
||||
if (osc_dw0) {
|
||||
if (osc_dw0 & OSC_REQUEST_ERROR)
|
||||
printk(KERN_DEBUG "_OSC request fails\n");
|
||||
@ -76,15 +76,21 @@ acpi_query_osc (
|
||||
printk(KERN_DEBUG "_OSC invalid revision\n");
|
||||
if (osc_dw0 & OSC_CAPABILITIES_MASK_ERROR) {
|
||||
/* Update Global Control Set */
|
||||
global_ctrlsets = *((u32 *)(out_obj.buffer.pointer+8));
|
||||
return AE_OK;
|
||||
global_ctrlsets = *((u32 *)(out_obj->buffer.pointer+8));
|
||||
status = AE_OK;
|
||||
goto query_osc_out;
|
||||
}
|
||||
return AE_ERROR;
|
||||
status = AE_ERROR;
|
||||
goto query_osc_out;
|
||||
}
|
||||
|
||||
/* Update Global Control Set */
|
||||
global_ctrlsets = *((u32 *)(out_obj.buffer.pointer + 8));
|
||||
return AE_OK;
|
||||
global_ctrlsets = *((u32 *)(out_obj->buffer.pointer + 8));
|
||||
status = AE_OK;
|
||||
|
||||
query_osc_out:
|
||||
kfree(output.pointer);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
@ -96,14 +102,10 @@ acpi_run_osc (
|
||||
acpi_status status;
|
||||
struct acpi_object_list input;
|
||||
union acpi_object in_params[4];
|
||||
struct acpi_buffer output;
|
||||
union acpi_object out_obj;
|
||||
struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL};
|
||||
union acpi_object *out_obj;
|
||||
u32 osc_dw0;
|
||||
|
||||
/* Setting up output buffer */
|
||||
output.length = sizeof(out_obj) + 3*sizeof(u32);
|
||||
output.pointer = &out_obj;
|
||||
|
||||
/* Setting up input parameters */
|
||||
input.count = 4;
|
||||
input.pointer = in_params;
|
||||
@ -124,12 +126,14 @@ acpi_run_osc (
|
||||
"Evaluate _OSC Set fails. Status = 0x%04x\n", status);
|
||||
return status;
|
||||
}
|
||||
if (out_obj.type != ACPI_TYPE_BUFFER) {
|
||||
out_obj = output.pointer;
|
||||
if (out_obj->type != ACPI_TYPE_BUFFER) {
|
||||
printk(KERN_DEBUG
|
||||
"Evaluate _OSC returns wrong type\n");
|
||||
return AE_TYPE;
|
||||
status = AE_TYPE;
|
||||
goto run_osc_out;
|
||||
}
|
||||
osc_dw0 = *((u32 *) out_obj.buffer.pointer);
|
||||
osc_dw0 = *((u32 *) out_obj->buffer.pointer);
|
||||
if (osc_dw0) {
|
||||
if (osc_dw0 & OSC_REQUEST_ERROR)
|
||||
printk(KERN_DEBUG "_OSC request fails\n");
|
||||
@ -139,11 +143,17 @@ acpi_run_osc (
|
||||
printk(KERN_DEBUG "_OSC invalid revision\n");
|
||||
if (osc_dw0 & OSC_CAPABILITIES_MASK_ERROR) {
|
||||
printk(KERN_DEBUG "_OSC FW not grant req. control\n");
|
||||
return AE_SUPPORT;
|
||||
status = AE_SUPPORT;
|
||||
goto run_osc_out;
|
||||
}
|
||||
return AE_ERROR;
|
||||
status = AE_ERROR;
|
||||
goto run_osc_out;
|
||||
}
|
||||
return AE_OK;
|
||||
status = AE_OK;
|
||||
|
||||
run_osc_out:
|
||||
kfree(output.pointer);
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -589,7 +589,7 @@ static int pd6729_check_irq(int irq, int flags)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u_int __init pd6729_isa_scan(void)
|
||||
static u_int __devinit pd6729_isa_scan(void)
|
||||
{
|
||||
u_int mask0, mask = 0;
|
||||
int i;
|
||||
|
@ -141,13 +141,13 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file,
|
||||
/* try the driver's ioctl interface */
|
||||
if (ops->ioctl) {
|
||||
err = ops->ioctl(class_dev->dev, cmd, arg);
|
||||
if (err != -EINVAL)
|
||||
if (err != -ENOIOCTLCMD)
|
||||
return err;
|
||||
}
|
||||
|
||||
/* if the driver does not provide the ioctl interface
|
||||
* or if that particular ioctl was not implemented
|
||||
* (-EINVAL), we will try to emulate here.
|
||||
* (-ENOIOCTLCMD), we will try to emulate here.
|
||||
*/
|
||||
|
||||
switch (cmd) {
|
||||
@ -233,7 +233,7 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file,
|
||||
break;
|
||||
|
||||
default:
|
||||
err = -EINVAL;
|
||||
err = -ENOTTY;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -247,7 +247,7 @@ static int sa1100_rtc_ioctl(struct device *dev, unsigned int cmd,
|
||||
rtc_freq = arg;
|
||||
return 0;
|
||||
}
|
||||
return -EINVAL;
|
||||
return -ENOIOCTLCMD;
|
||||
}
|
||||
|
||||
static int sa1100_rtc_read_time(struct device *dev, struct rtc_time *tm)
|
||||
|
@ -71,7 +71,7 @@ static int test_rtc_ioctl(struct device *dev, unsigned int cmd,
|
||||
return 0;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
return -ENOIOCTLCMD;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -270,7 +270,7 @@ static int vr41xx_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long
|
||||
epoch = arg;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
return -ENOIOCTLCMD;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -864,6 +864,9 @@ static unsigned int ata_id_xfermask(const u16 *id)
|
||||
/**
|
||||
* ata_port_queue_task - Queue port_task
|
||||
* @ap: The ata_port to queue port_task for
|
||||
* @fn: workqueue function to be scheduled
|
||||
* @data: data value to pass to workqueue function
|
||||
* @delay: delay time for workqueue function
|
||||
*
|
||||
* Schedule @fn(@data) for execution after @delay jiffies using
|
||||
* port_task. There is one port_task per port and it's the
|
||||
@ -2739,6 +2742,8 @@ static unsigned int ata_dev_set_xfermode(struct ata_port *ap,
|
||||
* ata_dev_init_params - Issue INIT DEV PARAMS command
|
||||
* @ap: Port associated with device @dev
|
||||
* @dev: Device to which command will be sent
|
||||
* @heads: Number of heads (taskfile parameter)
|
||||
* @sectors: Number of sectors (taskfile parameter)
|
||||
*
|
||||
* LOCKING:
|
||||
* Kernel thread context (may sleep)
|
||||
@ -4302,6 +4307,7 @@ int ata_device_resume(struct ata_port *ap, struct ata_device *dev)
|
||||
* ata_device_suspend - prepare a device for suspend
|
||||
* @ap: port the device is connected to
|
||||
* @dev: the device to suspend
|
||||
* @state: target power management state
|
||||
*
|
||||
* Flush the cache on the drive, if appropriate, then issue a
|
||||
* standbynow command.
|
||||
|
@ -37,7 +37,7 @@
|
||||
#include <asm/io.h>
|
||||
|
||||
#define DRV_NAME "sata_mv"
|
||||
#define DRV_VERSION "0.6"
|
||||
#define DRV_VERSION "0.7"
|
||||
|
||||
enum {
|
||||
/* BAR's are enumerated in terms of pci_resource_start() terms */
|
||||
@ -50,6 +50,12 @@ enum {
|
||||
|
||||
MV_PCI_REG_BASE = 0,
|
||||
MV_IRQ_COAL_REG_BASE = 0x18000, /* 6xxx part only */
|
||||
MV_IRQ_COAL_CAUSE = (MV_IRQ_COAL_REG_BASE + 0x08),
|
||||
MV_IRQ_COAL_CAUSE_LO = (MV_IRQ_COAL_REG_BASE + 0x88),
|
||||
MV_IRQ_COAL_CAUSE_HI = (MV_IRQ_COAL_REG_BASE + 0x8c),
|
||||
MV_IRQ_COAL_THRESHOLD = (MV_IRQ_COAL_REG_BASE + 0xcc),
|
||||
MV_IRQ_COAL_TIME_THRESHOLD = (MV_IRQ_COAL_REG_BASE + 0xd0),
|
||||
|
||||
MV_SATAHC0_REG_BASE = 0x20000,
|
||||
MV_FLASH_CTL = 0x1046c,
|
||||
MV_GPIO_PORT_CTL = 0x104f0,
|
||||
@ -302,9 +308,6 @@ struct mv_port_priv {
|
||||
dma_addr_t crpb_dma;
|
||||
struct mv_sg *sg_tbl;
|
||||
dma_addr_t sg_tbl_dma;
|
||||
|
||||
unsigned req_producer; /* cp of req_in_ptr */
|
||||
unsigned rsp_consumer; /* cp of rsp_out_ptr */
|
||||
u32 pp_flags;
|
||||
};
|
||||
|
||||
@ -937,8 +940,6 @@ static int mv_port_start(struct ata_port *ap)
|
||||
writelfl(pp->crpb_dma & EDMA_RSP_Q_BASE_LO_MASK,
|
||||
port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
|
||||
|
||||
pp->req_producer = pp->rsp_consumer = 0;
|
||||
|
||||
/* Don't turn on EDMA here...do it before DMA commands only. Else
|
||||
* we'll be unable to send non-data, PIO, etc due to restricted access
|
||||
* to shadow regs.
|
||||
@ -1022,16 +1023,16 @@ static void mv_fill_sg(struct ata_queued_cmd *qc)
|
||||
}
|
||||
}
|
||||
|
||||
static inline unsigned mv_inc_q_index(unsigned *index)
|
||||
static inline unsigned mv_inc_q_index(unsigned index)
|
||||
{
|
||||
*index = (*index + 1) & MV_MAX_Q_DEPTH_MASK;
|
||||
return *index;
|
||||
return (index + 1) & MV_MAX_Q_DEPTH_MASK;
|
||||
}
|
||||
|
||||
static inline void mv_crqb_pack_cmd(u16 *cmdw, u8 data, u8 addr, unsigned last)
|
||||
{
|
||||
*cmdw = data | (addr << CRQB_CMD_ADDR_SHIFT) | CRQB_CMD_CS |
|
||||
u16 tmp = data | (addr << CRQB_CMD_ADDR_SHIFT) | CRQB_CMD_CS |
|
||||
(last ? CRQB_CMD_LAST : 0);
|
||||
*cmdw = cpu_to_le16(tmp);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1053,15 +1054,11 @@ static void mv_qc_prep(struct ata_queued_cmd *qc)
|
||||
u16 *cw;
|
||||
struct ata_taskfile *tf;
|
||||
u16 flags = 0;
|
||||
unsigned in_index;
|
||||
|
||||
if (ATA_PROT_DMA != qc->tf.protocol)
|
||||
return;
|
||||
|
||||
/* the req producer index should be the same as we remember it */
|
||||
WARN_ON(((readl(mv_ap_base(qc->ap) + EDMA_REQ_Q_IN_PTR_OFS) >>
|
||||
EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) !=
|
||||
pp->req_producer);
|
||||
|
||||
/* Fill in command request block
|
||||
*/
|
||||
if (!(qc->tf.flags & ATA_TFLAG_WRITE))
|
||||
@ -1069,13 +1066,17 @@ static void mv_qc_prep(struct ata_queued_cmd *qc)
|
||||
WARN_ON(MV_MAX_Q_DEPTH <= qc->tag);
|
||||
flags |= qc->tag << CRQB_TAG_SHIFT;
|
||||
|
||||
pp->crqb[pp->req_producer].sg_addr =
|
||||
cpu_to_le32(pp->sg_tbl_dma & 0xffffffff);
|
||||
pp->crqb[pp->req_producer].sg_addr_hi =
|
||||
cpu_to_le32((pp->sg_tbl_dma >> 16) >> 16);
|
||||
pp->crqb[pp->req_producer].ctrl_flags = cpu_to_le16(flags);
|
||||
/* get current queue index from hardware */
|
||||
in_index = (readl(mv_ap_base(ap) + EDMA_REQ_Q_IN_PTR_OFS)
|
||||
>> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK;
|
||||
|
||||
cw = &pp->crqb[pp->req_producer].ata_cmd[0];
|
||||
pp->crqb[in_index].sg_addr =
|
||||
cpu_to_le32(pp->sg_tbl_dma & 0xffffffff);
|
||||
pp->crqb[in_index].sg_addr_hi =
|
||||
cpu_to_le32((pp->sg_tbl_dma >> 16) >> 16);
|
||||
pp->crqb[in_index].ctrl_flags = cpu_to_le16(flags);
|
||||
|
||||
cw = &pp->crqb[in_index].ata_cmd[0];
|
||||
tf = &qc->tf;
|
||||
|
||||
/* Sadly, the CRQB cannot accomodate all registers--there are
|
||||
@ -1144,16 +1145,12 @@ static void mv_qc_prep_iie(struct ata_queued_cmd *qc)
|
||||
struct mv_port_priv *pp = ap->private_data;
|
||||
struct mv_crqb_iie *crqb;
|
||||
struct ata_taskfile *tf;
|
||||
unsigned in_index;
|
||||
u32 flags = 0;
|
||||
|
||||
if (ATA_PROT_DMA != qc->tf.protocol)
|
||||
return;
|
||||
|
||||
/* the req producer index should be the same as we remember it */
|
||||
WARN_ON(((readl(mv_ap_base(qc->ap) + EDMA_REQ_Q_IN_PTR_OFS) >>
|
||||
EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) !=
|
||||
pp->req_producer);
|
||||
|
||||
/* Fill in Gen IIE command request block
|
||||
*/
|
||||
if (!(qc->tf.flags & ATA_TFLAG_WRITE))
|
||||
@ -1162,7 +1159,11 @@ static void mv_qc_prep_iie(struct ata_queued_cmd *qc)
|
||||
WARN_ON(MV_MAX_Q_DEPTH <= qc->tag);
|
||||
flags |= qc->tag << CRQB_TAG_SHIFT;
|
||||
|
||||
crqb = (struct mv_crqb_iie *) &pp->crqb[pp->req_producer];
|
||||
/* get current queue index from hardware */
|
||||
in_index = (readl(mv_ap_base(ap) + EDMA_REQ_Q_IN_PTR_OFS)
|
||||
>> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK;
|
||||
|
||||
crqb = (struct mv_crqb_iie *) &pp->crqb[in_index];
|
||||
crqb->addr = cpu_to_le32(pp->sg_tbl_dma & 0xffffffff);
|
||||
crqb->addr_hi = cpu_to_le32((pp->sg_tbl_dma >> 16) >> 16);
|
||||
crqb->flags = cpu_to_le32(flags);
|
||||
@ -1210,6 +1211,7 @@ static unsigned int mv_qc_issue(struct ata_queued_cmd *qc)
|
||||
{
|
||||
void __iomem *port_mmio = mv_ap_base(qc->ap);
|
||||
struct mv_port_priv *pp = qc->ap->private_data;
|
||||
unsigned in_index;
|
||||
u32 in_ptr;
|
||||
|
||||
if (ATA_PROT_DMA != qc->tf.protocol) {
|
||||
@ -1221,23 +1223,20 @@ static unsigned int mv_qc_issue(struct ata_queued_cmd *qc)
|
||||
return ata_qc_issue_prot(qc);
|
||||
}
|
||||
|
||||
in_ptr = readl(port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
|
||||
in_ptr = readl(port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
|
||||
in_index = (in_ptr >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK;
|
||||
|
||||
/* the req producer index should be the same as we remember it */
|
||||
WARN_ON(((in_ptr >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) !=
|
||||
pp->req_producer);
|
||||
/* until we do queuing, the queue should be empty at this point */
|
||||
WARN_ON(((in_ptr >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) !=
|
||||
((readl(port_mmio + EDMA_REQ_Q_OUT_PTR_OFS) >>
|
||||
EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK));
|
||||
WARN_ON(in_index != ((readl(port_mmio + EDMA_REQ_Q_OUT_PTR_OFS)
|
||||
>> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK));
|
||||
|
||||
mv_inc_q_index(&pp->req_producer); /* now incr producer index */
|
||||
in_index = mv_inc_q_index(in_index); /* now incr producer index */
|
||||
|
||||
mv_start_dma(port_mmio, pp);
|
||||
|
||||
/* and write the request in pointer to kick the EDMA to life */
|
||||
in_ptr &= EDMA_REQ_Q_BASE_LO_MASK;
|
||||
in_ptr |= pp->req_producer << EDMA_REQ_Q_PTR_SHIFT;
|
||||
in_ptr |= in_index << EDMA_REQ_Q_PTR_SHIFT;
|
||||
writelfl(in_ptr, port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
|
||||
|
||||
return 0;
|
||||
@ -1260,28 +1259,26 @@ static u8 mv_get_crpb_status(struct ata_port *ap)
|
||||
{
|
||||
void __iomem *port_mmio = mv_ap_base(ap);
|
||||
struct mv_port_priv *pp = ap->private_data;
|
||||
unsigned out_index;
|
||||
u32 out_ptr;
|
||||
u8 ata_status;
|
||||
|
||||
out_ptr = readl(port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
|
||||
out_ptr = readl(port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
|
||||
out_index = (out_ptr >> EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK;
|
||||
|
||||
/* the response consumer index should be the same as we remember it */
|
||||
WARN_ON(((out_ptr >> EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) !=
|
||||
pp->rsp_consumer);
|
||||
|
||||
ata_status = pp->crpb[pp->rsp_consumer].flags >> CRPB_FLAG_STATUS_SHIFT;
|
||||
ata_status = le16_to_cpu(pp->crpb[out_index].flags)
|
||||
>> CRPB_FLAG_STATUS_SHIFT;
|
||||
|
||||
/* increment our consumer index... */
|
||||
pp->rsp_consumer = mv_inc_q_index(&pp->rsp_consumer);
|
||||
out_index = mv_inc_q_index(out_index);
|
||||
|
||||
/* and, until we do NCQ, there should only be 1 CRPB waiting */
|
||||
WARN_ON(((readl(port_mmio + EDMA_RSP_Q_IN_PTR_OFS) >>
|
||||
EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) !=
|
||||
pp->rsp_consumer);
|
||||
WARN_ON(out_index != ((readl(port_mmio + EDMA_RSP_Q_IN_PTR_OFS)
|
||||
>> EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK));
|
||||
|
||||
/* write out our inc'd consumer index so EDMA knows we're caught up */
|
||||
out_ptr &= EDMA_RSP_Q_BASE_LO_MASK;
|
||||
out_ptr |= pp->rsp_consumer << EDMA_RSP_Q_PTR_SHIFT;
|
||||
out_ptr |= out_index << EDMA_RSP_Q_PTR_SHIFT;
|
||||
writelfl(out_ptr, port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
|
||||
|
||||
/* Return ATA status register for completed CRPB */
|
||||
@ -1291,6 +1288,7 @@ static u8 mv_get_crpb_status(struct ata_port *ap)
|
||||
/**
|
||||
* mv_err_intr - Handle error interrupts on the port
|
||||
* @ap: ATA channel to manipulate
|
||||
* @reset_allowed: bool: 0 == don't trigger from reset here
|
||||
*
|
||||
* In most cases, just clear the interrupt and move on. However,
|
||||
* some cases require an eDMA reset, which is done right before
|
||||
@ -1301,7 +1299,7 @@ static u8 mv_get_crpb_status(struct ata_port *ap)
|
||||
* LOCKING:
|
||||
* Inherited from caller.
|
||||
*/
|
||||
static void mv_err_intr(struct ata_port *ap)
|
||||
static void mv_err_intr(struct ata_port *ap, int reset_allowed)
|
||||
{
|
||||
void __iomem *port_mmio = mv_ap_base(ap);
|
||||
u32 edma_err_cause, serr = 0;
|
||||
@ -1323,9 +1321,8 @@ static void mv_err_intr(struct ata_port *ap)
|
||||
writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
|
||||
|
||||
/* check for fatal here and recover if needed */
|
||||
if (EDMA_ERR_FATAL & edma_err_cause) {
|
||||
if (reset_allowed && (EDMA_ERR_FATAL & edma_err_cause))
|
||||
mv_stop_and_reset(ap);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1374,12 +1371,12 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant,
|
||||
struct ata_port *ap = host_set->ports[port];
|
||||
struct mv_port_priv *pp = ap->private_data;
|
||||
|
||||
hard_port = port & MV_PORT_MASK; /* range 0-3 */
|
||||
hard_port = mv_hardport_from_port(port); /* range 0..3 */
|
||||
handled = 0; /* ensure ata_status is set if handled++ */
|
||||
|
||||
/* Note that DEV_IRQ might happen spuriously during EDMA,
|
||||
* and should be ignored in such cases. We could mask it,
|
||||
* but it's pretty rare and may not be worth the overhead.
|
||||
* and should be ignored in such cases.
|
||||
* The cause of this is still under investigation.
|
||||
*/
|
||||
if (pp->pp_flags & MV_PP_FLAG_EDMA_EN) {
|
||||
/* EDMA: check for response queue interrupt */
|
||||
@ -1393,6 +1390,11 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant,
|
||||
ata_status = readb((void __iomem *)
|
||||
ap->ioaddr.status_addr);
|
||||
handled = 1;
|
||||
/* ignore spurious intr if drive still BUSY */
|
||||
if (ata_status & ATA_BUSY) {
|
||||
ata_status = 0;
|
||||
handled = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1406,7 +1408,7 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant,
|
||||
shift++; /* skip bit 8 in the HC Main IRQ reg */
|
||||
}
|
||||
if ((PORT0_ERR << shift) & relevant) {
|
||||
mv_err_intr(ap);
|
||||
mv_err_intr(ap, 1);
|
||||
err_mask |= AC_ERR_OTHER;
|
||||
handled = 1;
|
||||
}
|
||||
@ -1448,6 +1450,7 @@ static irqreturn_t mv_interrupt(int irq, void *dev_instance,
|
||||
struct ata_host_set *host_set = dev_instance;
|
||||
unsigned int hc, handled = 0, n_hcs;
|
||||
void __iomem *mmio = host_set->mmio_base;
|
||||
struct mv_host_priv *hpriv;
|
||||
u32 irq_stat;
|
||||
|
||||
irq_stat = readl(mmio + HC_MAIN_IRQ_CAUSE_OFS);
|
||||
@ -1469,6 +1472,17 @@ static irqreturn_t mv_interrupt(int irq, void *dev_instance,
|
||||
handled++;
|
||||
}
|
||||
}
|
||||
|
||||
hpriv = host_set->private_data;
|
||||
if (IS_60XX(hpriv)) {
|
||||
/* deal with the interrupt coalescing bits */
|
||||
if (irq_stat & (TRAN_LO_DONE | TRAN_HI_DONE | PORTS_0_7_COAL_DONE)) {
|
||||
writelfl(0, mmio + MV_IRQ_COAL_CAUSE_LO);
|
||||
writelfl(0, mmio + MV_IRQ_COAL_CAUSE_HI);
|
||||
writelfl(0, mmio + MV_IRQ_COAL_CAUSE);
|
||||
}
|
||||
}
|
||||
|
||||
if (PCI_ERR & irq_stat) {
|
||||
printk(KERN_ERR DRV_NAME ": PCI ERROR; PCI IRQ cause=0x%08x\n",
|
||||
readl(mmio + PCI_IRQ_CAUSE_OFS));
|
||||
@ -1867,7 +1881,8 @@ static void mv_channel_reset(struct mv_host_priv *hpriv, void __iomem *mmio,
|
||||
|
||||
if (IS_60XX(hpriv)) {
|
||||
u32 ifctl = readl(port_mmio + SATA_INTERFACE_CTL);
|
||||
ifctl |= (1 << 12) | (1 << 7);
|
||||
ifctl |= (1 << 7); /* enable gen2i speed */
|
||||
ifctl = (ifctl & 0xfff) | 0x9b1000; /* from chip spec */
|
||||
writelfl(ifctl, port_mmio + SATA_INTERFACE_CTL);
|
||||
}
|
||||
|
||||
@ -2031,11 +2046,14 @@ static void mv_eng_timeout(struct ata_port *ap)
|
||||
ap->host_set->mmio_base, ap, qc, qc->scsicmd,
|
||||
&qc->scsicmd->cmnd);
|
||||
|
||||
mv_err_intr(ap);
|
||||
mv_err_intr(ap, 0);
|
||||
mv_stop_and_reset(ap);
|
||||
|
||||
qc->err_mask |= AC_ERR_TIMEOUT;
|
||||
ata_eh_qc_complete(qc);
|
||||
WARN_ON(!(qc->flags & ATA_QCFLAG_ACTIVE));
|
||||
if (qc->flags & ATA_QCFLAG_ACTIVE) {
|
||||
qc->err_mask |= AC_ERR_TIMEOUT;
|
||||
ata_eh_qc_complete(qc);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2229,7 +2247,8 @@ static int mv_init_host(struct pci_dev *pdev, struct ata_probe_ent *probe_ent,
|
||||
void __iomem *port_mmio = mv_port_base(mmio, port);
|
||||
|
||||
u32 ifctl = readl(port_mmio + SATA_INTERFACE_CTL);
|
||||
ifctl |= (1 << 12);
|
||||
ifctl |= (1 << 7); /* enable gen2i speed */
|
||||
ifctl = (ifctl & 0xfff) | 0x9b1000; /* from chip spec */
|
||||
writelfl(ifctl, port_mmio + SATA_INTERFACE_CTL);
|
||||
}
|
||||
|
||||
@ -2330,6 +2349,7 @@ static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
if (rc) {
|
||||
return rc;
|
||||
}
|
||||
pci_set_master(pdev);
|
||||
|
||||
rc = pci_request_regions(pdev, DRV_NAME);
|
||||
if (rc) {
|
||||
|
@ -4054,7 +4054,7 @@ static int st_probe(struct device *dev)
|
||||
}
|
||||
|
||||
sdev_printk(KERN_WARNING, SDp,
|
||||
"Attached scsi tape %s", tape_name(tpnt));
|
||||
"Attached scsi tape %s\n", tape_name(tpnt));
|
||||
printk(KERN_WARNING "%s: try direct i/o: %s (alignment %d B)\n",
|
||||
tape_name(tpnt), tpnt->try_dio ? "yes" : "no",
|
||||
queue_dma_alignment(SDp->request_queue) + 1);
|
||||
|
@ -1730,3 +1730,4 @@ static void __exit sunsu_exit(void)
|
||||
|
||||
module_init(sunsu_probe);
|
||||
module_exit(sunsu_exit);
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -75,6 +75,18 @@ config SPI_BUTTERFLY
|
||||
inexpensive battery powered microcontroller evaluation board.
|
||||
This same cable can be used to flash new firmware.
|
||||
|
||||
config SPI_MPC83xx
|
||||
tristate "Freescale MPC83xx SPI controller"
|
||||
depends on SPI_MASTER && PPC_83xx && EXPERIMENTAL
|
||||
select SPI_BITBANG
|
||||
help
|
||||
This enables using the Freescale MPC83xx SPI controller in master
|
||||
mode.
|
||||
|
||||
Note, this driver uniquely supports the SPI controller on the MPC83xx
|
||||
family of PowerPC processors. The MPC83xx uses a simple set of shift
|
||||
registers for data (opposed to the CPM based descriptor model).
|
||||
|
||||
config SPI_PXA2XX
|
||||
tristate "PXA2xx SSP SPI master"
|
||||
depends on SPI_MASTER && ARCH_PXA && EXPERIMENTAL
|
||||
@ -83,11 +95,25 @@ config SPI_PXA2XX
|
||||
The driver can be configured to use any SSP port and additional
|
||||
documentation can be found a Documentation/spi/pxa2xx.
|
||||
|
||||
config SPI_S3C24XX_GPIO
|
||||
tristate "Samsung S3C24XX series SPI by GPIO"
|
||||
depends on SPI_MASTER && ARCH_S3C2410 && SPI_BITBANG && EXPERIMENTAL
|
||||
help
|
||||
SPI driver for Samsung S3C24XX series ARM SoCs using
|
||||
GPIO lines to provide the SPI bus. This can be used where
|
||||
the inbuilt hardware cannot provide the transfer mode, or
|
||||
where the board is using non hardware connected pins.
|
||||
#
|
||||
# Add new SPI master controllers in alphabetical order above this line
|
||||
#
|
||||
|
||||
|
||||
config SPI_S3C24XX
|
||||
tristate "Samsung S3C24XX series SPI"
|
||||
depends on SPI_MASTER && ARCH_S3C2410 && EXPERIMENTAL
|
||||
help
|
||||
SPI driver for Samsung S3C24XX series ARM SoCs
|
||||
|
||||
#
|
||||
# There are lots of SPI device types, with sensors and memory
|
||||
# being probably the most widely used ones.
|
||||
|
@ -14,6 +14,9 @@ obj-$(CONFIG_SPI_MASTER) += spi.o
|
||||
obj-$(CONFIG_SPI_BITBANG) += spi_bitbang.o
|
||||
obj-$(CONFIG_SPI_BUTTERFLY) += spi_butterfly.o
|
||||
obj-$(CONFIG_SPI_PXA2XX) += pxa2xx_spi.o
|
||||
obj-$(CONFIG_SPI_MPC83xx) += spi_mpc83xx.o
|
||||
obj-$(CONFIG_SPI_S3C24XX_GPIO) += spi_s3c24xx_gpio.o
|
||||
obj-$(CONFIG_SPI_S3C24XX) += spi_s3c24xx.o
|
||||
# ... add above this line ...
|
||||
|
||||
# SPI protocol drivers (device/link on bus)
|
||||
|
@ -363,25 +363,30 @@ static void unmap_dma_buffers(struct driver_data *drv_data)
|
||||
}
|
||||
|
||||
/* caller already set message->status; dma and pio irqs are blocked */
|
||||
static void giveback(struct spi_message *message, struct driver_data *drv_data)
|
||||
static void giveback(struct driver_data *drv_data)
|
||||
{
|
||||
struct spi_transfer* last_transfer;
|
||||
unsigned long flags;
|
||||
struct spi_message *msg;
|
||||
|
||||
last_transfer = list_entry(message->transfers.prev,
|
||||
spin_lock_irqsave(&drv_data->lock, flags);
|
||||
msg = drv_data->cur_msg;
|
||||
drv_data->cur_msg = NULL;
|
||||
drv_data->cur_transfer = NULL;
|
||||
drv_data->cur_chip = NULL;
|
||||
queue_work(drv_data->workqueue, &drv_data->pump_messages);
|
||||
spin_unlock_irqrestore(&drv_data->lock, flags);
|
||||
|
||||
last_transfer = list_entry(msg->transfers.prev,
|
||||
struct spi_transfer,
|
||||
transfer_list);
|
||||
|
||||
if (!last_transfer->cs_change)
|
||||
drv_data->cs_control(PXA2XX_CS_DEASSERT);
|
||||
|
||||
message->state = NULL;
|
||||
if (message->complete)
|
||||
message->complete(message->context);
|
||||
|
||||
drv_data->cur_msg = NULL;
|
||||
drv_data->cur_transfer = NULL;
|
||||
drv_data->cur_chip = NULL;
|
||||
queue_work(drv_data->workqueue, &drv_data->pump_messages);
|
||||
msg->state = NULL;
|
||||
if (msg->complete)
|
||||
msg->complete(msg->context);
|
||||
}
|
||||
|
||||
static int wait_ssp_rx_stall(void *ioaddr)
|
||||
@ -415,10 +420,11 @@ static void dma_handler(int channel, void *data, struct pt_regs *regs)
|
||||
if (irq_status & DCSR_BUSERR) {
|
||||
|
||||
/* Disable interrupts, clear status and reset DMA */
|
||||
write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg);
|
||||
write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg);
|
||||
if (drv_data->ssp_type != PXA25x_SSP)
|
||||
write_SSTO(0, reg);
|
||||
write_SSSR(drv_data->clear_sr, reg);
|
||||
write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg);
|
||||
DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
|
||||
DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
|
||||
|
||||
@ -454,8 +460,8 @@ static void dma_handler(int channel, void *data, struct pt_regs *regs)
|
||||
"dma_handler: ssp rx stall failed\n");
|
||||
|
||||
/* Clear and disable interrupts on SSP and DMA channels*/
|
||||
write_SSSR(drv_data->clear_sr, reg);
|
||||
write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg);
|
||||
write_SSSR(drv_data->clear_sr, reg);
|
||||
DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
|
||||
DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
|
||||
if (wait_dma_channel_stop(drv_data->rx_channel) == 0)
|
||||
@ -497,10 +503,11 @@ static irqreturn_t dma_transfer(struct driver_data *drv_data)
|
||||
irq_status = read_SSSR(reg) & drv_data->mask_sr;
|
||||
if (irq_status & SSSR_ROR) {
|
||||
/* Clear and disable interrupts on SSP and DMA channels*/
|
||||
write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg);
|
||||
write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg);
|
||||
if (drv_data->ssp_type != PXA25x_SSP)
|
||||
write_SSTO(0, reg);
|
||||
write_SSSR(drv_data->clear_sr, reg);
|
||||
write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg);
|
||||
DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
|
||||
DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
|
||||
unmap_dma_buffers(drv_data);
|
||||
@ -526,10 +533,10 @@ static irqreturn_t dma_transfer(struct driver_data *drv_data)
|
||||
if (irq_status & SSSR_TINT || drv_data->rx == drv_data->rx_end) {
|
||||
|
||||
/* Clear and disable interrupts on SSP and DMA channels*/
|
||||
write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg);
|
||||
if (drv_data->ssp_type != PXA25x_SSP)
|
||||
write_SSTO(0, reg);
|
||||
write_SSSR(drv_data->clear_sr, reg);
|
||||
write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg);
|
||||
DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
|
||||
DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
|
||||
|
||||
@ -572,26 +579,30 @@ static irqreturn_t dma_transfer(struct driver_data *drv_data)
|
||||
|
||||
static irqreturn_t interrupt_transfer(struct driver_data *drv_data)
|
||||
{
|
||||
u32 irq_status;
|
||||
struct spi_message *msg = drv_data->cur_msg;
|
||||
void *reg = drv_data->ioaddr;
|
||||
irqreturn_t handled = IRQ_NONE;
|
||||
unsigned long limit = loops_per_jiffy << 1;
|
||||
u32 irq_status;
|
||||
u32 irq_mask = (read_SSCR1(reg) & SSCR1_TIE) ?
|
||||
drv_data->mask_sr : drv_data->mask_sr & ~SSSR_TFS;
|
||||
|
||||
while ((irq_status = (read_SSSR(reg) & drv_data->mask_sr))) {
|
||||
while ((irq_status = read_SSSR(reg) & irq_mask)) {
|
||||
|
||||
if (irq_status & SSSR_ROR) {
|
||||
|
||||
/* Clear and disable interrupts */
|
||||
write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg);
|
||||
write_SSCR1(read_SSCR1(reg) & ~drv_data->int_cr1, reg);
|
||||
if (drv_data->ssp_type != PXA25x_SSP)
|
||||
write_SSTO(0, reg);
|
||||
write_SSSR(drv_data->clear_sr, reg);
|
||||
write_SSCR1(read_SSCR1(reg) & ~drv_data->int_cr1, reg);
|
||||
|
||||
if (flush(drv_data) == 0)
|
||||
dev_err(&drv_data->pdev->dev,
|
||||
"interrupt_transfer: flush fail\n");
|
||||
|
||||
/* Stop the SSP */
|
||||
|
||||
dev_warn(&drv_data->pdev->dev,
|
||||
"interrupt_transfer: fifo overun\n");
|
||||
|
||||
@ -613,6 +624,7 @@ static irqreturn_t interrupt_transfer(struct driver_data *drv_data)
|
||||
if (drv_data->tx == drv_data->tx_end) {
|
||||
/* Disable tx interrupt */
|
||||
write_SSCR1(read_SSCR1(reg) & ~SSCR1_TIE, reg);
|
||||
irq_mask = drv_data->mask_sr & ~SSSR_TFS;
|
||||
|
||||
/* PXA25x_SSP has no timeout, read trailing bytes */
|
||||
if (drv_data->ssp_type == PXA25x_SSP) {
|
||||
@ -630,10 +642,10 @@ static irqreturn_t interrupt_transfer(struct driver_data *drv_data)
|
||||
|| (drv_data->rx == drv_data->rx_end)) {
|
||||
|
||||
/* Clear timeout */
|
||||
write_SSCR1(read_SSCR1(reg) & ~drv_data->int_cr1, reg);
|
||||
if (drv_data->ssp_type != PXA25x_SSP)
|
||||
write_SSTO(0, reg);
|
||||
write_SSSR(drv_data->clear_sr, reg);
|
||||
write_SSCR1(read_SSCR1(reg) & ~drv_data->int_cr1, reg);
|
||||
|
||||
/* Update total byte transfered */
|
||||
msg->actual_length += drv_data->len;
|
||||
@ -648,24 +660,29 @@ static irqreturn_t interrupt_transfer(struct driver_data *drv_data)
|
||||
|
||||
/* Schedule transfer tasklet */
|
||||
tasklet_schedule(&drv_data->pump_transfers);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/* We did something */
|
||||
handled = IRQ_HANDLED;
|
||||
}
|
||||
|
||||
return handled;
|
||||
/* We did something */
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t ssp_int(int irq, void *dev_id, struct pt_regs *regs)
|
||||
{
|
||||
struct driver_data *drv_data = (struct driver_data *)dev_id;
|
||||
void *reg = drv_data->ioaddr;
|
||||
|
||||
if (!drv_data->cur_msg) {
|
||||
|
||||
write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg);
|
||||
write_SSCR1(read_SSCR1(reg) & ~drv_data->int_cr1, reg);
|
||||
if (drv_data->ssp_type != PXA25x_SSP)
|
||||
write_SSTO(0, reg);
|
||||
write_SSSR(drv_data->clear_sr, reg);
|
||||
|
||||
dev_err(&drv_data->pdev->dev, "bad message state "
|
||||
"in interrupt handler\n");
|
||||
"in interrupt handler");
|
||||
|
||||
/* Never fail */
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
@ -694,14 +711,14 @@ static void pump_transfers(unsigned long data)
|
||||
/* Handle for abort */
|
||||
if (message->state == ERROR_STATE) {
|
||||
message->status = -EIO;
|
||||
giveback(message, drv_data);
|
||||
giveback(drv_data);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Handle end of message */
|
||||
if (message->state == DONE_STATE) {
|
||||
message->status = 0;
|
||||
giveback(message, drv_data);
|
||||
giveback(drv_data);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -718,7 +735,7 @@ static void pump_transfers(unsigned long data)
|
||||
if (flush(drv_data) == 0) {
|
||||
dev_err(&drv_data->pdev->dev, "pump_transfers: flush failed\n");
|
||||
message->status = -EIO;
|
||||
giveback(message, drv_data);
|
||||
giveback(drv_data);
|
||||
return;
|
||||
}
|
||||
drv_data->n_bytes = chip->n_bytes;
|
||||
@ -782,7 +799,7 @@ static void pump_transfers(unsigned long data)
|
||||
|
||||
cr0 = clk_div
|
||||
| SSCR0_Motorola
|
||||
| SSCR0_DataSize(bits & 0x0f)
|
||||
| SSCR0_DataSize(bits > 16 ? bits - 16 : bits)
|
||||
| SSCR0_SSE
|
||||
| (bits > 16 ? SSCR0_EDSS : 0);
|
||||
|
||||
@ -890,8 +907,6 @@ static void pump_messages(void *data)
|
||||
drv_data->cur_msg = list_entry(drv_data->queue.next,
|
||||
struct spi_message, queue);
|
||||
list_del_init(&drv_data->cur_msg->queue);
|
||||
drv_data->busy = 1;
|
||||
spin_unlock_irqrestore(&drv_data->lock, flags);
|
||||
|
||||
/* Initial message state*/
|
||||
drv_data->cur_msg->state = START_STATE;
|
||||
@ -905,6 +920,9 @@ static void pump_messages(void *data)
|
||||
|
||||
/* Mark as busy and launch transfers */
|
||||
tasklet_schedule(&drv_data->pump_transfers);
|
||||
|
||||
drv_data->busy = 1;
|
||||
spin_unlock_irqrestore(&drv_data->lock, flags);
|
||||
}
|
||||
|
||||
static int transfer(struct spi_device *spi, struct spi_message *msg)
|
||||
@ -958,7 +976,7 @@ static int setup(struct spi_device *spi)
|
||||
|
||||
chip->cs_control = null_cs_control;
|
||||
chip->enable_dma = 0;
|
||||
chip->timeout = 5;
|
||||
chip->timeout = SSP_TIMEOUT(1000);
|
||||
chip->threshold = SSCR1_RxTresh(1) | SSCR1_TxTresh(1);
|
||||
chip->dma_burst_size = drv_data->master_info->enable_dma ?
|
||||
DCMD_BURST8 : 0;
|
||||
@ -971,7 +989,7 @@ static int setup(struct spi_device *spi)
|
||||
if (chip_info->cs_control)
|
||||
chip->cs_control = chip_info->cs_control;
|
||||
|
||||
chip->timeout = (chip_info->timeout_microsecs * 10000) / 2712;
|
||||
chip->timeout = SSP_TIMEOUT(chip_info->timeout_microsecs);
|
||||
|
||||
chip->threshold = SSCR1_RxTresh(chip_info->rx_threshold)
|
||||
| SSCR1_TxTresh(chip_info->tx_threshold);
|
||||
@ -1013,7 +1031,8 @@ static int setup(struct spi_device *spi)
|
||||
|
||||
chip->cr0 = clk_div
|
||||
| SSCR0_Motorola
|
||||
| SSCR0_DataSize(spi->bits_per_word & 0x0f)
|
||||
| SSCR0_DataSize(spi->bits_per_word > 16 ?
|
||||
spi->bits_per_word - 16 : spi->bits_per_word)
|
||||
| SSCR0_SSE
|
||||
| (spi->bits_per_word > 16 ? SSCR0_EDSS : 0);
|
||||
chip->cr1 |= (((spi->mode & SPI_CPHA) != 0) << 4)
|
||||
@ -1196,7 +1215,7 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
|
||||
goto out_error_master_alloc;
|
||||
}
|
||||
|
||||
drv_data->ioaddr = (void *)io_p2v(memory_resource->start);
|
||||
drv_data->ioaddr = (void *)io_p2v((unsigned long)(memory_resource->start));
|
||||
drv_data->ssdr_physical = memory_resource->start + 0x00000010;
|
||||
if (platform_info->ssp_type == PXA25x_SSP) {
|
||||
drv_data->int_cr1 = SSCR1_TIE | SSCR1_RIE;
|
||||
@ -1218,7 +1237,7 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
|
||||
goto out_error_master_alloc;
|
||||
}
|
||||
|
||||
status = request_irq(irq, ssp_int, SA_INTERRUPT, dev->bus_id, drv_data);
|
||||
status = request_irq(irq, ssp_int, 0, dev->bus_id, drv_data);
|
||||
if (status < 0) {
|
||||
dev_err(&pdev->dev, "can not get IRQ\n");
|
||||
goto out_error_master_alloc;
|
||||
|
@ -338,18 +338,18 @@ static struct class spi_master_class = {
|
||||
* spi_alloc_master - allocate SPI master controller
|
||||
* @dev: the controller, possibly using the platform_bus
|
||||
* @size: how much driver-private data to preallocate; the pointer to this
|
||||
* memory is in the class_data field of the returned class_device,
|
||||
* memory is in the class_data field of the returned class_device,
|
||||
* accessible with spi_master_get_devdata().
|
||||
*
|
||||
* This call is used only by SPI master controller drivers, which are the
|
||||
* only ones directly touching chip registers. It's how they allocate
|
||||
* an spi_master structure, prior to calling spi_add_master().
|
||||
* an spi_master structure, prior to calling spi_register_master().
|
||||
*
|
||||
* This must be called from context that can sleep. It returns the SPI
|
||||
* master structure on success, else NULL.
|
||||
*
|
||||
* The caller is responsible for assigning the bus number and initializing
|
||||
* the master's methods before calling spi_add_master(); and (after errors
|
||||
* the master's methods before calling spi_register_master(); and (after errors
|
||||
* adding the device) calling spi_master_put() to prevent a memory leak.
|
||||
*/
|
||||
struct spi_master * __init_or_module
|
||||
|
@ -321,6 +321,7 @@ static void butterfly_attach(struct parport *p)
|
||||
* (firmware resets at45, acts as spi slave) or neither (we ignore
|
||||
* both, AVR uses AT45). Here we expect firmware for the first option.
|
||||
*/
|
||||
|
||||
pp->info[0].max_speed_hz = 15 * 1000 * 1000;
|
||||
strcpy(pp->info[0].modalias, "mtd_dataflash");
|
||||
pp->info[0].platform_data = &flash;
|
||||
|
483
drivers/spi/spi_mpc83xx.c
Normal file
483
drivers/spi/spi_mpc83xx.c
Normal file
@ -0,0 +1,483 @@
|
||||
/*
|
||||
* MPC83xx SPI controller driver.
|
||||
*
|
||||
* Maintainer: Kumar Gala
|
||||
*
|
||||
* Copyright (C) 2006 Polycom, Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/spi/spi_bitbang.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/fsl_devices.h>
|
||||
|
||||
#include <asm/irq.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
/* SPI Controller registers */
|
||||
struct mpc83xx_spi_reg {
|
||||
u8 res1[0x20];
|
||||
__be32 mode;
|
||||
__be32 event;
|
||||
__be32 mask;
|
||||
__be32 command;
|
||||
__be32 transmit;
|
||||
__be32 receive;
|
||||
};
|
||||
|
||||
/* SPI Controller mode register definitions */
|
||||
#define SPMODE_CI_INACTIVEHIGH (1 << 29)
|
||||
#define SPMODE_CP_BEGIN_EDGECLK (1 << 28)
|
||||
#define SPMODE_DIV16 (1 << 27)
|
||||
#define SPMODE_REV (1 << 26)
|
||||
#define SPMODE_MS (1 << 25)
|
||||
#define SPMODE_ENABLE (1 << 24)
|
||||
#define SPMODE_LEN(x) ((x) << 20)
|
||||
#define SPMODE_PM(x) ((x) << 16)
|
||||
|
||||
/*
|
||||
* Default for SPI Mode:
|
||||
* SPI MODE 0 (inactive low, phase middle, MSB, 8-bit length, slow clk
|
||||
*/
|
||||
#define SPMODE_INIT_VAL (SPMODE_CI_INACTIVEHIGH | SPMODE_DIV16 | SPMODE_REV | \
|
||||
SPMODE_MS | SPMODE_LEN(7) | SPMODE_PM(0xf))
|
||||
|
||||
/* SPIE register values */
|
||||
#define SPIE_NE 0x00000200 /* Not empty */
|
||||
#define SPIE_NF 0x00000100 /* Not full */
|
||||
|
||||
/* SPIM register values */
|
||||
#define SPIM_NE 0x00000200 /* Not empty */
|
||||
#define SPIM_NF 0x00000100 /* Not full */
|
||||
|
||||
/* SPI Controller driver's private data. */
|
||||
struct mpc83xx_spi {
|
||||
/* bitbang has to be first */
|
||||
struct spi_bitbang bitbang;
|
||||
struct completion done;
|
||||
|
||||
struct mpc83xx_spi_reg __iomem *base;
|
||||
|
||||
/* rx & tx bufs from the spi_transfer */
|
||||
const void *tx;
|
||||
void *rx;
|
||||
|
||||
/* functions to deal with different sized buffers */
|
||||
void (*get_rx) (u32 rx_data, struct mpc83xx_spi *);
|
||||
u32(*get_tx) (struct mpc83xx_spi *);
|
||||
|
||||
unsigned int count;
|
||||
u32 irq;
|
||||
|
||||
unsigned nsecs; /* (clock cycle time)/2 */
|
||||
|
||||
u32 sysclk;
|
||||
void (*activate_cs) (u8 cs, u8 polarity);
|
||||
void (*deactivate_cs) (u8 cs, u8 polarity);
|
||||
};
|
||||
|
||||
static inline void mpc83xx_spi_write_reg(__be32 __iomem * reg, u32 val)
|
||||
{
|
||||
out_be32(reg, val);
|
||||
}
|
||||
|
||||
static inline u32 mpc83xx_spi_read_reg(__be32 __iomem * reg)
|
||||
{
|
||||
return in_be32(reg);
|
||||
}
|
||||
|
||||
#define MPC83XX_SPI_RX_BUF(type) \
|
||||
void mpc83xx_spi_rx_buf_##type(u32 data, struct mpc83xx_spi *mpc83xx_spi) \
|
||||
{ \
|
||||
type * rx = mpc83xx_spi->rx; \
|
||||
*rx++ = (type)data; \
|
||||
mpc83xx_spi->rx = rx; \
|
||||
}
|
||||
|
||||
#define MPC83XX_SPI_TX_BUF(type) \
|
||||
u32 mpc83xx_spi_tx_buf_##type(struct mpc83xx_spi *mpc83xx_spi) \
|
||||
{ \
|
||||
u32 data; \
|
||||
const type * tx = mpc83xx_spi->tx; \
|
||||
data = *tx++; \
|
||||
mpc83xx_spi->tx = tx; \
|
||||
return data; \
|
||||
}
|
||||
|
||||
MPC83XX_SPI_RX_BUF(u8)
|
||||
MPC83XX_SPI_RX_BUF(u16)
|
||||
MPC83XX_SPI_RX_BUF(u32)
|
||||
MPC83XX_SPI_TX_BUF(u8)
|
||||
MPC83XX_SPI_TX_BUF(u16)
|
||||
MPC83XX_SPI_TX_BUF(u32)
|
||||
|
||||
static void mpc83xx_spi_chipselect(struct spi_device *spi, int value)
|
||||
{
|
||||
struct mpc83xx_spi *mpc83xx_spi;
|
||||
u8 pol = spi->mode & SPI_CS_HIGH ? 1 : 0;
|
||||
|
||||
mpc83xx_spi = spi_master_get_devdata(spi->master);
|
||||
|
||||
if (value == BITBANG_CS_INACTIVE) {
|
||||
if (mpc83xx_spi->deactivate_cs)
|
||||
mpc83xx_spi->deactivate_cs(spi->chip_select, pol);
|
||||
}
|
||||
|
||||
if (value == BITBANG_CS_ACTIVE) {
|
||||
u32 regval = mpc83xx_spi_read_reg(&mpc83xx_spi->base->mode);
|
||||
u32 len = spi->bits_per_word;
|
||||
if (len == 32)
|
||||
len = 0;
|
||||
else
|
||||
len = len - 1;
|
||||
|
||||
/* mask out bits we are going to set */
|
||||
regval &= ~0x38ff0000;
|
||||
|
||||
if (spi->mode & SPI_CPHA)
|
||||
regval |= SPMODE_CP_BEGIN_EDGECLK;
|
||||
if (spi->mode & SPI_CPOL)
|
||||
regval |= SPMODE_CI_INACTIVEHIGH;
|
||||
|
||||
regval |= SPMODE_LEN(len);
|
||||
|
||||
if ((mpc83xx_spi->sysclk / spi->max_speed_hz) >= 64) {
|
||||
u8 pm = mpc83xx_spi->sysclk / (spi->max_speed_hz * 64);
|
||||
regval |= SPMODE_PM(pm) | SPMODE_DIV16;
|
||||
} else {
|
||||
u8 pm = mpc83xx_spi->sysclk / (spi->max_speed_hz * 4);
|
||||
regval |= SPMODE_PM(pm);
|
||||
}
|
||||
|
||||
mpc83xx_spi_write_reg(&mpc83xx_spi->base->mode, regval);
|
||||
if (mpc83xx_spi->activate_cs)
|
||||
mpc83xx_spi->activate_cs(spi->chip_select, pol);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
int mpc83xx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
|
||||
{
|
||||
struct mpc83xx_spi *mpc83xx_spi;
|
||||
u32 regval;
|
||||
u8 bits_per_word;
|
||||
u32 hz;
|
||||
|
||||
mpc83xx_spi = spi_master_get_devdata(spi->master);
|
||||
|
||||
if (t) {
|
||||
bits_per_word = t->bits_per_word;
|
||||
hz = t->speed_hz;
|
||||
} else {
|
||||
bits_per_word = 0;
|
||||
hz = 0;
|
||||
}
|
||||
|
||||
/* spi_transfer level calls that work per-word */
|
||||
if (!bits_per_word)
|
||||
bits_per_word = spi->bits_per_word;
|
||||
|
||||
/* Make sure its a bit width we support [4..16, 32] */
|
||||
if ((bits_per_word < 4)
|
||||
|| ((bits_per_word > 16) && (bits_per_word != 32)))
|
||||
return -EINVAL;
|
||||
|
||||
if (bits_per_word <= 8) {
|
||||
mpc83xx_spi->get_rx = mpc83xx_spi_rx_buf_u8;
|
||||
mpc83xx_spi->get_tx = mpc83xx_spi_tx_buf_u8;
|
||||
} else if (bits_per_word <= 16) {
|
||||
mpc83xx_spi->get_rx = mpc83xx_spi_rx_buf_u16;
|
||||
mpc83xx_spi->get_tx = mpc83xx_spi_tx_buf_u16;
|
||||
} else if (bits_per_word <= 32) {
|
||||
mpc83xx_spi->get_rx = mpc83xx_spi_rx_buf_u32;
|
||||
mpc83xx_spi->get_tx = mpc83xx_spi_tx_buf_u32;
|
||||
} else
|
||||
return -EINVAL;
|
||||
|
||||
/* nsecs = (clock period)/2 */
|
||||
if (!hz)
|
||||
hz = spi->max_speed_hz;
|
||||
mpc83xx_spi->nsecs = (1000000000 / 2) / hz;
|
||||
if (mpc83xx_spi->nsecs > MAX_UDELAY_MS * 1000)
|
||||
return -EINVAL;
|
||||
|
||||
if (bits_per_word == 32)
|
||||
bits_per_word = 0;
|
||||
else
|
||||
bits_per_word = bits_per_word - 1;
|
||||
|
||||
regval = mpc83xx_spi_read_reg(&mpc83xx_spi->base->mode);
|
||||
|
||||
/* Mask out bits_per_wordgth */
|
||||
regval &= 0xff0fffff;
|
||||
regval |= SPMODE_LEN(bits_per_word);
|
||||
|
||||
mpc83xx_spi_write_reg(&mpc83xx_spi->base->mode, regval);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mpc83xx_spi_setup(struct spi_device *spi)
|
||||
{
|
||||
struct spi_bitbang *bitbang;
|
||||
struct mpc83xx_spi *mpc83xx_spi;
|
||||
int retval;
|
||||
|
||||
if (!spi->max_speed_hz)
|
||||
return -EINVAL;
|
||||
|
||||
bitbang = spi_master_get_devdata(spi->master);
|
||||
mpc83xx_spi = spi_master_get_devdata(spi->master);
|
||||
|
||||
if (!spi->bits_per_word)
|
||||
spi->bits_per_word = 8;
|
||||
|
||||
retval = mpc83xx_spi_setup_transfer(spi, NULL);
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
|
||||
dev_dbg(&spi->dev, "%s, mode %d, %u bits/w, %u nsec\n",
|
||||
__FUNCTION__, spi->mode & (SPI_CPOL | SPI_CPHA),
|
||||
spi->bits_per_word, 2 * mpc83xx_spi->nsecs);
|
||||
|
||||
/* NOTE we _need_ to call chipselect() early, ideally with adapter
|
||||
* setup, unless the hardware defaults cooperate to avoid confusion
|
||||
* between normal (active low) and inverted chipselects.
|
||||
*/
|
||||
|
||||
/* deselect chip (low or high) */
|
||||
spin_lock(&bitbang->lock);
|
||||
if (!bitbang->busy) {
|
||||
bitbang->chipselect(spi, BITBANG_CS_INACTIVE);
|
||||
ndelay(mpc83xx_spi->nsecs);
|
||||
}
|
||||
spin_unlock(&bitbang->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mpc83xx_spi_bufs(struct spi_device *spi, struct spi_transfer *t)
|
||||
{
|
||||
struct mpc83xx_spi *mpc83xx_spi;
|
||||
u32 word;
|
||||
|
||||
mpc83xx_spi = spi_master_get_devdata(spi->master);
|
||||
|
||||
mpc83xx_spi->tx = t->tx_buf;
|
||||
mpc83xx_spi->rx = t->rx_buf;
|
||||
mpc83xx_spi->count = t->len;
|
||||
INIT_COMPLETION(mpc83xx_spi->done);
|
||||
|
||||
/* enable rx ints */
|
||||
mpc83xx_spi_write_reg(&mpc83xx_spi->base->mask, SPIM_NE);
|
||||
|
||||
/* transmit word */
|
||||
word = mpc83xx_spi->get_tx(mpc83xx_spi);
|
||||
mpc83xx_spi_write_reg(&mpc83xx_spi->base->transmit, word);
|
||||
|
||||
wait_for_completion(&mpc83xx_spi->done);
|
||||
|
||||
/* disable rx ints */
|
||||
mpc83xx_spi_write_reg(&mpc83xx_spi->base->mask, 0);
|
||||
|
||||
return t->len - mpc83xx_spi->count;
|
||||
}
|
||||
|
||||
irqreturn_t mpc83xx_spi_irq(s32 irq, void *context_data,
|
||||
struct pt_regs * ptregs)
|
||||
{
|
||||
struct mpc83xx_spi *mpc83xx_spi = context_data;
|
||||
u32 event;
|
||||
irqreturn_t ret = IRQ_NONE;
|
||||
|
||||
/* Get interrupt events(tx/rx) */
|
||||
event = mpc83xx_spi_read_reg(&mpc83xx_spi->base->event);
|
||||
|
||||
/* We need handle RX first */
|
||||
if (event & SPIE_NE) {
|
||||
u32 rx_data = mpc83xx_spi_read_reg(&mpc83xx_spi->base->receive);
|
||||
|
||||
if (mpc83xx_spi->rx)
|
||||
mpc83xx_spi->get_rx(rx_data, mpc83xx_spi);
|
||||
|
||||
ret = IRQ_HANDLED;
|
||||
}
|
||||
|
||||
if ((event & SPIE_NF) == 0)
|
||||
/* spin until TX is done */
|
||||
while (((event =
|
||||
mpc83xx_spi_read_reg(&mpc83xx_spi->base->event)) &
|
||||
SPIE_NF) == 0)
|
||||
cpu_relax();
|
||||
|
||||
mpc83xx_spi->count -= 1;
|
||||
if (mpc83xx_spi->count) {
|
||||
if (mpc83xx_spi->tx) {
|
||||
u32 word = mpc83xx_spi->get_tx(mpc83xx_spi);
|
||||
mpc83xx_spi_write_reg(&mpc83xx_spi->base->transmit,
|
||||
word);
|
||||
}
|
||||
} else {
|
||||
complete(&mpc83xx_spi->done);
|
||||
}
|
||||
|
||||
/* Clear the events */
|
||||
mpc83xx_spi_write_reg(&mpc83xx_spi->base->event, event);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __init mpc83xx_spi_probe(struct platform_device *dev)
|
||||
{
|
||||
struct spi_master *master;
|
||||
struct mpc83xx_spi *mpc83xx_spi;
|
||||
struct fsl_spi_platform_data *pdata;
|
||||
struct resource *r;
|
||||
u32 regval;
|
||||
int ret = 0;
|
||||
|
||||
/* Get resources(memory, IRQ) associated with the device */
|
||||
master = spi_alloc_master(&dev->dev, sizeof(struct mpc83xx_spi));
|
||||
|
||||
if (master == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
platform_set_drvdata(dev, master);
|
||||
pdata = dev->dev.platform_data;
|
||||
|
||||
if (pdata == NULL) {
|
||||
ret = -ENODEV;
|
||||
goto free_master;
|
||||
}
|
||||
|
||||
r = platform_get_resource(dev, IORESOURCE_MEM, 0);
|
||||
if (r == NULL) {
|
||||
ret = -ENODEV;
|
||||
goto free_master;
|
||||
}
|
||||
|
||||
mpc83xx_spi = spi_master_get_devdata(master);
|
||||
mpc83xx_spi->bitbang.master = spi_master_get(master);
|
||||
mpc83xx_spi->bitbang.chipselect = mpc83xx_spi_chipselect;
|
||||
mpc83xx_spi->bitbang.setup_transfer = mpc83xx_spi_setup_transfer;
|
||||
mpc83xx_spi->bitbang.txrx_bufs = mpc83xx_spi_bufs;
|
||||
mpc83xx_spi->sysclk = pdata->sysclk;
|
||||
mpc83xx_spi->activate_cs = pdata->activate_cs;
|
||||
mpc83xx_spi->deactivate_cs = pdata->deactivate_cs;
|
||||
mpc83xx_spi->get_rx = mpc83xx_spi_rx_buf_u8;
|
||||
mpc83xx_spi->get_tx = mpc83xx_spi_tx_buf_u8;
|
||||
|
||||
mpc83xx_spi->bitbang.master->setup = mpc83xx_spi_setup;
|
||||
init_completion(&mpc83xx_spi->done);
|
||||
|
||||
mpc83xx_spi->base = ioremap(r->start, r->end - r->start + 1);
|
||||
if (mpc83xx_spi->base == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto put_master;
|
||||
}
|
||||
|
||||
mpc83xx_spi->irq = platform_get_irq(dev, 0);
|
||||
|
||||
if (mpc83xx_spi->irq < 0) {
|
||||
ret = -ENXIO;
|
||||
goto unmap_io;
|
||||
}
|
||||
|
||||
/* Register for SPI Interrupt */
|
||||
ret = request_irq(mpc83xx_spi->irq, mpc83xx_spi_irq,
|
||||
0, "mpc83xx_spi", mpc83xx_spi);
|
||||
|
||||
if (ret != 0)
|
||||
goto unmap_io;
|
||||
|
||||
master->bus_num = pdata->bus_num;
|
||||
master->num_chipselect = pdata->max_chipselect;
|
||||
|
||||
/* SPI controller initializations */
|
||||
mpc83xx_spi_write_reg(&mpc83xx_spi->base->mode, 0);
|
||||
mpc83xx_spi_write_reg(&mpc83xx_spi->base->mask, 0);
|
||||
mpc83xx_spi_write_reg(&mpc83xx_spi->base->command, 0);
|
||||
mpc83xx_spi_write_reg(&mpc83xx_spi->base->event, 0xffffffff);
|
||||
|
||||
/* Enable SPI interface */
|
||||
regval = pdata->initial_spmode | SPMODE_INIT_VAL | SPMODE_ENABLE;
|
||||
mpc83xx_spi_write_reg(&mpc83xx_spi->base->mode, regval);
|
||||
|
||||
ret = spi_bitbang_start(&mpc83xx_spi->bitbang);
|
||||
|
||||
if (ret != 0)
|
||||
goto free_irq;
|
||||
|
||||
printk(KERN_INFO
|
||||
"%s: MPC83xx SPI Controller driver at 0x%p (irq = %d)\n",
|
||||
dev->dev.bus_id, mpc83xx_spi->base, mpc83xx_spi->irq);
|
||||
|
||||
return ret;
|
||||
|
||||
free_irq:
|
||||
free_irq(mpc83xx_spi->irq, mpc83xx_spi);
|
||||
unmap_io:
|
||||
iounmap(mpc83xx_spi->base);
|
||||
put_master:
|
||||
spi_master_put(master);
|
||||
free_master:
|
||||
kfree(master);
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit mpc83xx_spi_remove(struct platform_device *dev)
|
||||
{
|
||||
struct mpc83xx_spi *mpc83xx_spi;
|
||||
struct spi_master *master;
|
||||
|
||||
master = platform_get_drvdata(dev);
|
||||
mpc83xx_spi = spi_master_get_devdata(master);
|
||||
|
||||
spi_bitbang_stop(&mpc83xx_spi->bitbang);
|
||||
free_irq(mpc83xx_spi->irq, mpc83xx_spi);
|
||||
iounmap(mpc83xx_spi->base);
|
||||
spi_master_put(mpc83xx_spi->bitbang.master);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver mpc83xx_spi_driver = {
|
||||
.probe = mpc83xx_spi_probe,
|
||||
.remove = __devexit_p(mpc83xx_spi_remove),
|
||||
.driver = {
|
||||
.name = "mpc83xx_spi",
|
||||
},
|
||||
};
|
||||
|
||||
static int __init mpc83xx_spi_init(void)
|
||||
{
|
||||
return platform_driver_register(&mpc83xx_spi_driver);
|
||||
}
|
||||
|
||||
static void __exit mpc83xx_spi_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&mpc83xx_spi_driver);
|
||||
}
|
||||
|
||||
module_init(mpc83xx_spi_init);
|
||||
module_exit(mpc83xx_spi_exit);
|
||||
|
||||
MODULE_AUTHOR("Kumar Gala");
|
||||
MODULE_DESCRIPTION("Simple MPC83xx SPI Driver");
|
||||
MODULE_LICENSE("GPL");
|
453
drivers/spi/spi_s3c24xx.c
Normal file
453
drivers/spi/spi_s3c24xx.c
Normal file
@ -0,0 +1,453 @@
|
||||
/* linux/drivers/spi/spi_s3c24xx.c
|
||||
*
|
||||
* Copyright (c) 2006 Ben Dooks
|
||||
* Copyright (c) 2006 Simtec Electronics
|
||||
* Ben Dooks <ben@simtec.co.uk>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
//#define DEBUG
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/spi/spi_bitbang.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/dma.h>
|
||||
#include <asm/hardware.h>
|
||||
|
||||
#include <asm/arch/regs-gpio.h>
|
||||
#include <asm/arch/regs-spi.h>
|
||||
#include <asm/arch/spi.h>
|
||||
|
||||
struct s3c24xx_spi {
|
||||
/* bitbang has to be first */
|
||||
struct spi_bitbang bitbang;
|
||||
struct completion done;
|
||||
|
||||
void __iomem *regs;
|
||||
int irq;
|
||||
int len;
|
||||
int count;
|
||||
|
||||
/* data buffers */
|
||||
const unsigned char *tx;
|
||||
unsigned char *rx;
|
||||
|
||||
struct clk *clk;
|
||||
struct resource *ioarea;
|
||||
struct spi_master *master;
|
||||
struct spi_device *curdev;
|
||||
struct device *dev;
|
||||
struct s3c2410_spi_info *pdata;
|
||||
};
|
||||
|
||||
#define SPCON_DEFAULT (S3C2410_SPCON_MSTR | S3C2410_SPCON_SMOD_INT)
|
||||
#define SPPIN_DEFAULT (S3C2410_SPPIN_KEEP)
|
||||
|
||||
static inline struct s3c24xx_spi *to_hw(struct spi_device *sdev)
|
||||
{
|
||||
return spi_master_get_devdata(sdev->master);
|
||||
}
|
||||
|
||||
static void s3c24xx_spi_chipsel(struct spi_device *spi, int value)
|
||||
{
|
||||
struct s3c24xx_spi *hw = to_hw(spi);
|
||||
unsigned int cspol = spi->mode & SPI_CS_HIGH ? 1 : 0;
|
||||
unsigned int spcon;
|
||||
|
||||
switch (value) {
|
||||
case BITBANG_CS_INACTIVE:
|
||||
if (hw->pdata->set_cs)
|
||||
hw->pdata->set_cs(hw->pdata, value, cspol);
|
||||
else
|
||||
s3c2410_gpio_setpin(hw->pdata->pin_cs, cspol ^ 1);
|
||||
break;
|
||||
|
||||
case BITBANG_CS_ACTIVE:
|
||||
spcon = readb(hw->regs + S3C2410_SPCON);
|
||||
|
||||
if (spi->mode & SPI_CPHA)
|
||||
spcon |= S3C2410_SPCON_CPHA_FMTB;
|
||||
else
|
||||
spcon &= ~S3C2410_SPCON_CPHA_FMTB;
|
||||
|
||||
if (spi->mode & SPI_CPOL)
|
||||
spcon |= S3C2410_SPCON_CPOL_HIGH;
|
||||
else
|
||||
spcon &= ~S3C2410_SPCON_CPOL_HIGH;
|
||||
|
||||
spcon |= S3C2410_SPCON_ENSCK;
|
||||
|
||||
/* write new configration */
|
||||
|
||||
writeb(spcon, hw->regs + S3C2410_SPCON);
|
||||
|
||||
if (hw->pdata->set_cs)
|
||||
hw->pdata->set_cs(hw->pdata, value, cspol);
|
||||
else
|
||||
s3c2410_gpio_setpin(hw->pdata->pin_cs, cspol);
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static int s3c24xx_spi_setupxfer(struct spi_device *spi,
|
||||
struct spi_transfer *t)
|
||||
{
|
||||
struct s3c24xx_spi *hw = to_hw(spi);
|
||||
unsigned int bpw;
|
||||
unsigned int hz;
|
||||
unsigned int div;
|
||||
|
||||
bpw = t ? t->bits_per_word : spi->bits_per_word;
|
||||
hz = t ? t->speed_hz : spi->max_speed_hz;
|
||||
|
||||
if (bpw != 8) {
|
||||
dev_err(&spi->dev, "invalid bits-per-word (%d)\n", bpw);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
div = clk_get_rate(hw->clk) / hz;
|
||||
|
||||
/* is clk = pclk / (2 * (pre+1)), or is it
|
||||
* clk = (pclk * 2) / ( pre + 1) */
|
||||
|
||||
div = (div / 2) - 1;
|
||||
|
||||
if (div < 0)
|
||||
div = 1;
|
||||
|
||||
if (div > 255)
|
||||
div = 255;
|
||||
|
||||
dev_dbg(&spi->dev, "setting pre-scaler to %d (hz %d)\n", div, hz);
|
||||
writeb(div, hw->regs + S3C2410_SPPRE);
|
||||
|
||||
spin_lock(&hw->bitbang.lock);
|
||||
if (!hw->bitbang.busy) {
|
||||
hw->bitbang.chipselect(spi, BITBANG_CS_INACTIVE);
|
||||
/* need to ndelay for 0.5 clocktick ? */
|
||||
}
|
||||
spin_unlock(&hw->bitbang.lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s3c24xx_spi_setup(struct spi_device *spi)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!spi->bits_per_word)
|
||||
spi->bits_per_word = 8;
|
||||
|
||||
if ((spi->mode & SPI_LSB_FIRST) != 0)
|
||||
return -EINVAL;
|
||||
|
||||
ret = s3c24xx_spi_setupxfer(spi, NULL);
|
||||
if (ret < 0) {
|
||||
dev_err(&spi->dev, "setupxfer returned %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
dev_dbg(&spi->dev, "%s: mode %d, %u bpw, %d hz\n",
|
||||
__FUNCTION__, spi->mode, spi->bits_per_word,
|
||||
spi->max_speed_hz);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline unsigned int hw_txbyte(struct s3c24xx_spi *hw, int count)
|
||||
{
|
||||
return hw->tx ? hw->tx[count] : 0xff;
|
||||
}
|
||||
|
||||
static int s3c24xx_spi_txrx(struct spi_device *spi, struct spi_transfer *t)
|
||||
{
|
||||
struct s3c24xx_spi *hw = to_hw(spi);
|
||||
|
||||
dev_dbg(&spi->dev, "txrx: tx %p, rx %p, len %d\n",
|
||||
t->tx_buf, t->rx_buf, t->len);
|
||||
|
||||
hw->tx = t->tx_buf;
|
||||
hw->rx = t->rx_buf;
|
||||
hw->len = t->len;
|
||||
hw->count = 0;
|
||||
|
||||
/* send the first byte */
|
||||
writeb(hw_txbyte(hw, 0), hw->regs + S3C2410_SPTDAT);
|
||||
wait_for_completion(&hw->done);
|
||||
|
||||
return hw->count;
|
||||
}
|
||||
|
||||
static irqreturn_t s3c24xx_spi_irq(int irq, void *dev, struct pt_regs *regs)
|
||||
{
|
||||
struct s3c24xx_spi *hw = dev;
|
||||
unsigned int spsta = readb(hw->regs + S3C2410_SPSTA);
|
||||
unsigned int count = hw->count;
|
||||
|
||||
if (spsta & S3C2410_SPSTA_DCOL) {
|
||||
dev_dbg(hw->dev, "data-collision\n");
|
||||
complete(&hw->done);
|
||||
goto irq_done;
|
||||
}
|
||||
|
||||
if (!(spsta & S3C2410_SPSTA_READY)) {
|
||||
dev_dbg(hw->dev, "spi not ready for tx?\n");
|
||||
complete(&hw->done);
|
||||
goto irq_done;
|
||||
}
|
||||
|
||||
hw->count++;
|
||||
|
||||
if (hw->rx)
|
||||
hw->rx[count] = readb(hw->regs + S3C2410_SPRDAT);
|
||||
|
||||
count++;
|
||||
|
||||
if (count < hw->len)
|
||||
writeb(hw_txbyte(hw, count), hw->regs + S3C2410_SPTDAT);
|
||||
else
|
||||
complete(&hw->done);
|
||||
|
||||
irq_done:
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int s3c24xx_spi_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct s3c24xx_spi *hw;
|
||||
struct spi_master *master;
|
||||
struct spi_board_info *bi;
|
||||
struct resource *res;
|
||||
int err = 0;
|
||||
int i;
|
||||
|
||||
master = spi_alloc_master(&pdev->dev, sizeof(struct s3c24xx_spi));
|
||||
if (master == NULL) {
|
||||
dev_err(&pdev->dev, "No memory for spi_master\n");
|
||||
err = -ENOMEM;
|
||||
goto err_nomem;
|
||||
}
|
||||
|
||||
hw = spi_master_get_devdata(master);
|
||||
memset(hw, 0, sizeof(struct s3c24xx_spi));
|
||||
|
||||
hw->master = spi_master_get(master);
|
||||
hw->pdata = pdev->dev.platform_data;
|
||||
hw->dev = &pdev->dev;
|
||||
|
||||
if (hw->pdata == NULL) {
|
||||
dev_err(&pdev->dev, "No platform data supplied\n");
|
||||
err = -ENOENT;
|
||||
goto err_no_pdata;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, hw);
|
||||
init_completion(&hw->done);
|
||||
|
||||
/* setup the state for the bitbang driver */
|
||||
|
||||
hw->bitbang.master = hw->master;
|
||||
hw->bitbang.setup_transfer = s3c24xx_spi_setupxfer;
|
||||
hw->bitbang.chipselect = s3c24xx_spi_chipsel;
|
||||
hw->bitbang.txrx_bufs = s3c24xx_spi_txrx;
|
||||
hw->bitbang.master->setup = s3c24xx_spi_setup;
|
||||
|
||||
dev_dbg(hw->dev, "bitbang at %p\n", &hw->bitbang);
|
||||
|
||||
/* find and map our resources */
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (res == NULL) {
|
||||
dev_err(&pdev->dev, "Cannot get IORESOURCE_MEM\n");
|
||||
err = -ENOENT;
|
||||
goto err_no_iores;
|
||||
}
|
||||
|
||||
hw->ioarea = request_mem_region(res->start, (res->end - res->start)+1,
|
||||
pdev->name);
|
||||
|
||||
if (hw->ioarea == NULL) {
|
||||
dev_err(&pdev->dev, "Cannot reserve region\n");
|
||||
err = -ENXIO;
|
||||
goto err_no_iores;
|
||||
}
|
||||
|
||||
hw->regs = ioremap(res->start, (res->end - res->start)+1);
|
||||
if (hw->regs == NULL) {
|
||||
dev_err(&pdev->dev, "Cannot map IO\n");
|
||||
err = -ENXIO;
|
||||
goto err_no_iomap;
|
||||
}
|
||||
|
||||
hw->irq = platform_get_irq(pdev, 0);
|
||||
if (hw->irq < 0) {
|
||||
dev_err(&pdev->dev, "No IRQ specified\n");
|
||||
err = -ENOENT;
|
||||
goto err_no_irq;
|
||||
}
|
||||
|
||||
err = request_irq(hw->irq, s3c24xx_spi_irq, 0, pdev->name, hw);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "Cannot claim IRQ\n");
|
||||
goto err_no_irq;
|
||||
}
|
||||
|
||||
hw->clk = clk_get(&pdev->dev, "spi");
|
||||
if (IS_ERR(hw->clk)) {
|
||||
dev_err(&pdev->dev, "No clock for device\n");
|
||||
err = PTR_ERR(hw->clk);
|
||||
goto err_no_clk;
|
||||
}
|
||||
|
||||
/* for the moment, permanently enable the clock */
|
||||
|
||||
clk_enable(hw->clk);
|
||||
|
||||
/* program defaults into the registers */
|
||||
|
||||
writeb(0xff, hw->regs + S3C2410_SPPRE);
|
||||
writeb(SPPIN_DEFAULT, hw->regs + S3C2410_SPPIN);
|
||||
writeb(SPCON_DEFAULT, hw->regs + S3C2410_SPCON);
|
||||
|
||||
/* setup any gpio we can */
|
||||
|
||||
if (!hw->pdata->set_cs) {
|
||||
s3c2410_gpio_setpin(hw->pdata->pin_cs, 1);
|
||||
s3c2410_gpio_cfgpin(hw->pdata->pin_cs, S3C2410_GPIO_OUTPUT);
|
||||
}
|
||||
|
||||
/* register our spi controller */
|
||||
|
||||
err = spi_bitbang_start(&hw->bitbang);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "Failed to register SPI master\n");
|
||||
goto err_register;
|
||||
}
|
||||
|
||||
dev_dbg(hw->dev, "shutdown=%d\n", hw->bitbang.shutdown);
|
||||
|
||||
/* register all the devices associated */
|
||||
|
||||
bi = &hw->pdata->board_info[0];
|
||||
for (i = 0; i < hw->pdata->board_size; i++, bi++) {
|
||||
dev_info(hw->dev, "registering %s\n", bi->modalias);
|
||||
|
||||
bi->controller_data = hw;
|
||||
spi_new_device(master, bi);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_register:
|
||||
clk_disable(hw->clk);
|
||||
clk_put(hw->clk);
|
||||
|
||||
err_no_clk:
|
||||
free_irq(hw->irq, hw);
|
||||
|
||||
err_no_irq:
|
||||
iounmap(hw->regs);
|
||||
|
||||
err_no_iomap:
|
||||
release_resource(hw->ioarea);
|
||||
kfree(hw->ioarea);
|
||||
|
||||
err_no_iores:
|
||||
err_no_pdata:
|
||||
spi_master_put(hw->master);;
|
||||
|
||||
err_nomem:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int s3c24xx_spi_remove(struct platform_device *dev)
|
||||
{
|
||||
struct s3c24xx_spi *hw = platform_get_drvdata(dev);
|
||||
|
||||
platform_set_drvdata(dev, NULL);
|
||||
|
||||
spi_unregister_master(hw->master);
|
||||
|
||||
clk_disable(hw->clk);
|
||||
clk_put(hw->clk);
|
||||
|
||||
free_irq(hw->irq, hw);
|
||||
iounmap(hw->regs);
|
||||
|
||||
release_resource(hw->ioarea);
|
||||
kfree(hw->ioarea);
|
||||
|
||||
spi_master_put(hw->master);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
static int s3c24xx_spi_suspend(struct platform_device *pdev, pm_message_t msg)
|
||||
{
|
||||
struct s3c24xx_spi *hw = platform_get_drvdata(dev);
|
||||
|
||||
clk_disable(hw->clk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s3c24xx_spi_resume(struct platform_device *pdev)
|
||||
{
|
||||
struct s3c24xx_spi *hw = platform_get_drvdata(dev);
|
||||
|
||||
clk_enable(hw->clk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
#define s3c24xx_spi_suspend NULL
|
||||
#define s3c24xx_spi_resume NULL
|
||||
#endif
|
||||
|
||||
static struct platform_driver s3c24xx_spidrv = {
|
||||
.probe = s3c24xx_spi_probe,
|
||||
.remove = s3c24xx_spi_remove,
|
||||
.suspend = s3c24xx_spi_suspend,
|
||||
.resume = s3c24xx_spi_resume,
|
||||
.driver = {
|
||||
.name = "s3c2410-spi",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init s3c24xx_spi_init(void)
|
||||
{
|
||||
return platform_driver_register(&s3c24xx_spidrv);
|
||||
}
|
||||
|
||||
static void __exit s3c24xx_spi_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&s3c24xx_spidrv);
|
||||
}
|
||||
|
||||
module_init(s3c24xx_spi_init);
|
||||
module_exit(s3c24xx_spi_exit);
|
||||
|
||||
MODULE_DESCRIPTION("S3C24XX SPI Driver");
|
||||
MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
|
||||
MODULE_LICENSE("GPL");
|
188
drivers/spi/spi_s3c24xx_gpio.c
Normal file
188
drivers/spi/spi_s3c24xx_gpio.c
Normal file
@ -0,0 +1,188 @@
|
||||
/* linux/drivers/spi/spi_s3c24xx_gpio.c
|
||||
*
|
||||
* Copyright (c) 2006 Ben Dooks
|
||||
* Copyright (c) 2006 Simtec Electronics
|
||||
*
|
||||
* S3C24XX GPIO based SPI driver
|
||||
*
|
||||
* 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/config.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/spi/spi_bitbang.h>
|
||||
|
||||
#include <asm/arch/regs-gpio.h>
|
||||
#include <asm/arch/spi-gpio.h>
|
||||
#include <asm/arch/hardware.h>
|
||||
|
||||
struct s3c2410_spigpio {
|
||||
struct spi_bitbang bitbang;
|
||||
|
||||
struct s3c2410_spigpio_info *info;
|
||||
struct platform_device *dev;
|
||||
};
|
||||
|
||||
static inline struct s3c2410_spigpio *spidev_to_sg(struct spi_device *spi)
|
||||
{
|
||||
return spi->controller_data;
|
||||
}
|
||||
|
||||
static inline void setsck(struct spi_device *dev, int on)
|
||||
{
|
||||
struct s3c2410_spigpio *sg = spidev_to_sg(dev);
|
||||
s3c2410_gpio_setpin(sg->info->pin_clk, on ? 1 : 0);
|
||||
}
|
||||
|
||||
static inline void setmosi(struct spi_device *dev, int on)
|
||||
{
|
||||
struct s3c2410_spigpio *sg = spidev_to_sg(dev);
|
||||
s3c2410_gpio_setpin(sg->info->pin_mosi, on ? 1 : 0);
|
||||
}
|
||||
|
||||
static inline u32 getmiso(struct spi_device *dev)
|
||||
{
|
||||
struct s3c2410_spigpio *sg = spidev_to_sg(dev);
|
||||
return s3c2410_gpio_getpin(sg->info->pin_miso) ? 1 : 0;
|
||||
}
|
||||
|
||||
#define spidelay(x) ndelay(x)
|
||||
|
||||
#define EXPAND_BITBANG_TXRX
|
||||
#include <linux/spi/spi_bitbang.h>
|
||||
|
||||
|
||||
static u32 s3c2410_spigpio_txrx_mode0(struct spi_device *spi,
|
||||
unsigned nsecs, u32 word, u8 bits)
|
||||
{
|
||||
return bitbang_txrx_be_cpha0(spi, nsecs, 0, word, bits);
|
||||
}
|
||||
|
||||
static u32 s3c2410_spigpio_txrx_mode1(struct spi_device *spi,
|
||||
unsigned nsecs, u32 word, u8 bits)
|
||||
{
|
||||
return bitbang_txrx_be_cpha1(spi, nsecs, 0, word, bits);
|
||||
}
|
||||
|
||||
static void s3c2410_spigpio_chipselect(struct spi_device *dev, int value)
|
||||
{
|
||||
struct s3c2410_spigpio *sg = spidev_to_sg(dev);
|
||||
|
||||
if (sg->info && sg->info->chip_select)
|
||||
(sg->info->chip_select)(sg->info, value);
|
||||
}
|
||||
|
||||
static int s3c2410_spigpio_probe(struct platform_device *dev)
|
||||
{
|
||||
struct spi_master *master;
|
||||
struct s3c2410_spigpio *sp;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
master = spi_alloc_master(&dev->dev, sizeof(struct s3c2410_spigpio));
|
||||
if (master == NULL) {
|
||||
dev_err(&dev->dev, "failed to allocate spi master\n");
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
sp = spi_master_get_devdata(master);
|
||||
|
||||
platform_set_drvdata(dev, sp);
|
||||
|
||||
/* copy in the plkatform data */
|
||||
sp->info = dev->dev.platform_data;
|
||||
|
||||
/* setup spi bitbang adaptor */
|
||||
sp->bitbang.master = spi_master_get(master);
|
||||
sp->bitbang.chipselect = s3c2410_spigpio_chipselect;
|
||||
|
||||
sp->bitbang.txrx_word[SPI_MODE_0] = s3c2410_spigpio_txrx_mode0;
|
||||
sp->bitbang.txrx_word[SPI_MODE_1] = s3c2410_spigpio_txrx_mode1;
|
||||
|
||||
/* set state of spi pins */
|
||||
s3c2410_gpio_setpin(sp->info->pin_clk, 0);
|
||||
s3c2410_gpio_setpin(sp->info->pin_mosi, 0);
|
||||
|
||||
s3c2410_gpio_cfgpin(sp->info->pin_clk, S3C2410_GPIO_OUTPUT);
|
||||
s3c2410_gpio_cfgpin(sp->info->pin_mosi, S3C2410_GPIO_OUTPUT);
|
||||
s3c2410_gpio_cfgpin(sp->info->pin_miso, S3C2410_GPIO_INPUT);
|
||||
|
||||
ret = spi_bitbang_start(&sp->bitbang);
|
||||
if (ret)
|
||||
goto err_no_bitbang;
|
||||
|
||||
/* register the chips to go with the board */
|
||||
|
||||
for (i = 0; i < sp->info->board_size; i++) {
|
||||
dev_info(&dev->dev, "registering %p: %s\n",
|
||||
&sp->info->board_info[i],
|
||||
sp->info->board_info[i].modalias);
|
||||
|
||||
sp->info->board_info[i].controller_data = sp;
|
||||
spi_new_device(master, sp->info->board_info + i);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_no_bitbang:
|
||||
spi_master_put(sp->bitbang.master);
|
||||
err:
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
static int s3c2410_spigpio_remove(struct platform_device *dev)
|
||||
{
|
||||
struct s3c2410_spigpio *sp = platform_get_drvdata(dev);
|
||||
|
||||
spi_bitbang_stop(&sp->bitbang);
|
||||
spi_master_put(sp->bitbang.master);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* all gpio should be held over suspend/resume, so we should
|
||||
* not need to deal with this
|
||||
*/
|
||||
|
||||
#define s3c2410_spigpio_suspend NULL
|
||||
#define s3c2410_spigpio_resume NULL
|
||||
|
||||
|
||||
static struct platform_driver s3c2410_spigpio_drv = {
|
||||
.probe = s3c2410_spigpio_probe,
|
||||
.remove = s3c2410_spigpio_remove,
|
||||
.suspend = s3c2410_spigpio_suspend,
|
||||
.resume = s3c2410_spigpio_resume,
|
||||
.driver = {
|
||||
.name = "s3c24xx-spi-gpio",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init s3c2410_spigpio_init(void)
|
||||
{
|
||||
return platform_driver_register(&s3c2410_spigpio_drv);
|
||||
}
|
||||
|
||||
static void __exit s3c2410_spigpio_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&s3c2410_spigpio_drv);
|
||||
}
|
||||
|
||||
module_init(s3c2410_spigpio_init);
|
||||
module_exit(s3c2410_spigpio_exit);
|
||||
|
||||
MODULE_DESCRIPTION("S3C24XX SPI Driver");
|
||||
MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
|
||||
MODULE_LICENSE("GPL");
|
@ -317,6 +317,7 @@ static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t coun
|
||||
}
|
||||
|
||||
schedule();
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
}
|
||||
|
||||
set_current_state(TASK_RUNNING);
|
||||
|
@ -76,8 +76,8 @@
|
||||
*
|
||||
* Experiment with v_offset to find out which works best for you.
|
||||
*/
|
||||
static u32 v_offset_default __initdata; /* For 32 MiB Aper size, 8 should be the default */
|
||||
static u32 voffset __initdata = 0;
|
||||
static u32 v_offset_default __devinitdata; /* For 32 MiB Aper size, 8 should be the default */
|
||||
static u32 voffset __devinitdata;
|
||||
|
||||
static int i810fb_cursor(struct fb_info *info, struct fb_cursor *cursor);
|
||||
static int __devinit i810fb_init_pci (struct pci_dev *dev,
|
||||
|
@ -316,14 +316,24 @@ static int __g450_setclk(WPMINFO unsigned int fout, unsigned int pll,
|
||||
case M_PIXEL_PLL_B:
|
||||
case M_PIXEL_PLL_C:
|
||||
{
|
||||
u_int8_t tmp;
|
||||
u_int8_t tmp, xpwrctrl;
|
||||
unsigned long flags;
|
||||
|
||||
matroxfb_DAC_lock_irqsave(flags);
|
||||
|
||||
xpwrctrl = matroxfb_DAC_in(PMINFO M1064_XPWRCTRL);
|
||||
matroxfb_DAC_out(PMINFO M1064_XPWRCTRL, xpwrctrl & ~M1064_XPWRCTRL_PANELPDN);
|
||||
mga_outb(M_SEQ_INDEX, M_SEQ1);
|
||||
mga_outb(M_SEQ_DATA, mga_inb(M_SEQ_DATA) | M_SEQ1_SCROFF);
|
||||
tmp = matroxfb_DAC_in(PMINFO M1064_XPIXCLKCTRL);
|
||||
tmp |= M1064_XPIXCLKCTRL_DIS;
|
||||
if (!(tmp & M1064_XPIXCLKCTRL_PLL_UP)) {
|
||||
matroxfb_DAC_out(PMINFO M1064_XPIXCLKCTRL, tmp | M1064_XPIXCLKCTRL_PLL_UP);
|
||||
tmp |= M1064_XPIXCLKCTRL_PLL_UP;
|
||||
}
|
||||
matroxfb_DAC_out(PMINFO M1064_XPIXCLKCTRL, tmp);
|
||||
matroxfb_DAC_out(PMINFO M1064_XDVICLKCTRL, 0);
|
||||
matroxfb_DAC_out(PMINFO M1064_XPWRCTRL, xpwrctrl);
|
||||
|
||||
matroxfb_DAC_unlock_irqrestore(flags);
|
||||
}
|
||||
{
|
||||
@ -418,6 +428,15 @@ static int __g450_setclk(WPMINFO unsigned int fout, unsigned int pll,
|
||||
frequency to higher - with <= lowest wins, while
|
||||
with < highest one wins */
|
||||
if (delta <= deltaarray[idx-1]) {
|
||||
/* all else being equal except VCO,
|
||||
* choose VCO not near (within 1/16th or so) VCOmin
|
||||
* (freqs near VCOmin aren't as stable)
|
||||
*/
|
||||
if (delta == deltaarray[idx-1]
|
||||
&& vco != g450_mnp2vco(PMINFO mnparray[idx-1])
|
||||
&& vco < (pi->vcomin * 17 / 16)) {
|
||||
break;
|
||||
}
|
||||
mnparray[idx] = mnparray[idx-1];
|
||||
deltaarray[idx] = deltaarray[idx-1];
|
||||
} else {
|
||||
|
@ -40,6 +40,7 @@ void DAC1064_global_restore(WPMINFO2);
|
||||
#define M1064_XCURCOL1RED 0x0C
|
||||
#define M1064_XCURCOL1GREEN 0x0D
|
||||
#define M1064_XCURCOL1BLUE 0x0E
|
||||
#define M1064_XDVICLKCTRL 0x0F
|
||||
#define M1064_XCURCOL2RED 0x10
|
||||
#define M1064_XCURCOL2GREEN 0x11
|
||||
#define M1064_XCURCOL2BLUE 0x12
|
||||
@ -144,6 +145,7 @@ void DAC1064_global_restore(WPMINFO2);
|
||||
#define M1064_XVIDPLLN 0x8F
|
||||
|
||||
#define M1064_XPWRCTRL 0xA0
|
||||
#define M1064_XPWRCTRL_PANELPDN 0x04
|
||||
|
||||
#define M1064_XPANMODE 0xA2
|
||||
|
||||
|
@ -672,6 +672,8 @@ void matroxfb_unregister_driver(struct matroxfb_driver* drv);
|
||||
|
||||
#define M_SEQ_INDEX 0x1FC4
|
||||
#define M_SEQ_DATA 0x1FC5
|
||||
#define M_SEQ1 0x01
|
||||
#define M_SEQ1_SCROFF 0x20
|
||||
|
||||
#define M_MISC_REG_READ 0x1FCC
|
||||
|
||||
|
@ -428,7 +428,6 @@ static int load_flat_file(struct linux_binprm * bprm,
|
||||
loff_t fpos;
|
||||
unsigned long start_code, end_code;
|
||||
int ret;
|
||||
int exec_fileno;
|
||||
|
||||
hdr = ((struct flat_hdr *) bprm->buf); /* exec-header */
|
||||
inode = bprm->file->f_dentry->d_inode;
|
||||
@ -502,21 +501,12 @@ static int load_flat_file(struct linux_binprm * bprm,
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* check file descriptor */
|
||||
exec_fileno = get_unused_fd();
|
||||
if (exec_fileno < 0) {
|
||||
ret = -EMFILE;
|
||||
goto err;
|
||||
}
|
||||
get_file(bprm->file);
|
||||
fd_install(exec_fileno, bprm->file);
|
||||
|
||||
/* Flush all traces of the currently running executable */
|
||||
if (id == 0) {
|
||||
result = flush_old_exec(bprm);
|
||||
if (result) {
|
||||
ret = result;
|
||||
goto err_close;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* OK, This is the point of no return */
|
||||
@ -548,7 +538,7 @@ static int load_flat_file(struct linux_binprm * bprm,
|
||||
textpos = (unsigned long) -ENOMEM;
|
||||
printk("Unable to mmap process text, errno %d\n", (int)-textpos);
|
||||
ret = textpos;
|
||||
goto err_close;
|
||||
goto err;
|
||||
}
|
||||
|
||||
down_write(¤t->mm->mmap_sem);
|
||||
@ -564,7 +554,7 @@ static int load_flat_file(struct linux_binprm * bprm,
|
||||
(int)-datapos);
|
||||
do_munmap(current->mm, textpos, text_len);
|
||||
ret = realdatastart;
|
||||
goto err_close;
|
||||
goto err;
|
||||
}
|
||||
datapos = realdatastart + MAX_SHARED_LIBS * sizeof(unsigned long);
|
||||
|
||||
@ -587,7 +577,7 @@ static int load_flat_file(struct linux_binprm * bprm,
|
||||
do_munmap(current->mm, textpos, text_len);
|
||||
do_munmap(current->mm, realdatastart, data_len + extra);
|
||||
ret = result;
|
||||
goto err_close;
|
||||
goto err;
|
||||
}
|
||||
|
||||
reloc = (unsigned long *) (datapos+(ntohl(hdr->reloc_start)-text_len));
|
||||
@ -606,7 +596,7 @@ static int load_flat_file(struct linux_binprm * bprm,
|
||||
printk("Unable to allocate RAM for process text/data, errno %d\n",
|
||||
(int)-textpos);
|
||||
ret = textpos;
|
||||
goto err_close;
|
||||
goto err;
|
||||
}
|
||||
|
||||
realdatastart = textpos + ntohl(hdr->data_start);
|
||||
@ -652,7 +642,7 @@ static int load_flat_file(struct linux_binprm * bprm,
|
||||
do_munmap(current->mm, textpos, text_len + data_len + extra +
|
||||
MAX_SHARED_LIBS * sizeof(unsigned long));
|
||||
ret = result;
|
||||
goto err_close;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
@ -717,7 +707,7 @@ static int load_flat_file(struct linux_binprm * bprm,
|
||||
addr = calc_reloc(*rp, libinfo, id, 0);
|
||||
if (addr == RELOC_FAILED) {
|
||||
ret = -ENOEXEC;
|
||||
goto err_close;
|
||||
goto err;
|
||||
}
|
||||
*rp = addr;
|
||||
}
|
||||
@ -747,7 +737,7 @@ static int load_flat_file(struct linux_binprm * bprm,
|
||||
rp = (unsigned long *) calc_reloc(addr, libinfo, id, 1);
|
||||
if (rp == (unsigned long *)RELOC_FAILED) {
|
||||
ret = -ENOEXEC;
|
||||
goto err_close;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Get the pointer's value. */
|
||||
@ -762,7 +752,7 @@ static int load_flat_file(struct linux_binprm * bprm,
|
||||
addr = calc_reloc(addr, libinfo, id, 0);
|
||||
if (addr == RELOC_FAILED) {
|
||||
ret = -ENOEXEC;
|
||||
goto err_close;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Write back the relocated pointer. */
|
||||
@ -783,8 +773,6 @@ static int load_flat_file(struct linux_binprm * bprm,
|
||||
stack_len);
|
||||
|
||||
return 0;
|
||||
err_close:
|
||||
sys_close(exec_fileno);
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
3
fs/bio.c
3
fs/bio.c
@ -1116,6 +1116,9 @@ struct bio_pair *bio_split(struct bio *bi, mempool_t *pool, int first_sectors)
|
||||
bp->bio1.bi_io_vec = &bp->bv1;
|
||||
bp->bio2.bi_io_vec = &bp->bv2;
|
||||
|
||||
bp->bio1.bi_max_vecs = 1;
|
||||
bp->bio2.bi_max_vecs = 1;
|
||||
|
||||
bp->bio1.bi_end_io = bio_pair_end_1;
|
||||
bp->bio2.bi_end_io = bio_pair_end_2;
|
||||
|
||||
|
169
fs/compat.c
169
fs/compat.c
@ -2030,109 +2030,115 @@ union compat_nfsctl_res {
|
||||
struct knfsd_fh cr32_getfs;
|
||||
};
|
||||
|
||||
static int compat_nfs_svc_trans(struct nfsctl_arg *karg, struct compat_nfsctl_arg __user *arg)
|
||||
static int compat_nfs_svc_trans(struct nfsctl_arg *karg,
|
||||
struct compat_nfsctl_arg __user *arg)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = access_ok(VERIFY_READ, &arg->ca32_svc, sizeof(arg->ca32_svc));
|
||||
err |= get_user(karg->ca_version, &arg->ca32_version);
|
||||
err |= __get_user(karg->ca_svc.svc_port, &arg->ca32_svc.svc32_port);
|
||||
err |= __get_user(karg->ca_svc.svc_nthreads, &arg->ca32_svc.svc32_nthreads);
|
||||
return (err) ? -EFAULT : 0;
|
||||
if (!access_ok(VERIFY_READ, &arg->ca32_svc, sizeof(arg->ca32_svc)) ||
|
||||
get_user(karg->ca_version, &arg->ca32_version) ||
|
||||
__get_user(karg->ca_svc.svc_port, &arg->ca32_svc.svc32_port) ||
|
||||
__get_user(karg->ca_svc.svc_nthreads,
|
||||
&arg->ca32_svc.svc32_nthreads))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int compat_nfs_clnt_trans(struct nfsctl_arg *karg, struct compat_nfsctl_arg __user *arg)
|
||||
static int compat_nfs_clnt_trans(struct nfsctl_arg *karg,
|
||||
struct compat_nfsctl_arg __user *arg)
|
||||
{
|
||||
int err;
|
||||
if (!access_ok(VERIFY_READ, &arg->ca32_client,
|
||||
sizeof(arg->ca32_client)) ||
|
||||
get_user(karg->ca_version, &arg->ca32_version) ||
|
||||
__copy_from_user(&karg->ca_client.cl_ident[0],
|
||||
&arg->ca32_client.cl32_ident[0],
|
||||
NFSCLNT_IDMAX) ||
|
||||
__get_user(karg->ca_client.cl_naddr,
|
||||
&arg->ca32_client.cl32_naddr) ||
|
||||
__copy_from_user(&karg->ca_client.cl_addrlist[0],
|
||||
&arg->ca32_client.cl32_addrlist[0],
|
||||
(sizeof(struct in_addr) * NFSCLNT_ADDRMAX)) ||
|
||||
__get_user(karg->ca_client.cl_fhkeytype,
|
||||
&arg->ca32_client.cl32_fhkeytype) ||
|
||||
__get_user(karg->ca_client.cl_fhkeylen,
|
||||
&arg->ca32_client.cl32_fhkeylen) ||
|
||||
__copy_from_user(&karg->ca_client.cl_fhkey[0],
|
||||
&arg->ca32_client.cl32_fhkey[0],
|
||||
NFSCLNT_KEYMAX))
|
||||
return -EFAULT;
|
||||
|
||||
err = access_ok(VERIFY_READ, &arg->ca32_client, sizeof(arg->ca32_client));
|
||||
err |= get_user(karg->ca_version, &arg->ca32_version);
|
||||
err |= __copy_from_user(&karg->ca_client.cl_ident[0],
|
||||
&arg->ca32_client.cl32_ident[0],
|
||||
NFSCLNT_IDMAX);
|
||||
err |= __get_user(karg->ca_client.cl_naddr, &arg->ca32_client.cl32_naddr);
|
||||
err |= __copy_from_user(&karg->ca_client.cl_addrlist[0],
|
||||
&arg->ca32_client.cl32_addrlist[0],
|
||||
(sizeof(struct in_addr) * NFSCLNT_ADDRMAX));
|
||||
err |= __get_user(karg->ca_client.cl_fhkeytype,
|
||||
&arg->ca32_client.cl32_fhkeytype);
|
||||
err |= __get_user(karg->ca_client.cl_fhkeylen,
|
||||
&arg->ca32_client.cl32_fhkeylen);
|
||||
err |= __copy_from_user(&karg->ca_client.cl_fhkey[0],
|
||||
&arg->ca32_client.cl32_fhkey[0],
|
||||
NFSCLNT_KEYMAX);
|
||||
|
||||
return (err) ? -EFAULT : 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int compat_nfs_exp_trans(struct nfsctl_arg *karg, struct compat_nfsctl_arg __user *arg)
|
||||
static int compat_nfs_exp_trans(struct nfsctl_arg *karg,
|
||||
struct compat_nfsctl_arg __user *arg)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = access_ok(VERIFY_READ, &arg->ca32_export, sizeof(arg->ca32_export));
|
||||
err |= get_user(karg->ca_version, &arg->ca32_version);
|
||||
err |= __copy_from_user(&karg->ca_export.ex_client[0],
|
||||
&arg->ca32_export.ex32_client[0],
|
||||
NFSCLNT_IDMAX);
|
||||
err |= __copy_from_user(&karg->ca_export.ex_path[0],
|
||||
&arg->ca32_export.ex32_path[0],
|
||||
NFS_MAXPATHLEN);
|
||||
err |= __get_user(karg->ca_export.ex_dev,
|
||||
&arg->ca32_export.ex32_dev);
|
||||
err |= __get_user(karg->ca_export.ex_ino,
|
||||
&arg->ca32_export.ex32_ino);
|
||||
err |= __get_user(karg->ca_export.ex_flags,
|
||||
&arg->ca32_export.ex32_flags);
|
||||
err |= __get_user(karg->ca_export.ex_anon_uid,
|
||||
&arg->ca32_export.ex32_anon_uid);
|
||||
err |= __get_user(karg->ca_export.ex_anon_gid,
|
||||
&arg->ca32_export.ex32_anon_gid);
|
||||
if (!access_ok(VERIFY_READ, &arg->ca32_export,
|
||||
sizeof(arg->ca32_export)) ||
|
||||
get_user(karg->ca_version, &arg->ca32_version) ||
|
||||
__copy_from_user(&karg->ca_export.ex_client[0],
|
||||
&arg->ca32_export.ex32_client[0],
|
||||
NFSCLNT_IDMAX) ||
|
||||
__copy_from_user(&karg->ca_export.ex_path[0],
|
||||
&arg->ca32_export.ex32_path[0],
|
||||
NFS_MAXPATHLEN) ||
|
||||
__get_user(karg->ca_export.ex_dev,
|
||||
&arg->ca32_export.ex32_dev) ||
|
||||
__get_user(karg->ca_export.ex_ino,
|
||||
&arg->ca32_export.ex32_ino) ||
|
||||
__get_user(karg->ca_export.ex_flags,
|
||||
&arg->ca32_export.ex32_flags) ||
|
||||
__get_user(karg->ca_export.ex_anon_uid,
|
||||
&arg->ca32_export.ex32_anon_uid) ||
|
||||
__get_user(karg->ca_export.ex_anon_gid,
|
||||
&arg->ca32_export.ex32_anon_gid))
|
||||
return -EFAULT;
|
||||
SET_UID(karg->ca_export.ex_anon_uid, karg->ca_export.ex_anon_uid);
|
||||
SET_GID(karg->ca_export.ex_anon_gid, karg->ca_export.ex_anon_gid);
|
||||
|
||||
return (err) ? -EFAULT : 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int compat_nfs_getfd_trans(struct nfsctl_arg *karg, struct compat_nfsctl_arg __user *arg)
|
||||
static int compat_nfs_getfd_trans(struct nfsctl_arg *karg,
|
||||
struct compat_nfsctl_arg __user *arg)
|
||||
{
|
||||
int err;
|
||||
if (!access_ok(VERIFY_READ, &arg->ca32_getfd,
|
||||
sizeof(arg->ca32_getfd)) ||
|
||||
get_user(karg->ca_version, &arg->ca32_version) ||
|
||||
__copy_from_user(&karg->ca_getfd.gd_addr,
|
||||
&arg->ca32_getfd.gd32_addr,
|
||||
(sizeof(struct sockaddr))) ||
|
||||
__copy_from_user(&karg->ca_getfd.gd_path,
|
||||
&arg->ca32_getfd.gd32_path,
|
||||
(NFS_MAXPATHLEN+1)) ||
|
||||
__get_user(karg->ca_getfd.gd_version,
|
||||
&arg->ca32_getfd.gd32_version))
|
||||
return -EFAULT;
|
||||
|
||||
err = access_ok(VERIFY_READ, &arg->ca32_getfd, sizeof(arg->ca32_getfd));
|
||||
err |= get_user(karg->ca_version, &arg->ca32_version);
|
||||
err |= __copy_from_user(&karg->ca_getfd.gd_addr,
|
||||
&arg->ca32_getfd.gd32_addr,
|
||||
(sizeof(struct sockaddr)));
|
||||
err |= __copy_from_user(&karg->ca_getfd.gd_path,
|
||||
&arg->ca32_getfd.gd32_path,
|
||||
(NFS_MAXPATHLEN+1));
|
||||
err |= __get_user(karg->ca_getfd.gd_version,
|
||||
&arg->ca32_getfd.gd32_version);
|
||||
|
||||
return (err) ? -EFAULT : 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int compat_nfs_getfs_trans(struct nfsctl_arg *karg, struct compat_nfsctl_arg __user *arg)
|
||||
static int compat_nfs_getfs_trans(struct nfsctl_arg *karg,
|
||||
struct compat_nfsctl_arg __user *arg)
|
||||
{
|
||||
int err;
|
||||
if (!access_ok(VERIFY_READ,&arg->ca32_getfs,sizeof(arg->ca32_getfs)) ||
|
||||
get_user(karg->ca_version, &arg->ca32_version) ||
|
||||
__copy_from_user(&karg->ca_getfs.gd_addr,
|
||||
&arg->ca32_getfs.gd32_addr,
|
||||
(sizeof(struct sockaddr))) ||
|
||||
__copy_from_user(&karg->ca_getfs.gd_path,
|
||||
&arg->ca32_getfs.gd32_path,
|
||||
(NFS_MAXPATHLEN+1)) ||
|
||||
__get_user(karg->ca_getfs.gd_maxlen,
|
||||
&arg->ca32_getfs.gd32_maxlen))
|
||||
return -EFAULT;
|
||||
|
||||
err = access_ok(VERIFY_READ, &arg->ca32_getfs, sizeof(arg->ca32_getfs));
|
||||
err |= get_user(karg->ca_version, &arg->ca32_version);
|
||||
err |= __copy_from_user(&karg->ca_getfs.gd_addr,
|
||||
&arg->ca32_getfs.gd32_addr,
|
||||
(sizeof(struct sockaddr)));
|
||||
err |= __copy_from_user(&karg->ca_getfs.gd_path,
|
||||
&arg->ca32_getfs.gd32_path,
|
||||
(NFS_MAXPATHLEN+1));
|
||||
err |= __get_user(karg->ca_getfs.gd_maxlen,
|
||||
&arg->ca32_getfs.gd32_maxlen);
|
||||
|
||||
return (err) ? -EFAULT : 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This really doesn't need translations, we are only passing
|
||||
* back a union which contains opaque nfs file handle data.
|
||||
*/
|
||||
static int compat_nfs_getfh_res_trans(union nfsctl_res *kres, union compat_nfsctl_res __user *res)
|
||||
static int compat_nfs_getfh_res_trans(union nfsctl_res *kres,
|
||||
union compat_nfsctl_res __user *res)
|
||||
{
|
||||
int err;
|
||||
|
||||
@ -2141,8 +2147,9 @@ static int compat_nfs_getfh_res_trans(union nfsctl_res *kres, union compat_nfsct
|
||||
return (err) ? -EFAULT : 0;
|
||||
}
|
||||
|
||||
asmlinkage long compat_sys_nfsservctl(int cmd, struct compat_nfsctl_arg __user *arg,
|
||||
union compat_nfsctl_res __user *res)
|
||||
asmlinkage long compat_sys_nfsservctl(int cmd,
|
||||
struct compat_nfsctl_arg __user *arg,
|
||||
union compat_nfsctl_res __user *res)
|
||||
{
|
||||
struct nfsctl_arg *karg;
|
||||
union nfsctl_res *kres;
|
||||
|
@ -102,7 +102,7 @@ find_exported_dentry(struct super_block *sb, void *obj, void *parent,
|
||||
if (acceptable(context, result))
|
||||
return result;
|
||||
if (S_ISDIR(result->d_inode->i_mode)) {
|
||||
/* there is no other dentry, so fail */
|
||||
err = -EACCES;
|
||||
goto err_result;
|
||||
}
|
||||
|
||||
|
@ -848,7 +848,11 @@ static int inotify_release(struct inode *ignored, struct file *file)
|
||||
inode = watch->inode;
|
||||
mutex_lock(&inode->inotify_mutex);
|
||||
mutex_lock(&dev->mutex);
|
||||
remove_watch_no_event(watch, dev);
|
||||
|
||||
/* make sure we didn't race with another list removal */
|
||||
if (likely(idr_find(&dev->idr, watch->wd)))
|
||||
remove_watch_no_event(watch, dev);
|
||||
|
||||
mutex_unlock(&dev->mutex);
|
||||
mutex_unlock(&inode->inotify_mutex);
|
||||
put_inotify_watch(watch);
|
||||
@ -890,8 +894,7 @@ static int inotify_ignore(struct inotify_device *dev, s32 wd)
|
||||
mutex_lock(&dev->mutex);
|
||||
|
||||
/* make sure that we did not race */
|
||||
watch = idr_find(&dev->idr, wd);
|
||||
if (likely(watch))
|
||||
if (likely(idr_find(&dev->idr, wd) == watch))
|
||||
remove_watch(watch, dev);
|
||||
|
||||
mutex_unlock(&dev->mutex);
|
||||
|
@ -1066,9 +1066,11 @@ exp_pseudoroot(struct auth_domain *clp, struct svc_fh *fhp,
|
||||
rv = nfserr_perm;
|
||||
else if (IS_ERR(exp))
|
||||
rv = nfserrno(PTR_ERR(exp));
|
||||
else
|
||||
else {
|
||||
rv = fh_compose(fhp, exp,
|
||||
fsid_key->ek_dentry, NULL);
|
||||
exp_put(exp);
|
||||
}
|
||||
cache_put(&fsid_key->h, &svc_expkey_cache);
|
||||
return rv;
|
||||
}
|
||||
|
@ -1922,11 +1922,10 @@ nfsd_set_posix_acl(struct svc_fh *fhp, int type, struct posix_acl *acl)
|
||||
value = kmalloc(size, GFP_KERNEL);
|
||||
if (!value)
|
||||
return -ENOMEM;
|
||||
size = posix_acl_to_xattr(acl, value, size);
|
||||
if (size < 0) {
|
||||
error = size;
|
||||
error = posix_acl_to_xattr(acl, value, size);
|
||||
if (error < 0)
|
||||
goto getout;
|
||||
}
|
||||
size = error;
|
||||
} else
|
||||
size = 0;
|
||||
|
||||
|
@ -27,13 +27,16 @@
|
||||
#define SSP1_SerClkDiv(x) (((CLOCK_SPEED_HZ/2/(x+1))<<8)&0x0000ff00)
|
||||
#define SSP2_SerClkDiv(x) (((CLOCK_SPEED_HZ/(x+1))<<8)&0x000fff00)
|
||||
#define SSP3_SerClkDiv(x) (((CLOCK_SPEED_HZ/(x+1))<<8)&0x000fff00)
|
||||
#define SSP_TIMEOUT_SCALE (2712)
|
||||
#elif defined(CONFIG_PXA27x)
|
||||
#define CLOCK_SPEED_HZ 13000000
|
||||
#define SSP1_SerClkDiv(x) (((CLOCK_SPEED_HZ/(x+1))<<8)&0x000fff00)
|
||||
#define SSP2_SerClkDiv(x) (((CLOCK_SPEED_HZ/(x+1))<<8)&0x000fff00)
|
||||
#define SSP3_SerClkDiv(x) (((CLOCK_SPEED_HZ/(x+1))<<8)&0x000fff00)
|
||||
#define SSP_TIMEOUT_SCALE (769)
|
||||
#endif
|
||||
|
||||
#define SSP_TIMEOUT(x) ((x*10000)/SSP_TIMEOUT_SCALE)
|
||||
#define SSP1_VIRT ((void *)(io_p2v(__PREG(SSCR0_P(1)))))
|
||||
#define SSP2_VIRT ((void *)(io_p2v(__PREG(SSCR0_P(2)))))
|
||||
#define SSP3_VIRT ((void *)(io_p2v(__PREG(SSCR0_P(3)))))
|
||||
|
31
include/asm-arm/arch-s3c2410/spi-gpio.h
Normal file
31
include/asm-arm/arch-s3c2410/spi-gpio.h
Normal file
@ -0,0 +1,31 @@
|
||||
/* linux/include/asm-arm/arch-s3c2410/spi.h
|
||||
*
|
||||
* Copyright (c) 2006 Simtec Electronics
|
||||
* Ben Dooks <ben@simtec.co.uk>
|
||||
*
|
||||
* S3C2410 - SPI Controller platfrom_device info
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef __ASM_ARCH_SPIGPIO_H
|
||||
#define __ASM_ARCH_SPIGPIO_H __FILE__
|
||||
|
||||
struct s3c2410_spigpio_info;
|
||||
struct spi_board_info;
|
||||
|
||||
struct s3c2410_spigpio_info {
|
||||
unsigned long pin_clk;
|
||||
unsigned long pin_mosi;
|
||||
unsigned long pin_miso;
|
||||
|
||||
unsigned long board_size;
|
||||
struct spi_board_info *board_info;
|
||||
|
||||
void (*chip_select)(struct s3c2410_spigpio_info *spi, int cs);
|
||||
};
|
||||
|
||||
|
||||
#endif /* __ASM_ARCH_SPIGPIO_H */
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user