diff options
author | Linus Torvalds <torvalds@g5.osdl.org> | 2005-11-07 14:15:23 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-11-07 14:15:23 -0500 |
commit | 3f00d3e8fb963968a922d821a9a53b503b687e81 (patch) | |
tree | dfac1c73ae63f8d48340f3bbb77ee53b322c59e9 | |
parent | 407cf84f956ee4b52da5508d5357b8ae212ff77c (diff) | |
parent | a637a114f36b94a1ad8b9867f43bac0414958420 (diff) |
Merge branch 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus
38 files changed, 1896 insertions, 917 deletions
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 0097a0d53b3b..e380a8322a94 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig | |||
@@ -958,7 +958,7 @@ config SOC_PNX8550 | |||
958 | bool | 958 | bool |
959 | select DMA_NONCOHERENT | 959 | select DMA_NONCOHERENT |
960 | select HW_HAS_PCI | 960 | select HW_HAS_PCI |
961 | select SYS_HAS_CPU_R4X00 | 961 | select SYS_HAS_CPU_MIPS32_R1 |
962 | select SYS_SUPPORTS_32BIT_KERNEL | 962 | select SYS_SUPPORTS_32BIT_KERNEL |
963 | 963 | ||
964 | config SWAP_IO_SPACE | 964 | config SWAP_IO_SPACE |
diff --git a/arch/mips/boot/.gitignore b/arch/mips/boot/.gitignore new file mode 100644 index 000000000000..ba63401c6e10 --- /dev/null +++ b/arch/mips/boot/.gitignore | |||
@@ -0,0 +1,4 @@ | |||
1 | mkboot | ||
2 | elf2ecoff | ||
3 | zImage | ||
4 | zImage.tmp | ||
diff --git a/arch/mips/configs/pnx8550-jbs_defconfig b/arch/mips/configs/pnx8550-jbs_defconfig index 95f84d711912..555837e4c06f 100644 --- a/arch/mips/configs/pnx8550-jbs_defconfig +++ b/arch/mips/configs/pnx8550-jbs_defconfig | |||
@@ -129,7 +129,7 @@ CONFIG_MIPS_L1_CACHE_SHIFT=5 | |||
129 | # | 129 | # |
130 | # CPU selection | 130 | # CPU selection |
131 | # | 131 | # |
132 | # CONFIG_CPU_MIPS32_R1 is not set | 132 | CONFIG_CPU_MIPS32_R1=y |
133 | # CONFIG_CPU_MIPS32_R2 is not set | 133 | # CONFIG_CPU_MIPS32_R2 is not set |
134 | # CONFIG_CPU_MIPS64_R1 is not set | 134 | # CONFIG_CPU_MIPS64_R1 is not set |
135 | # CONFIG_CPU_MIPS64_R2 is not set | 135 | # CONFIG_CPU_MIPS64_R2 is not set |
@@ -137,7 +137,7 @@ CONFIG_MIPS_L1_CACHE_SHIFT=5 | |||
137 | # CONFIG_CPU_TX39XX is not set | 137 | # CONFIG_CPU_TX39XX is not set |
138 | # CONFIG_CPU_VR41XX is not set | 138 | # CONFIG_CPU_VR41XX is not set |
139 | # CONFIG_CPU_R4300 is not set | 139 | # CONFIG_CPU_R4300 is not set |
140 | CONFIG_CPU_R4X00=y | 140 | # CONFIG_CPU_R4X00 is not set |
141 | # CONFIG_CPU_TX49XX is not set | 141 | # CONFIG_CPU_TX49XX is not set |
142 | # CONFIG_CPU_R5000 is not set | 142 | # CONFIG_CPU_R5000 is not set |
143 | # CONFIG_CPU_R5432 is not set | 143 | # CONFIG_CPU_R5432 is not set |
@@ -148,10 +148,11 @@ CONFIG_CPU_R4X00=y | |||
148 | # CONFIG_CPU_RM7000 is not set | 148 | # CONFIG_CPU_RM7000 is not set |
149 | # CONFIG_CPU_RM9000 is not set | 149 | # CONFIG_CPU_RM9000 is not set |
150 | # CONFIG_CPU_SB1 is not set | 150 | # CONFIG_CPU_SB1 is not set |
151 | CONFIG_SYS_HAS_CPU_R4X00=y | 151 | CONFIG_SYS_HAS_CPU_MIPS32_R1=y |
152 | CONFIG_CPU_MIPS32=y | ||
153 | CONFIG_CPU_MIPSR1=y | ||
152 | CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y | 154 | CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y |
153 | CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y | 155 | CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y |
154 | CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y | ||
155 | 156 | ||
156 | # | 157 | # |
157 | # Kernel type | 158 | # Kernel type |
@@ -162,11 +163,11 @@ CONFIG_PAGE_SIZE_4KB=y | |||
162 | # CONFIG_PAGE_SIZE_8KB is not set | 163 | # CONFIG_PAGE_SIZE_8KB is not set |
163 | # CONFIG_PAGE_SIZE_16KB is not set | 164 | # CONFIG_PAGE_SIZE_16KB is not set |
164 | # CONFIG_PAGE_SIZE_64KB is not set | 165 | # CONFIG_PAGE_SIZE_64KB is not set |
166 | CONFIG_CPU_HAS_PREFETCH=y | ||
165 | # CONFIG_MIPS_MT is not set | 167 | # CONFIG_MIPS_MT is not set |
166 | # CONFIG_64BIT_PHYS_ADDR is not set | 168 | # CONFIG_64BIT_PHYS_ADDR is not set |
167 | # CONFIG_CPU_ADVANCED is not set | 169 | # CONFIG_CPU_ADVANCED is not set |
168 | CONFIG_CPU_HAS_LLSC=y | 170 | CONFIG_CPU_HAS_LLSC=y |
169 | CONFIG_CPU_HAS_LLDSCD=y | ||
170 | CONFIG_CPU_HAS_SYNC=y | 171 | CONFIG_CPU_HAS_SYNC=y |
171 | CONFIG_GENERIC_HARDIRQS=y | 172 | CONFIG_GENERIC_HARDIRQS=y |
172 | CONFIG_GENERIC_IRQ_PROBE=y | 173 | CONFIG_GENERIC_IRQ_PROBE=y |
diff --git a/arch/mips/configs/pnx8550-v2pci_defconfig b/arch/mips/configs/pnx8550-v2pci_defconfig index deb24c29ac0a..05e65206a7b4 100644 --- a/arch/mips/configs/pnx8550-v2pci_defconfig +++ b/arch/mips/configs/pnx8550-v2pci_defconfig | |||
@@ -128,7 +128,7 @@ CONFIG_MIPS_L1_CACHE_SHIFT=5 | |||
128 | # | 128 | # |
129 | # CPU selection | 129 | # CPU selection |
130 | # | 130 | # |
131 | # CONFIG_CPU_MIPS32_R1 is not set | 131 | CONFIG_CPU_MIPS32_R1=y |
132 | # CONFIG_CPU_MIPS32_R2 is not set | 132 | # CONFIG_CPU_MIPS32_R2 is not set |
133 | # CONFIG_CPU_MIPS64_R1 is not set | 133 | # CONFIG_CPU_MIPS64_R1 is not set |
134 | # CONFIG_CPU_MIPS64_R2 is not set | 134 | # CONFIG_CPU_MIPS64_R2 is not set |
@@ -136,7 +136,7 @@ CONFIG_MIPS_L1_CACHE_SHIFT=5 | |||
136 | # CONFIG_CPU_TX39XX is not set | 136 | # CONFIG_CPU_TX39XX is not set |
137 | # CONFIG_CPU_VR41XX is not set | 137 | # CONFIG_CPU_VR41XX is not set |
138 | # CONFIG_CPU_R4300 is not set | 138 | # CONFIG_CPU_R4300 is not set |
139 | CONFIG_CPU_R4X00=y | 139 | # CONFIG_CPU_R4X00 is not set |
140 | # CONFIG_CPU_TX49XX is not set | 140 | # CONFIG_CPU_TX49XX is not set |
141 | # CONFIG_CPU_R5000 is not set | 141 | # CONFIG_CPU_R5000 is not set |
142 | # CONFIG_CPU_R5432 is not set | 142 | # CONFIG_CPU_R5432 is not set |
@@ -147,10 +147,11 @@ CONFIG_CPU_R4X00=y | |||
147 | # CONFIG_CPU_RM7000 is not set | 147 | # CONFIG_CPU_RM7000 is not set |
148 | # CONFIG_CPU_RM9000 is not set | 148 | # CONFIG_CPU_RM9000 is not set |
149 | # CONFIG_CPU_SB1 is not set | 149 | # CONFIG_CPU_SB1 is not set |
150 | CONFIG_SYS_HAS_CPU_R4X00=y | 150 | CONFIG_SYS_HAS_CPU_MIPS32_R1=y |
151 | CONFIG_CPU_MIPS32=y | ||
152 | CONFIG_CPU_MIPSR1=y | ||
151 | CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y | 153 | CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y |
152 | CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y | 154 | CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y |
153 | CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y | ||
154 | 155 | ||
155 | # | 156 | # |
156 | # Kernel type | 157 | # Kernel type |
@@ -161,6 +162,7 @@ CONFIG_PAGE_SIZE_4KB=y | |||
161 | # CONFIG_PAGE_SIZE_8KB is not set | 162 | # CONFIG_PAGE_SIZE_8KB is not set |
162 | # CONFIG_PAGE_SIZE_16KB is not set | 163 | # CONFIG_PAGE_SIZE_16KB is not set |
163 | # CONFIG_PAGE_SIZE_64KB is not set | 164 | # CONFIG_PAGE_SIZE_64KB is not set |
165 | CONFIG_CPU_HAS_PREFETCH=y | ||
164 | # CONFIG_MIPS_MT is not set | 166 | # CONFIG_MIPS_MT is not set |
165 | # CONFIG_64BIT_PHYS_ADDR is not set | 167 | # CONFIG_64BIT_PHYS_ADDR is not set |
166 | CONFIG_CPU_ADVANCED=y | 168 | CONFIG_CPU_ADVANCED=y |
diff --git a/arch/mips/ddb5xxx/common/rtc_ds1386.c b/arch/mips/ddb5xxx/common/rtc_ds1386.c index f5b11508ff2f..995896ac0e39 100644 --- a/arch/mips/ddb5xxx/common/rtc_ds1386.c +++ b/arch/mips/ddb5xxx/common/rtc_ds1386.c | |||
@@ -41,7 +41,9 @@ rtc_ds1386_get_time(void) | |||
41 | u8 byte; | 41 | u8 byte; |
42 | u8 temp; | 42 | u8 temp; |
43 | unsigned int year, month, day, hour, minute, second; | 43 | unsigned int year, month, day, hour, minute, second; |
44 | unsigned long flags; | ||
44 | 45 | ||
46 | spin_lock_irqsave(&rtc_lock, flags); | ||
45 | /* let us freeze external registers */ | 47 | /* let us freeze external registers */ |
46 | byte = READ_RTC(0xB); | 48 | byte = READ_RTC(0xB); |
47 | byte &= 0x3f; | 49 | byte &= 0x3f; |
@@ -60,6 +62,7 @@ rtc_ds1386_get_time(void) | |||
60 | /* enable time transfer */ | 62 | /* enable time transfer */ |
61 | byte |= 0x80; | 63 | byte |= 0x80; |
62 | WRITE_RTC(0xB, byte); | 64 | WRITE_RTC(0xB, byte); |
65 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
63 | 66 | ||
64 | /* calc hour */ | 67 | /* calc hour */ |
65 | if (temp & 0x40) { | 68 | if (temp & 0x40) { |
@@ -81,7 +84,9 @@ rtc_ds1386_set_time(unsigned long t) | |||
81 | u8 byte; | 84 | u8 byte; |
82 | u8 temp; | 85 | u8 temp; |
83 | u8 year, month, day, hour, minute, second; | 86 | u8 year, month, day, hour, minute, second; |
87 | unsigned long flags; | ||
84 | 88 | ||
89 | spin_lock_irqsave(&rtc_lock, flags); | ||
85 | /* let us freeze external registers */ | 90 | /* let us freeze external registers */ |
86 | byte = READ_RTC(0xB); | 91 | byte = READ_RTC(0xB); |
87 | byte &= 0x3f; | 92 | byte &= 0x3f; |
@@ -133,6 +138,7 @@ rtc_ds1386_set_time(unsigned long t) | |||
133 | if (second != READ_RTC(0x1)) { | 138 | if (second != READ_RTC(0x1)) { |
134 | WRITE_RTC(0x1, second); | 139 | WRITE_RTC(0x1, second); |
135 | } | 140 | } |
141 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
136 | 142 | ||
137 | return 0; | 143 | return 0; |
138 | } | 144 | } |
diff --git a/arch/mips/dec/time.c b/arch/mips/dec/time.c index dc7091caa7aa..174822344131 100644 --- a/arch/mips/dec/time.c +++ b/arch/mips/dec/time.c | |||
@@ -37,10 +37,25 @@ | |||
37 | #include <asm/dec/machtype.h> | 37 | #include <asm/dec/machtype.h> |
38 | 38 | ||
39 | 39 | ||
40 | /* | ||
41 | * Returns true if a clock update is in progress | ||
42 | */ | ||
43 | static inline unsigned char dec_rtc_is_updating(void) | ||
44 | { | ||
45 | unsigned char uip; | ||
46 | unsigned long flags; | ||
47 | |||
48 | spin_lock_irqsave(&rtc_lock, flags); | ||
49 | uip = (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP); | ||
50 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
51 | return uip; | ||
52 | } | ||
53 | |||
40 | static unsigned long dec_rtc_get_time(void) | 54 | static unsigned long dec_rtc_get_time(void) |
41 | { | 55 | { |
42 | unsigned int year, mon, day, hour, min, sec, real_year; | 56 | unsigned int year, mon, day, hour, min, sec, real_year; |
43 | int i; | 57 | int i; |
58 | unsigned long flags; | ||
44 | 59 | ||
45 | /* The Linux interpretation of the DS1287 clock register contents: | 60 | /* The Linux interpretation of the DS1287 clock register contents: |
46 | * When the Update-In-Progress (UIP) flag goes from 1 to 0, the | 61 | * When the Update-In-Progress (UIP) flag goes from 1 to 0, the |
@@ -49,11 +64,12 @@ static unsigned long dec_rtc_get_time(void) | |||
49 | */ | 64 | */ |
50 | /* read RTC exactly on falling edge of update flag */ | 65 | /* read RTC exactly on falling edge of update flag */ |
51 | for (i = 0; i < 1000000; i++) /* may take up to 1 second... */ | 66 | for (i = 0; i < 1000000; i++) /* may take up to 1 second... */ |
52 | if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP) | 67 | if (dec_rtc_is_updating()) |
53 | break; | 68 | break; |
54 | for (i = 0; i < 1000000; i++) /* must try at least 2.228 ms */ | 69 | for (i = 0; i < 1000000; i++) /* must try at least 2.228 ms */ |
55 | if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)) | 70 | if (!dec_rtc_is_updating()) |
56 | break; | 71 | break; |
72 | spin_lock_irqsave(&rtc_lock, flags); | ||
57 | /* Isn't this overkill? UIP above should guarantee consistency */ | 73 | /* Isn't this overkill? UIP above should guarantee consistency */ |
58 | do { | 74 | do { |
59 | sec = CMOS_READ(RTC_SECONDS); | 75 | sec = CMOS_READ(RTC_SECONDS); |
@@ -77,6 +93,7 @@ static unsigned long dec_rtc_get_time(void) | |||
77 | * of unused BBU RAM locations. | 93 | * of unused BBU RAM locations. |
78 | */ | 94 | */ |
79 | real_year = CMOS_READ(RTC_DEC_YEAR); | 95 | real_year = CMOS_READ(RTC_DEC_YEAR); |
96 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
80 | year += real_year - 72 + 2000; | 97 | year += real_year - 72 + 2000; |
81 | 98 | ||
82 | return mktime(year, mon, day, hour, min, sec); | 99 | return mktime(year, mon, day, hour, min, sec); |
@@ -95,6 +112,8 @@ static int dec_rtc_set_mmss(unsigned long nowtime) | |||
95 | int real_seconds, real_minutes, cmos_minutes; | 112 | int real_seconds, real_minutes, cmos_minutes; |
96 | unsigned char save_control, save_freq_select; | 113 | unsigned char save_control, save_freq_select; |
97 | 114 | ||
115 | /* irq are locally disabled here */ | ||
116 | spin_lock(&rtc_lock); | ||
98 | /* tell the clock it's being set */ | 117 | /* tell the clock it's being set */ |
99 | save_control = CMOS_READ(RTC_CONTROL); | 118 | save_control = CMOS_READ(RTC_CONTROL); |
100 | CMOS_WRITE((save_control | RTC_SET), RTC_CONTROL); | 119 | CMOS_WRITE((save_control | RTC_SET), RTC_CONTROL); |
@@ -141,6 +160,7 @@ static int dec_rtc_set_mmss(unsigned long nowtime) | |||
141 | */ | 160 | */ |
142 | CMOS_WRITE(save_control, RTC_CONTROL); | 161 | CMOS_WRITE(save_control, RTC_CONTROL); |
143 | CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); | 162 | CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); |
163 | spin_unlock(&rtc_lock); | ||
144 | 164 | ||
145 | return retval; | 165 | return retval; |
146 | } | 166 | } |
diff --git a/arch/mips/jmr3927/common/rtc_ds1742.c b/arch/mips/jmr3927/common/rtc_ds1742.c index 1ae4318e1358..8b407d7dc460 100644 --- a/arch/mips/jmr3927/common/rtc_ds1742.c +++ b/arch/mips/jmr3927/common/rtc_ds1742.c | |||
@@ -57,7 +57,9 @@ rtc_ds1742_get_time(void) | |||
57 | { | 57 | { |
58 | unsigned int year, month, day, hour, minute, second; | 58 | unsigned int year, month, day, hour, minute, second; |
59 | unsigned int century; | 59 | unsigned int century; |
60 | unsigned long flags; | ||
60 | 61 | ||
62 | spin_lock_irqsave(&rtc_lock, flags); | ||
61 | CMOS_WRITE(RTC_READ, RTC_CONTROL); | 63 | CMOS_WRITE(RTC_READ, RTC_CONTROL); |
62 | second = BCD2BIN(CMOS_READ(RTC_SECONDS) & RTC_SECONDS_MASK); | 64 | second = BCD2BIN(CMOS_READ(RTC_SECONDS) & RTC_SECONDS_MASK); |
63 | minute = BCD2BIN(CMOS_READ(RTC_MINUTES)); | 65 | minute = BCD2BIN(CMOS_READ(RTC_MINUTES)); |
@@ -67,6 +69,7 @@ rtc_ds1742_get_time(void) | |||
67 | year = BCD2BIN(CMOS_READ(RTC_YEAR)); | 69 | year = BCD2BIN(CMOS_READ(RTC_YEAR)); |
68 | century = BCD2BIN(CMOS_READ(RTC_CENTURY) & RTC_CENTURY_MASK); | 70 | century = BCD2BIN(CMOS_READ(RTC_CENTURY) & RTC_CENTURY_MASK); |
69 | CMOS_WRITE(0, RTC_CONTROL); | 71 | CMOS_WRITE(0, RTC_CONTROL); |
72 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
70 | 73 | ||
71 | year += century * 100; | 74 | year += century * 100; |
72 | 75 | ||
@@ -81,7 +84,9 @@ rtc_ds1742_set_time(unsigned long t) | |||
81 | u8 year, month, day, hour, minute, second; | 84 | u8 year, month, day, hour, minute, second; |
82 | u8 cmos_year, cmos_month, cmos_day, cmos_hour, cmos_minute, cmos_second; | 85 | u8 cmos_year, cmos_month, cmos_day, cmos_hour, cmos_minute, cmos_second; |
83 | int cmos_century; | 86 | int cmos_century; |
87 | unsigned long flags; | ||
84 | 88 | ||
89 | spin_lock_irqsave(&rtc_lock, flags); | ||
85 | CMOS_WRITE(RTC_READ, RTC_CONTROL); | 90 | CMOS_WRITE(RTC_READ, RTC_CONTROL); |
86 | cmos_second = (u8)(CMOS_READ(RTC_SECONDS) & RTC_SECONDS_MASK); | 91 | cmos_second = (u8)(CMOS_READ(RTC_SECONDS) & RTC_SECONDS_MASK); |
87 | cmos_minute = (u8)CMOS_READ(RTC_MINUTES); | 92 | cmos_minute = (u8)CMOS_READ(RTC_MINUTES); |
@@ -139,6 +144,7 @@ rtc_ds1742_set_time(unsigned long t) | |||
139 | 144 | ||
140 | /* RTC_CENTURY and RTC_CONTROL share same address... */ | 145 | /* RTC_CENTURY and RTC_CONTROL share same address... */ |
141 | CMOS_WRITE(cmos_century, RTC_CONTROL); | 146 | CMOS_WRITE(cmos_century, RTC_CONTROL); |
147 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
142 | 148 | ||
143 | return 0; | 149 | return 0; |
144 | } | 150 | } |
diff --git a/arch/mips/kernel/irixsig.c b/arch/mips/kernel/irixsig.c index 908e63684208..dd118c60bcd0 100644 --- a/arch/mips/kernel/irixsig.c +++ b/arch/mips/kernel/irixsig.c | |||
@@ -502,8 +502,7 @@ asmlinkage int irix_sigpoll_sys(unsigned long __user *set, | |||
502 | while(1) { | 502 | while(1) { |
503 | long tmp = 0; | 503 | long tmp = 0; |
504 | 504 | ||
505 | current->state = TASK_INTERRUPTIBLE; | 505 | expire = schedule_timeout_interruptible(expire); |
506 | expire = schedule_timeout(expire); | ||
507 | 506 | ||
508 | for (i=0; i<=4; i++) | 507 | for (i=0; i<=4; i++) |
509 | tmp |= (current->pending.signal.sig[i] & kset.sig[i]); | 508 | tmp |= (current->pending.signal.sig[i] & kset.sig[i]); |
diff --git a/arch/mips/kernel/rtlx.c b/arch/mips/kernel/rtlx.c index 8c81f3cb4e2d..1d855112bac2 100644 --- a/arch/mips/kernel/rtlx.c +++ b/arch/mips/kernel/rtlx.c | |||
@@ -20,42 +20,42 @@ | |||
20 | #include <linux/module.h> | 20 | #include <linux/module.h> |
21 | #include <linux/fs.h> | 21 | #include <linux/fs.h> |
22 | #include <linux/init.h> | 22 | #include <linux/init.h> |
23 | #include <asm/uaccess.h> | ||
24 | #include <linux/slab.h> | ||
25 | #include <linux/list.h> | ||
26 | #include <linux/vmalloc.h> | ||
27 | #include <linux/elf.h> | ||
28 | #include <linux/seq_file.h> | ||
29 | #include <linux/syscalls.h> | ||
30 | #include <linux/moduleloader.h> | ||
31 | #include <linux/interrupt.h> | ||
32 | #include <linux/poll.h> | 23 | #include <linux/poll.h> |
33 | #include <linux/sched.h> | 24 | #include <linux/sched.h> |
34 | #include <linux/wait.h> | 25 | #include <linux/wait.h> |
35 | #include <asm/mipsmtregs.h> | 26 | #include <asm/mipsmtregs.h> |
36 | #include <asm/cacheflush.h> | 27 | #include <asm/bitops.h> |
37 | #include <asm/atomic.h> | ||
38 | #include <asm/cpu.h> | 28 | #include <asm/cpu.h> |
39 | #include <asm/processor.h> | 29 | #include <asm/processor.h> |
40 | #include <asm/system.h> | ||
41 | #include <asm/rtlx.h> | 30 | #include <asm/rtlx.h> |
31 | #include <asm/uaccess.h> | ||
42 | 32 | ||
43 | #define RTLX_MAJOR 64 | ||
44 | #define RTLX_TARG_VPE 1 | 33 | #define RTLX_TARG_VPE 1 |
45 | 34 | ||
46 | struct rtlx_info *rtlx; | 35 | static struct rtlx_info *rtlx; |
47 | static int major; | 36 | static int major; |
48 | static char module_name[] = "rtlx"; | 37 | static char module_name[] = "rtlx"; |
49 | static inline int spacefree(int read, int write, int size); | 38 | static struct irqaction irq; |
39 | static int irq_num; | ||
40 | |||
41 | static inline int spacefree(int read, int write, int size) | ||
42 | { | ||
43 | if (read == write) { | ||
44 | /* | ||
45 | * never fill the buffer completely, so indexes are always | ||
46 | * equal if empty and only empty, or !equal if data available | ||
47 | */ | ||
48 | return size - 1; | ||
49 | } | ||
50 | |||
51 | return ((read + size - write) % size) - 1; | ||
52 | } | ||
50 | 53 | ||
51 | static struct chan_waitqueues { | 54 | static struct chan_waitqueues { |
52 | wait_queue_head_t rt_queue; | 55 | wait_queue_head_t rt_queue; |
53 | wait_queue_head_t lx_queue; | 56 | wait_queue_head_t lx_queue; |
54 | } channel_wqs[RTLX_CHANNELS]; | 57 | } channel_wqs[RTLX_CHANNELS]; |
55 | 58 | ||
56 | static struct irqaction irq; | ||
57 | static int irq_num; | ||
58 | |||
59 | extern void *vpe_get_shared(int index); | 59 | extern void *vpe_get_shared(int index); |
60 | 60 | ||
61 | static void rtlx_dispatch(struct pt_regs *regs) | 61 | static void rtlx_dispatch(struct pt_regs *regs) |
@@ -63,9 +63,8 @@ static void rtlx_dispatch(struct pt_regs *regs) | |||
63 | do_IRQ(MIPSCPU_INT_BASE + MIPS_CPU_RTLX_IRQ, regs); | 63 | do_IRQ(MIPSCPU_INT_BASE + MIPS_CPU_RTLX_IRQ, regs); |
64 | } | 64 | } |
65 | 65 | ||
66 | irqreturn_t rtlx_interrupt(int irq, void *dev_id, struct pt_regs *regs) | 66 | static irqreturn_t rtlx_interrupt(int irq, void *dev_id, struct pt_regs *regs) |
67 | { | 67 | { |
68 | irqreturn_t r = IRQ_HANDLED; | ||
69 | int i; | 68 | int i; |
70 | 69 | ||
71 | for (i = 0; i < RTLX_CHANNELS; i++) { | 70 | for (i = 0; i < RTLX_CHANNELS; i++) { |
@@ -75,30 +74,7 @@ irqreturn_t rtlx_interrupt(int irq, void *dev_id, struct pt_regs *regs) | |||
75 | wake_up_interruptible(&channel_wqs[i].lx_queue); | 74 | wake_up_interruptible(&channel_wqs[i].lx_queue); |
76 | } | 75 | } |
77 | 76 | ||
78 | return r; | 77 | return IRQ_HANDLED; |
79 | } | ||
80 | |||
81 | void dump_rtlx(void) | ||
82 | { | ||
83 | int i; | ||
84 | |||
85 | printk("id 0x%lx state %d\n", rtlx->id, rtlx->state); | ||
86 | |||
87 | for (i = 0; i < RTLX_CHANNELS; i++) { | ||
88 | struct rtlx_channel *chan = &rtlx->channel[i]; | ||
89 | |||
90 | printk(" rt_state %d lx_state %d buffer_size %d\n", | ||
91 | chan->rt_state, chan->lx_state, chan->buffer_size); | ||
92 | |||
93 | printk(" rt_read %d rt_write %d\n", | ||
94 | chan->rt_read, chan->rt_write); | ||
95 | |||
96 | printk(" lx_read %d lx_write %d\n", | ||
97 | chan->lx_read, chan->lx_write); | ||
98 | |||
99 | printk(" rt_buffer <%s>\n", chan->rt_buffer); | ||
100 | printk(" lx_buffer <%s>\n", chan->lx_buffer); | ||
101 | } | ||
102 | } | 78 | } |
103 | 79 | ||
104 | /* call when we have the address of the shared structure from the SP side. */ | 80 | /* call when we have the address of the shared structure from the SP side. */ |
@@ -108,7 +84,7 @@ static int rtlx_init(struct rtlx_info *rtlxi) | |||
108 | 84 | ||
109 | if (rtlxi->id != RTLX_ID) { | 85 | if (rtlxi->id != RTLX_ID) { |
110 | printk(KERN_WARNING "no valid RTLX id at 0x%p\n", rtlxi); | 86 | printk(KERN_WARNING "no valid RTLX id at 0x%p\n", rtlxi); |
111 | return (-ENOEXEC); | 87 | return -ENOEXEC; |
112 | } | 88 | } |
113 | 89 | ||
114 | /* initialise the wait queues */ | 90 | /* initialise the wait queues */ |
@@ -120,9 +96,8 @@ static int rtlx_init(struct rtlx_info *rtlxi) | |||
120 | /* set up for interrupt handling */ | 96 | /* set up for interrupt handling */ |
121 | memset(&irq, 0, sizeof(struct irqaction)); | 97 | memset(&irq, 0, sizeof(struct irqaction)); |
122 | 98 | ||
123 | if (cpu_has_vint) { | 99 | if (cpu_has_vint) |
124 | set_vi_handler(MIPS_CPU_RTLX_IRQ, rtlx_dispatch); | 100 | set_vi_handler(MIPS_CPU_RTLX_IRQ, rtlx_dispatch); |
125 | } | ||
126 | 101 | ||
127 | irq_num = MIPSCPU_INT_BASE + MIPS_CPU_RTLX_IRQ; | 102 | irq_num = MIPSCPU_INT_BASE + MIPS_CPU_RTLX_IRQ; |
128 | irq.handler = rtlx_interrupt; | 103 | irq.handler = rtlx_interrupt; |
@@ -132,7 +107,8 @@ static int rtlx_init(struct rtlx_info *rtlxi) | |||
132 | setup_irq(irq_num, &irq); | 107 | setup_irq(irq_num, &irq); |
133 | 108 | ||
134 | rtlx = rtlxi; | 109 | rtlx = rtlxi; |
135 | return (0); | 110 | |
111 | return 0; | ||
136 | } | 112 | } |
137 | 113 | ||
138 | /* only allow one open process at a time to open each channel */ | 114 | /* only allow one open process at a time to open each channel */ |
@@ -147,36 +123,36 @@ static int rtlx_open(struct inode *inode, struct file *filp) | |||
147 | if (rtlx == NULL) { | 123 | if (rtlx == NULL) { |
148 | struct rtlx_info **p; | 124 | struct rtlx_info **p; |
149 | if( (p = vpe_get_shared(RTLX_TARG_VPE)) == NULL) { | 125 | if( (p = vpe_get_shared(RTLX_TARG_VPE)) == NULL) { |
150 | printk(" vpe_get_shared is NULL. Has an SP program been loaded?\n"); | 126 | printk(KERN_ERR "vpe_get_shared is NULL. " |
151 | return (-EFAULT); | 127 | "Has an SP program been loaded?\n"); |
128 | return -EFAULT; | ||
152 | } | 129 | } |
153 | 130 | ||
154 | if (*p == NULL) { | 131 | if (*p == NULL) { |
155 | printk(" vpe_shared %p %p\n", p, *p); | 132 | printk(KERN_ERR "vpe_shared %p %p\n", p, *p); |
156 | return (-EFAULT); | 133 | return -EFAULT; |
157 | } | 134 | } |
158 | 135 | ||
159 | if ((ret = rtlx_init(*p)) < 0) | 136 | if ((ret = rtlx_init(*p)) < 0) |
160 | return (ret); | 137 | return ret; |
161 | } | 138 | } |
162 | 139 | ||
163 | chan = &rtlx->channel[minor]; | 140 | chan = &rtlx->channel[minor]; |
164 | 141 | ||
165 | /* already open? */ | 142 | if (test_and_set_bit(RTLX_STATE_OPENED, &chan->lx_state)) |
166 | if (chan->lx_state == RTLX_STATE_OPENED) | 143 | return -EBUSY; |
167 | return (-EBUSY); | ||
168 | 144 | ||
169 | chan->lx_state = RTLX_STATE_OPENED; | 145 | return 0; |
170 | return (0); | ||
171 | } | 146 | } |
172 | 147 | ||
173 | static int rtlx_release(struct inode *inode, struct file *filp) | 148 | static int rtlx_release(struct inode *inode, struct file *filp) |
174 | { | 149 | { |
175 | int minor; | 150 | int minor = MINOR(inode->i_rdev); |
176 | 151 | ||
177 | minor = MINOR(inode->i_rdev); | 152 | clear_bit(RTLX_STATE_OPENED, &rtlx->channel[minor].lx_state); |
178 | rtlx->channel[minor].lx_state = RTLX_STATE_UNUSED; | 153 | smp_mb__after_clear_bit(); |
179 | return (0); | 154 | |
155 | return 0; | ||
180 | } | 156 | } |
181 | 157 | ||
182 | static unsigned int rtlx_poll(struct file *file, poll_table * wait) | 158 | static unsigned int rtlx_poll(struct file *file, poll_table * wait) |
@@ -199,12 +175,13 @@ static unsigned int rtlx_poll(struct file *file, poll_table * wait) | |||
199 | if (spacefree(chan->rt_read, chan->rt_write, chan->buffer_size)) | 175 | if (spacefree(chan->rt_read, chan->rt_write, chan->buffer_size)) |
200 | mask |= POLLOUT | POLLWRNORM; | 176 | mask |= POLLOUT | POLLWRNORM; |
201 | 177 | ||
202 | return (mask); | 178 | return mask; |
203 | } | 179 | } |
204 | 180 | ||
205 | static ssize_t rtlx_read(struct file *file, char __user * buffer, size_t count, | 181 | static ssize_t rtlx_read(struct file *file, char __user * buffer, size_t count, |
206 | loff_t * ppos) | 182 | loff_t * ppos) |
207 | { | 183 | { |
184 | unsigned long failed; | ||
208 | size_t fl = 0L; | 185 | size_t fl = 0L; |
209 | int minor; | 186 | int minor; |
210 | struct rtlx_channel *lx; | 187 | struct rtlx_channel *lx; |
@@ -216,7 +193,7 @@ static ssize_t rtlx_read(struct file *file, char __user * buffer, size_t count, | |||
216 | /* data available? */ | 193 | /* data available? */ |
217 | if (lx->lx_write == lx->lx_read) { | 194 | if (lx->lx_write == lx->lx_read) { |
218 | if (file->f_flags & O_NONBLOCK) | 195 | if (file->f_flags & O_NONBLOCK) |
219 | return (0); // -EAGAIN makes cat whinge | 196 | return 0; /* -EAGAIN makes cat whinge */ |
220 | 197 | ||
221 | /* go to sleep */ | 198 | /* go to sleep */ |
222 | add_wait_queue(&channel_wqs[minor].lx_queue, &wait); | 199 | add_wait_queue(&channel_wqs[minor].lx_queue, &wait); |
@@ -232,39 +209,39 @@ static ssize_t rtlx_read(struct file *file, char __user * buffer, size_t count, | |||
232 | } | 209 | } |
233 | 210 | ||
234 | /* find out how much in total */ | 211 | /* find out how much in total */ |
235 | count = min( count, | 212 | count = min(count, |
236 | (size_t)(lx->lx_write + lx->buffer_size - lx->lx_read) % lx->buffer_size); | 213 | (size_t)(lx->lx_write + lx->buffer_size - lx->lx_read) % lx->buffer_size); |
237 | 214 | ||
238 | /* then how much from the read pointer onwards */ | 215 | /* then how much from the read pointer onwards */ |
239 | fl = min( count, (size_t)lx->buffer_size - lx->lx_read); | 216 | fl = min(count, (size_t)lx->buffer_size - lx->lx_read); |
240 | 217 | ||
241 | copy_to_user (buffer, &lx->lx_buffer[lx->lx_read], fl); | 218 | failed = copy_to_user (buffer, &lx->lx_buffer[lx->lx_read], fl); |
219 | if (failed) { | ||
220 | count = fl - failed; | ||
221 | goto out; | ||
222 | } | ||
242 | 223 | ||
243 | /* and if there is anything left at the beginning of the buffer */ | 224 | /* and if there is anything left at the beginning of the buffer */ |
244 | if ( count - fl ) | 225 | if (count - fl) { |
245 | copy_to_user (buffer + fl, lx->lx_buffer, count - fl); | 226 | failed = copy_to_user (buffer + fl, lx->lx_buffer, count - fl); |
227 | if (failed) { | ||
228 | count -= failed; | ||
229 | goto out; | ||
230 | } | ||
231 | } | ||
246 | 232 | ||
233 | out: | ||
247 | /* update the index */ | 234 | /* update the index */ |
248 | lx->lx_read += count; | 235 | lx->lx_read += count; |
249 | lx->lx_read %= lx->buffer_size; | 236 | lx->lx_read %= lx->buffer_size; |
250 | 237 | ||
251 | return (count); | 238 | return count; |
252 | } | ||
253 | |||
254 | static inline int spacefree(int read, int write, int size) | ||
255 | { | ||
256 | if (read == write) { | ||
257 | /* never fill the buffer completely, so indexes are always equal if empty | ||
258 | and only empty, or !equal if data available */ | ||
259 | return (size - 1); | ||
260 | } | ||
261 | |||
262 | return ((read + size - write) % size) - 1; | ||
263 | } | 239 | } |
264 | 240 | ||
265 | static ssize_t rtlx_write(struct file *file, const char __user * buffer, | 241 | static ssize_t rtlx_write(struct file *file, const char __user * buffer, |
266 | size_t count, loff_t * ppos) | 242 | size_t count, loff_t * ppos) |
267 | { | 243 | { |
244 | unsigned long failed; | ||
268 | int minor; | 245 | int minor; |
269 | struct rtlx_channel *rt; | 246 | struct rtlx_channel *rt; |
270 | size_t fl; | 247 | size_t fl; |
@@ -277,7 +254,7 @@ static ssize_t rtlx_write(struct file *file, const char __user * buffer, | |||
277 | if (!spacefree(rt->rt_read, rt->rt_write, rt->buffer_size)) { | 254 | if (!spacefree(rt->rt_read, rt->rt_write, rt->buffer_size)) { |
278 | 255 | ||
279 | if (file->f_flags & O_NONBLOCK) | 256 | if (file->f_flags & O_NONBLOCK) |
280 | return (-EAGAIN); | 257 | return -EAGAIN; |
281 | 258 | ||
282 | add_wait_queue(&channel_wqs[minor].rt_queue, &wait); | 259 | add_wait_queue(&channel_wqs[minor].rt_queue, &wait); |
283 | set_current_state(TASK_INTERRUPTIBLE); | 260 | set_current_state(TASK_INTERRUPTIBLE); |
@@ -290,52 +267,64 @@ static ssize_t rtlx_write(struct file *file, const char __user * buffer, | |||
290 | } | 267 | } |
291 | 268 | ||
292 | /* total number of bytes to copy */ | 269 | /* total number of bytes to copy */ |
293 | count = min( count, (size_t)spacefree(rt->rt_read, rt->rt_write, rt->buffer_size) ); | 270 | count = min(count, (size_t)spacefree(rt->rt_read, rt->rt_write, rt->buffer_size) ); |
294 | 271 | ||
295 | /* first bit from write pointer to the end of the buffer, or count */ | 272 | /* first bit from write pointer to the end of the buffer, or count */ |
296 | fl = min(count, (size_t) rt->buffer_size - rt->rt_write); | 273 | fl = min(count, (size_t) rt->buffer_size - rt->rt_write); |
297 | 274 | ||
298 | copy_from_user(&rt->rt_buffer[rt->rt_write], buffer, fl); | 275 | failed = copy_from_user(&rt->rt_buffer[rt->rt_write], buffer, fl); |
276 | if (failed) { | ||
277 | count = fl - failed; | ||
278 | goto out; | ||
279 | } | ||
299 | 280 | ||
300 | /* if there's any left copy to the beginning of the buffer */ | 281 | /* if there's any left copy to the beginning of the buffer */ |
301 | if( count - fl ) | 282 | if (count - fl) { |
302 | copy_from_user(rt->rt_buffer, buffer + fl, count - fl); | 283 | failed = copy_from_user(rt->rt_buffer, buffer + fl, count - fl); |
284 | if (failed) { | ||
285 | count -= failed; | ||
286 | goto out; | ||
287 | } | ||
288 | } | ||
303 | 289 | ||
290 | out: | ||
304 | rt->rt_write += count; | 291 | rt->rt_write += count; |
305 | rt->rt_write %= rt->buffer_size; | 292 | rt->rt_write %= rt->buffer_size; |
306 | 293 | ||
307 | return(count); | 294 | return count; |
308 | } | 295 | } |
309 | 296 | ||
310 | static struct file_operations rtlx_fops = { | 297 | static struct file_operations rtlx_fops = { |
311 | .owner = THIS_MODULE, | 298 | .owner = THIS_MODULE, |
312 | .open = rtlx_open, | 299 | .open = rtlx_open, |
313 | .release = rtlx_release, | 300 | .release = rtlx_release, |
314 | .write = rtlx_write, | 301 | .write = rtlx_write, |
315 | .read = rtlx_read, | 302 | .read = rtlx_read, |
316 | .poll = rtlx_poll | 303 | .poll = rtlx_poll |
317 | }; | 304 | }; |
318 | 305 | ||
319 | static int rtlx_module_init(void) | 306 | static char register_chrdev_failed[] __initdata = |
307 | KERN_ERR "rtlx_module_init: unable to register device\n"; | ||
308 | |||
309 | static int __init rtlx_module_init(void) | ||
320 | { | 310 | { |
321 | if ((major = register_chrdev(RTLX_MAJOR, module_name, &rtlx_fops)) < 0) { | 311 | major = register_chrdev(0, module_name, &rtlx_fops); |
322 | printk("rtlx_module_init: unable to register device\n"); | 312 | if (major < 0) { |
323 | return (-EBUSY); | 313 | printk(register_chrdev_failed); |
314 | return major; | ||
324 | } | 315 | } |
325 | 316 | ||
326 | if (major == 0) | 317 | return 0; |
327 | major = RTLX_MAJOR; | ||
328 | |||
329 | return (0); | ||
330 | } | 318 | } |
331 | 319 | ||
332 | static void rtlx_module_exit(void) | 320 | static void __exit rtlx_module_exit(void) |
333 | { | 321 | { |
334 | unregister_chrdev(major, module_name); | 322 | unregister_chrdev(major, module_name); |
335 | } | 323 | } |
336 | 324 | ||
337 | module_init(rtlx_module_init); | 325 | module_init(rtlx_module_init); |
338 | module_exit(rtlx_module_exit); | 326 | module_exit(rtlx_module_exit); |
327 | |||
339 | MODULE_DESCRIPTION("MIPS RTLX"); | 328 | MODULE_DESCRIPTION("MIPS RTLX"); |
340 | MODULE_AUTHOR("Elizabeth Clarke, MIPS Technologies, Inc"); | 329 | MODULE_AUTHOR("Elizabeth Clarke, MIPS Technologies, Inc."); |
341 | MODULE_LICENSE("GPL"); | 330 | MODULE_LICENSE("GPL"); |
diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c index 9202a17db8f7..05e09eedabff 100644 --- a/arch/mips/kernel/signal.c +++ b/arch/mips/kernel/signal.c | |||
@@ -384,9 +384,6 @@ give_sigsegv: | |||
384 | return 0; | 384 | return 0; |
385 | } | 385 | } |
386 | 386 | ||
387 | extern void setup_rt_frame_n32(struct k_sigaction * ka, | ||
388 | struct pt_regs *regs, int signr, sigset_t *set, siginfo_t *info); | ||
389 | |||
390 | static inline int handle_signal(unsigned long sig, siginfo_t *info, | 387 | static inline int handle_signal(unsigned long sig, siginfo_t *info, |
391 | struct k_sigaction *ka, sigset_t *oldset, struct pt_regs *regs) | 388 | struct k_sigaction *ka, sigset_t *oldset, struct pt_regs *regs) |
392 | { | 389 | { |
diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c index dbe821303125..e315d3f6aa6e 100644 --- a/arch/mips/kernel/signal32.c +++ b/arch/mips/kernel/signal32.c | |||
@@ -647,8 +647,8 @@ static inline void *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, | |||
647 | return (void *)((sp - frame_size) & ALMASK); | 647 | return (void *)((sp - frame_size) & ALMASK); |
648 | } | 648 | } |
649 | 649 | ||
650 | void setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs, | 650 | int setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs, |
651 | int signr, sigset_t *set) | 651 | int signr, sigset_t *set) |
652 | { | 652 | { |
653 | struct sigframe *frame; | 653 | struct sigframe *frame; |
654 | int err = 0; | 654 | int err = 0; |
@@ -694,13 +694,15 @@ void setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs, | |||
694 | current->comm, current->pid, | 694 | current->comm, current->pid, |
695 | frame, regs->cp0_epc, frame->sf_code); | 695 | frame, regs->cp0_epc, frame->sf_code); |
696 | #endif | 696 | #endif |
697 | return; | 697 | return 1; |
698 | 698 | ||
699 | give_sigsegv: | 699 | give_sigsegv: |
700 | force_sigsegv(signr, current); | 700 | force_sigsegv(signr, current); |
701 | return 0; | ||
701 | } | 702 | } |
702 | 703 | ||
703 | void setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs, int signr, sigset_t *set, siginfo_t *info) | 704 | int setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs, |
705 | int signr, sigset_t *set, siginfo_t *info) | ||
704 | { | 706 | { |
705 | struct rt_sigframe32 *frame; | 707 | struct rt_sigframe32 *frame; |
706 | int err = 0; | 708 | int err = 0; |
@@ -763,10 +765,11 @@ void setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs, int signr, | |||
763 | current->comm, current->pid, | 765 | current->comm, current->pid, |
764 | frame, regs->cp0_epc, frame->rs_code); | 766 | frame, regs->cp0_epc, frame->rs_code); |
765 | #endif | 767 | #endif |
766 | return; | 768 | return 1; |
767 | 769 | ||
768 | give_sigsegv: | 770 | give_sigsegv: |
769 | force_sigsegv(signr, current); | 771 | force_sigsegv(signr, current); |
772 | return 0; | ||
770 | } | 773 | } |
771 | 774 | ||
772 | static inline int handle_signal(unsigned long sig, siginfo_t *info, | 775 | static inline int handle_signal(unsigned long sig, siginfo_t *info, |
diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c index 97fefcc9dbe7..06be405be399 100644 --- a/arch/mips/kernel/vpe.c +++ b/arch/mips/kernel/vpe.c | |||
@@ -58,10 +58,6 @@ | |||
58 | 58 | ||
59 | typedef void *vpe_handle; | 59 | typedef void *vpe_handle; |
60 | 60 | ||
61 | // defined here because the kernel module loader doesn't have | ||
62 | // anything to do with it. | ||
63 | #define SHN_MIPS_SCOMMON 0xff03 | ||
64 | |||
65 | #ifndef ARCH_SHF_SMALL | 61 | #ifndef ARCH_SHF_SMALL |
66 | #define ARCH_SHF_SMALL 0 | 62 | #define ARCH_SHF_SMALL 0 |
67 | #endif | 63 | #endif |
@@ -69,11 +65,8 @@ typedef void *vpe_handle; | |||
69 | /* If this is set, the section belongs in the init part of the module */ | 65 | /* If this is set, the section belongs in the init part of the module */ |
70 | #define INIT_OFFSET_MASK (1UL << (BITS_PER_LONG-1)) | 66 | #define INIT_OFFSET_MASK (1UL << (BITS_PER_LONG-1)) |
71 | 67 | ||
72 | // temp number, | ||
73 | #define VPE_MAJOR 63 | ||
74 | |||
75 | static char module_name[] = "vpe"; | 68 | static char module_name[] = "vpe"; |
76 | static int major = 0; | 69 | static int major; |
77 | 70 | ||
78 | /* grab the likely amount of memory we will need. */ | 71 | /* grab the likely amount of memory we will need. */ |
79 | #ifdef CONFIG_MIPS_VPE_LOADER_TOM | 72 | #ifdef CONFIG_MIPS_VPE_LOADER_TOM |
@@ -98,22 +91,7 @@ enum tc_state { | |||
98 | TC_STATE_DYNAMIC | 91 | TC_STATE_DYNAMIC |
99 | }; | 92 | }; |
100 | 93 | ||
101 | struct vpe; | 94 | struct vpe { |
102 | typedef struct tc { | ||
103 | enum tc_state state; | ||
104 | int index; | ||
105 | |||
106 | /* parent VPE */ | ||
107 | struct vpe *pvpe; | ||
108 | |||
109 | /* The list of TC's with this VPE */ | ||
110 | struct list_head tc; | ||
111 | |||
112 | /* The global list of tc's */ | ||
113 | struct list_head list; | ||
114 | } tc_t; | ||
115 | |||
116 | typedef struct vpe { | ||
117 | enum vpe_state state; | 95 | enum vpe_state state; |
118 | 96 | ||
119 | /* (device) minor associated with this vpe */ | 97 | /* (device) minor associated with this vpe */ |
@@ -135,7 +113,21 @@ typedef struct vpe { | |||
135 | 113 | ||
136 | /* shared symbol address */ | 114 | /* shared symbol address */ |
137 | void *shared_ptr; | 115 | void *shared_ptr; |
138 | } vpe_t; | 116 | }; |
117 | |||
118 | struct tc { | ||
119 | enum tc_state state; | ||
120 | int index; | ||
121 | |||
122 | /* parent VPE */ | ||
123 | struct vpe *pvpe; | ||
124 | |||
125 | /* The list of TC's with this VPE */ | ||
126 | struct list_head tc; | ||
127 | |||
128 | /* The global list of tc's */ | ||
129 | struct list_head list; | ||
130 | }; | ||
139 | 131 | ||
140 | struct vpecontrol_ { | 132 | struct vpecontrol_ { |
141 | /* Virtual processing elements */ | 133 | /* Virtual processing elements */ |
@@ -146,7 +138,7 @@ struct vpecontrol_ { | |||
146 | } vpecontrol; | 138 | } vpecontrol; |
147 | 139 | ||
148 | static void release_progmem(void *ptr); | 140 | static void release_progmem(void *ptr); |
149 | static void dump_vpe(vpe_t * v); | 141 | static void dump_vpe(struct vpe * v); |
150 | extern void save_gp_address(unsigned int secbase, unsigned int rel); | 142 | extern void save_gp_address(unsigned int secbase, unsigned int rel); |
151 | 143 | ||
152 | /* get the vpe associated with this minor */ | 144 | /* get the vpe associated with this minor */ |
@@ -197,13 +189,11 @@ struct vpe *alloc_vpe(int minor) | |||
197 | { | 189 | { |
198 | struct vpe *v; | 190 | struct vpe *v; |
199 | 191 | ||
200 | if ((v = kmalloc(sizeof(struct vpe), GFP_KERNEL)) == NULL) { | 192 | if ((v = kzalloc(sizeof(struct vpe), GFP_KERNEL)) == NULL) { |
201 | printk(KERN_WARNING "VPE: alloc_vpe no mem\n"); | 193 | printk(KERN_WARNING "VPE: alloc_vpe no mem\n"); |
202 | return NULL; | 194 | return NULL; |
203 | } | 195 | } |
204 | 196 | ||
205 | memset(v, 0, sizeof(struct vpe)); | ||
206 | |||
207 | INIT_LIST_HEAD(&v->tc); | 197 | INIT_LIST_HEAD(&v->tc); |
208 | list_add_tail(&v->list, &vpecontrol.vpe_list); | 198 | list_add_tail(&v->list, &vpecontrol.vpe_list); |
209 | 199 | ||
@@ -216,13 +206,11 @@ struct tc *alloc_tc(int index) | |||
216 | { | 206 | { |
217 | struct tc *t; | 207 | struct tc *t; |
218 | 208 | ||
219 | if ((t = kmalloc(sizeof(struct tc), GFP_KERNEL)) == NULL) { | 209 | if ((t = kzalloc(sizeof(struct tc), GFP_KERNEL)) == NULL) { |
220 | printk(KERN_WARNING "VPE: alloc_tc no mem\n"); | 210 | printk(KERN_WARNING "VPE: alloc_tc no mem\n"); |
221 | return NULL; | 211 | return NULL; |
222 | } | 212 | } |
223 | 213 | ||
224 | memset(t, 0, sizeof(struct tc)); | ||
225 | |||
226 | INIT_LIST_HEAD(&t->tc); | 214 | INIT_LIST_HEAD(&t->tc); |
227 | list_add_tail(&t->list, &vpecontrol.tc_list); | 215 | list_add_tail(&t->list, &vpecontrol.tc_list); |
228 | 216 | ||
@@ -412,16 +400,17 @@ static int apply_r_mips_26(struct module *me, uint32_t *location, | |||
412 | return -ENOEXEC; | 400 | return -ENOEXEC; |
413 | } | 401 | } |
414 | 402 | ||
415 | /* Not desperately convinced this is a good check of an overflow condition | 403 | /* |
416 | anyway. But it gets in the way of handling undefined weak symbols which | 404 | * Not desperately convinced this is a good check of an overflow condition |
417 | we want to set to zero. | 405 | * anyway. But it gets in the way of handling undefined weak symbols which |
418 | if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) { | 406 | * we want to set to zero. |
419 | printk(KERN_ERR | 407 | * if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) { |
420 | "module %s: relocation overflow\n", | 408 | * printk(KERN_ERR |
421 | me->name); | 409 | * "module %s: relocation overflow\n", |
422 | return -ENOEXEC; | 410 | * me->name); |
423 | } | 411 | * return -ENOEXEC; |
424 | */ | 412 | * } |
413 | */ | ||
425 | 414 | ||
426 | *location = (*location & ~0x03ffffff) | | 415 | *location = (*location & ~0x03ffffff) | |
427 | ((*location + (v >> 2)) & 0x03ffffff); | 416 | ((*location + (v >> 2)) & 0x03ffffff); |
@@ -681,7 +670,7 @@ static void dump_tclist(void) | |||
681 | } | 670 | } |
682 | 671 | ||
683 | /* We are prepared so configure and start the VPE... */ | 672 | /* We are prepared so configure and start the VPE... */ |
684 | int vpe_run(vpe_t * v) | 673 | int vpe_run(struct vpe * v) |
685 | { | 674 | { |
686 | unsigned long val; | 675 | unsigned long val; |
687 | struct tc *t; | 676 | struct tc *t; |
@@ -772,7 +761,7 @@ int vpe_run(vpe_t * v) | |||
772 | return 0; | 761 | return 0; |
773 | } | 762 | } |
774 | 763 | ||
775 | static unsigned long find_vpe_symbols(vpe_t * v, Elf_Shdr * sechdrs, | 764 | static unsigned long find_vpe_symbols(struct vpe * v, Elf_Shdr * sechdrs, |
776 | unsigned int symindex, const char *strtab, | 765 | unsigned int symindex, const char *strtab, |
777 | struct module *mod) | 766 | struct module *mod) |
778 | { | 767 | { |
@@ -792,10 +781,12 @@ static unsigned long find_vpe_symbols(vpe_t * v, Elf_Shdr * sechdrs, | |||
792 | return 0; | 781 | return 0; |
793 | } | 782 | } |
794 | 783 | ||
795 | /* Allocates a VPE with some program code space(the load address), copies the contents | 784 | /* |
796 | of the program (p)buffer performing relocatations/etc, free's it when finished. | 785 | * Allocates a VPE with some program code space(the load address), copies |
786 | * the contents of the program (p)buffer performing relocatations/etc, | ||
787 | * free's it when finished. | ||
797 | */ | 788 | */ |
798 | int vpe_elfload(vpe_t * v) | 789 | int vpe_elfload(struct vpe * v) |
799 | { | 790 | { |
800 | Elf_Ehdr *hdr; | 791 | Elf_Ehdr *hdr; |
801 | Elf_Shdr *sechdrs; | 792 | Elf_Shdr *sechdrs; |
@@ -931,7 +922,7 @@ cleanup: | |||
931 | return err; | 922 | return err; |
932 | } | 923 | } |
933 | 924 | ||
934 | static void dump_vpe(vpe_t * v) | 925 | static void dump_vpe(struct vpe * v) |
935 | { | 926 | { |
936 | struct tc *t; | 927 | struct tc *t; |
937 | 928 | ||
@@ -947,7 +938,7 @@ static void dump_vpe(vpe_t * v) | |||
947 | static int vpe_open(struct inode *inode, struct file *filp) | 938 | static int vpe_open(struct inode *inode, struct file *filp) |
948 | { | 939 | { |
949 | int minor; | 940 | int minor; |
950 | vpe_t *v; | 941 | struct vpe *v; |
951 | 942 | ||
952 | /* assume only 1 device at the mo. */ | 943 | /* assume only 1 device at the mo. */ |
953 | if ((minor = MINOR(inode->i_rdev)) != 1) { | 944 | if ((minor = MINOR(inode->i_rdev)) != 1) { |
@@ -1001,7 +992,7 @@ static int vpe_open(struct inode *inode, struct file *filp) | |||
1001 | static int vpe_release(struct inode *inode, struct file *filp) | 992 | static int vpe_release(struct inode *inode, struct file *filp) |
1002 | { | 993 | { |
1003 | int minor, ret = 0; | 994 | int minor, ret = 0; |
1004 | vpe_t *v; | 995 | struct vpe *v; |
1005 | Elf_Ehdr *hdr; | 996 | Elf_Ehdr *hdr; |
1006 | 997 | ||
1007 | minor = MINOR(inode->i_rdev); | 998 | minor = MINOR(inode->i_rdev); |
@@ -1035,7 +1026,7 @@ static ssize_t vpe_write(struct file *file, const char __user * buffer, | |||
1035 | { | 1026 | { |
1036 | int minor; | 1027 | int minor; |
1037 | size_t ret = count; | 1028 | size_t ret = count; |
1038 | vpe_t *v; | 1029 | struct vpe *v; |
1039 | 1030 | ||
1040 | minor = MINOR(file->f_dentry->d_inode->i_rdev); | 1031 | minor = MINOR(file->f_dentry->d_inode->i_rdev); |
1041 | if ((v = get_vpe(minor)) == NULL) | 1032 | if ((v = get_vpe(minor)) == NULL) |
@@ -1180,14 +1171,11 @@ static int __init vpe_module_init(void) | |||
1180 | return -ENODEV; | 1171 | return -ENODEV; |
1181 | } | 1172 | } |
1182 | 1173 | ||
1183 | if ((major = register_chrdev(VPE_MAJOR, module_name, &vpe_fops) < 0)) { | 1174 | if ((major = register_chrdev(0, module_name, &vpe_fops) < 0)) { |
1184 | printk("VPE loader: unable to register character device\n"); | 1175 | printk("VPE loader: unable to register character device\n"); |
1185 | return -EBUSY; | 1176 | return major; |
1186 | } | 1177 | } |
1187 | 1178 | ||
1188 | if (major == 0) | ||
1189 | major = VPE_MAJOR; | ||
1190 | |||
1191 | dmt(); | 1179 | dmt(); |
1192 | dvpe(); | 1180 | dvpe(); |
1193 | 1181 | ||
diff --git a/arch/mips/lasat/ds1603.c b/arch/mips/lasat/ds1603.c index 9d7812e03dcd..7dced67c55eb 100644 --- a/arch/mips/lasat/ds1603.c +++ b/arch/mips/lasat/ds1603.c | |||
@@ -8,6 +8,7 @@ | |||
8 | #include <asm/lasat/lasat.h> | 8 | #include <asm/lasat/lasat.h> |
9 | #include <linux/delay.h> | 9 | #include <linux/delay.h> |
10 | #include <asm/lasat/ds1603.h> | 10 | #include <asm/lasat/ds1603.h> |
11 | #include <asm/time.h> | ||
11 | 12 | ||
12 | #include "ds1603.h" | 13 | #include "ds1603.h" |
13 | 14 | ||
@@ -138,19 +139,27 @@ static void rtc_end_op(void) | |||
138 | unsigned long ds1603_read(void) | 139 | unsigned long ds1603_read(void) |
139 | { | 140 | { |
140 | unsigned long word; | 141 | unsigned long word; |
142 | unsigned long flags; | ||
143 | |||
144 | spin_lock_irqsave(&rtc_lock, flags); | ||
141 | rtc_init_op(); | 145 | rtc_init_op(); |
142 | rtc_write_byte(READ_TIME_CMD); | 146 | rtc_write_byte(READ_TIME_CMD); |
143 | word = rtc_read_word(); | 147 | word = rtc_read_word(); |
144 | rtc_end_op(); | 148 | rtc_end_op(); |
149 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
145 | return word; | 150 | return word; |
146 | } | 151 | } |
147 | 152 | ||
148 | int ds1603_set(unsigned long time) | 153 | int ds1603_set(unsigned long time) |
149 | { | 154 | { |
155 | unsigned long flags; | ||
156 | |||
157 | spin_lock_irqsave(&rtc_lock, flags); | ||
150 | rtc_init_op(); | 158 | rtc_init_op(); |
151 | rtc_write_byte(SET_TIME_CMD); | 159 | rtc_write_byte(SET_TIME_CMD); |
152 | rtc_write_word(time); | 160 | rtc_write_word(time); |
153 | rtc_end_op(); | 161 | rtc_end_op(); |
162 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
154 | 163 | ||
155 | return 0; | 164 | return 0; |
156 | } | 165 | } |
diff --git a/arch/mips/momentum/jaguar_atx/setup.c b/arch/mips/momentum/jaguar_atx/setup.c index 768bf4406452..bab192ddc185 100644 --- a/arch/mips/momentum/jaguar_atx/setup.c +++ b/arch/mips/momentum/jaguar_atx/setup.c | |||
@@ -149,7 +149,9 @@ arch_initcall(per_cpu_mappings); | |||
149 | unsigned long m48t37y_get_time(void) | 149 | unsigned long m48t37y_get_time(void) |
150 | { | 150 | { |
151 | unsigned int year, month, day, hour, min, sec; | 151 | unsigned int year, month, day, hour, min, sec; |
152 | unsigned long flags; | ||
152 | 153 | ||
154 | spin_lock_irqsave(&rtc_lock, flags); | ||
153 | /* stop the update */ | 155 | /* stop the update */ |
154 | rtc_base[0x7ff8] = 0x40; | 156 | rtc_base[0x7ff8] = 0x40; |
155 | 157 | ||
@@ -166,6 +168,7 @@ unsigned long m48t37y_get_time(void) | |||
166 | 168 | ||
167 | /* start the update */ | 169 | /* start the update */ |
168 | rtc_base[0x7ff8] = 0x00; | 170 | rtc_base[0x7ff8] = 0x00; |
171 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
169 | 172 | ||
170 | return mktime(year, month, day, hour, min, sec); | 173 | return mktime(year, month, day, hour, min, sec); |
171 | } | 174 | } |
@@ -173,11 +176,13 @@ unsigned long m48t37y_get_time(void) | |||
173 | int m48t37y_set_time(unsigned long sec) | 176 | int m48t37y_set_time(unsigned long sec) |
174 | { | 177 | { |
175 | struct rtc_time tm; | 178 | struct rtc_time tm; |
179 | unsigned long flags; | ||
176 | 180 | ||
177 | /* convert to a more useful format -- note months count from 0 */ | 181 | /* convert to a more useful format -- note months count from 0 */ |
178 | to_tm(sec, &tm); | 182 | to_tm(sec, &tm); |
179 | tm.tm_mon += 1; | 183 | tm.tm_mon += 1; |
180 | 184 | ||
185 | spin_lock_irqsave(&rtc_lock, flags); | ||
181 | /* enable writing */ | 186 | /* enable writing */ |
182 | rtc_base[0x7ff8] = 0x80; | 187 | rtc_base[0x7ff8] = 0x80; |
183 | 188 | ||
@@ -201,6 +206,7 @@ int m48t37y_set_time(unsigned long sec) | |||
201 | 206 | ||
202 | /* disable writing */ | 207 | /* disable writing */ |
203 | rtc_base[0x7ff8] = 0x00; | 208 | rtc_base[0x7ff8] = 0x00; |
209 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
204 | 210 | ||
205 | return 0; | 211 | return 0; |
206 | } | 212 | } |
diff --git a/arch/mips/momentum/ocelot_3/setup.c b/arch/mips/momentum/ocelot_3/setup.c index a7803e08f9db..c9b7ff8148ec 100644 --- a/arch/mips/momentum/ocelot_3/setup.c +++ b/arch/mips/momentum/ocelot_3/setup.c | |||
@@ -135,7 +135,9 @@ void setup_wired_tlb_entries(void) | |||
135 | unsigned long m48t37y_get_time(void) | 135 | unsigned long m48t37y_get_time(void) |
136 | { | 136 | { |
137 | unsigned int year, month, day, hour, min, sec; | 137 | unsigned int year, month, day, hour, min, sec; |
138 | unsigned long flags; | ||
138 | 139 | ||
140 | spin_lock_irqsave(&rtc_lock, flags); | ||
139 | /* stop the update */ | 141 | /* stop the update */ |
140 | rtc_base[0x7ff8] = 0x40; | 142 | rtc_base[0x7ff8] = 0x40; |
141 | 143 | ||
@@ -152,6 +154,7 @@ unsigned long m48t37y_get_time(void) | |||
152 | 154 | ||
153 | /* start the update */ | 155 | /* start the update */ |
154 | rtc_base[0x7ff8] = 0x00; | 156 | rtc_base[0x7ff8] = 0x00; |
157 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
155 | 158 | ||
156 | return mktime(year, month, day, hour, min, sec); | 159 | return mktime(year, month, day, hour, min, sec); |
157 | } | 160 | } |
@@ -159,11 +162,13 @@ unsigned long m48t37y_get_time(void) | |||
159 | int m48t37y_set_time(unsigned long sec) | 162 | int m48t37y_set_time(unsigned long sec) |
160 | { | 163 | { |
161 | struct rtc_time tm; | 164 | struct rtc_time tm; |
165 | unsigned long flags; | ||
162 | 166 | ||
163 | /* convert to a more useful format -- note months count from 0 */ | 167 | /* convert to a more useful format -- note months count from 0 */ |
164 | to_tm(sec, &tm); | 168 | to_tm(sec, &tm); |
165 | tm.tm_mon += 1; | 169 | tm.tm_mon += 1; |
166 | 170 | ||
171 | spin_lock_irqsave(&rtc_lock, flags); | ||
167 | /* enable writing */ | 172 | /* enable writing */ |
168 | rtc_base[0x7ff8] = 0x80; | 173 | rtc_base[0x7ff8] = 0x80; |
169 | 174 | ||
@@ -187,6 +192,7 @@ int m48t37y_set_time(unsigned long sec) | |||
187 | 192 | ||
188 | /* disable writing */ | 193 | /* disable writing */ |
189 | rtc_base[0x7ff8] = 0x00; | 194 | rtc_base[0x7ff8] = 0x00; |
195 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
190 | 196 | ||
191 | return 0; | 197 | return 0; |
192 | } | 198 | } |
diff --git a/arch/mips/momentum/ocelot_c/setup.c b/arch/mips/momentum/ocelot_c/setup.c index ce70fc96f160..2755c1547473 100644 --- a/arch/mips/momentum/ocelot_c/setup.c +++ b/arch/mips/momentum/ocelot_c/setup.c | |||
@@ -140,7 +140,9 @@ unsigned long m48t37y_get_time(void) | |||
140 | unsigned char* rtc_base = (unsigned char*)0xfc800000; | 140 | unsigned char* rtc_base = (unsigned char*)0xfc800000; |
141 | #endif | 141 | #endif |
142 | unsigned int year, month, day, hour, min, sec; | 142 | unsigned int year, month, day, hour, min, sec; |
143 | unsigned long flags; | ||
143 | 144 | ||
145 | spin_lock_irqsave(&rtc_lock, flags); | ||
144 | /* stop the update */ | 146 | /* stop the update */ |
145 | rtc_base[0x7ff8] = 0x40; | 147 | rtc_base[0x7ff8] = 0x40; |
146 | 148 | ||
@@ -157,6 +159,7 @@ unsigned long m48t37y_get_time(void) | |||
157 | 159 | ||
158 | /* start the update */ | 160 | /* start the update */ |
159 | rtc_base[0x7ff8] = 0x00; | 161 | rtc_base[0x7ff8] = 0x00; |
162 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
160 | 163 | ||
161 | return mktime(year, month, day, hour, min, sec); | 164 | return mktime(year, month, day, hour, min, sec); |
162 | } | 165 | } |
@@ -169,11 +172,13 @@ int m48t37y_set_time(unsigned long sec) | |||
169 | unsigned char* rtc_base = (unsigned char*)0xfc800000; | 172 | unsigned char* rtc_base = (unsigned char*)0xfc800000; |
170 | #endif | 173 | #endif |
171 | struct rtc_time tm; | 174 | struct rtc_time tm; |
175 | unsigned long flags; | ||
172 | 176 | ||
173 | /* convert to a more useful format -- note months count from 0 */ | 177 | /* convert to a more useful format -- note months count from 0 */ |
174 | to_tm(sec, &tm); | 178 | to_tm(sec, &tm); |
175 | tm.tm_mon += 1; | 179 | tm.tm_mon += 1; |
176 | 180 | ||
181 | spin_lock_irqsave(&rtc_lock, flags); | ||
177 | /* enable writing */ | 182 | /* enable writing */ |
178 | rtc_base[0x7ff8] = 0x80; | 183 | rtc_base[0x7ff8] = 0x80; |
179 | 184 | ||
@@ -197,6 +202,7 @@ int m48t37y_set_time(unsigned long sec) | |||
197 | 202 | ||
198 | /* disable writing */ | 203 | /* disable writing */ |
199 | rtc_base[0x7ff8] = 0x00; | 204 | rtc_base[0x7ff8] = 0x00; |
205 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
200 | 206 | ||
201 | return 0; | 207 | return 0; |
202 | } | 208 | } |
diff --git a/arch/mips/pmc-sierra/yosemite/setup.c b/arch/mips/pmc-sierra/yosemite/setup.c index bdc2ab55bed6..059755b5ed57 100644 --- a/arch/mips/pmc-sierra/yosemite/setup.c +++ b/arch/mips/pmc-sierra/yosemite/setup.c | |||
@@ -73,7 +73,9 @@ void __init bus_error_init(void) | |||
73 | unsigned long m48t37y_get_time(void) | 73 | unsigned long m48t37y_get_time(void) |
74 | { | 74 | { |
75 | unsigned int year, month, day, hour, min, sec; | 75 | unsigned int year, month, day, hour, min, sec; |
76 | unsigned long flags; | ||
76 | 77 | ||
78 | spin_lock_irqsave(&rtc_lock, flags); | ||
77 | /* Stop the update to the time */ | 79 | /* Stop the update to the time */ |
78 | m48t37_base->control = 0x40; | 80 | m48t37_base->control = 0x40; |
79 | 81 | ||
@@ -88,6 +90,7 @@ unsigned long m48t37y_get_time(void) | |||
88 | 90 | ||
89 | /* Start the update to the time again */ | 91 | /* Start the update to the time again */ |
90 | m48t37_base->control = 0x00; | 92 | m48t37_base->control = 0x00; |
93 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
91 | 94 | ||
92 | return mktime(year, month, day, hour, min, sec); | 95 | return mktime(year, month, day, hour, min, sec); |
93 | } | 96 | } |
@@ -95,11 +98,13 @@ unsigned long m48t37y_get_time(void) | |||
95 | int m48t37y_set_time(unsigned long sec) | 98 | int m48t37y_set_time(unsigned long sec) |
96 | { | 99 | { |
97 | struct rtc_time tm; | 100 | struct rtc_time tm; |
101 | unsigned long flags; | ||
98 | 102 | ||
99 | /* convert to a more useful format -- note months count from 0 */ | 103 | /* convert to a more useful format -- note months count from 0 */ |
100 | to_tm(sec, &tm); | 104 | to_tm(sec, &tm); |
101 | tm.tm_mon += 1; | 105 | tm.tm_mon += 1; |
102 | 106 | ||
107 | spin_lock_irqsave(&rtc_lock, flags); | ||
103 | /* enable writing */ | 108 | /* enable writing */ |
104 | m48t37_base->control = 0x80; | 109 | m48t37_base->control = 0x80; |
105 | 110 | ||
@@ -123,6 +128,7 @@ int m48t37y_set_time(unsigned long sec) | |||
123 | 128 | ||
124 | /* disable writing */ | 129 | /* disable writing */ |
125 | m48t37_base->control = 0x00; | 130 | m48t37_base->control = 0x00; |
131 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
126 | 132 | ||
127 | return 0; | 133 | return 0; |
128 | } | 134 | } |
diff --git a/arch/mips/sgi-ip22/ip22-time.c b/arch/mips/sgi-ip22/ip22-time.c index df9b5694328a..b7300cc5c5ad 100644 --- a/arch/mips/sgi-ip22/ip22-time.c +++ b/arch/mips/sgi-ip22/ip22-time.c | |||
@@ -35,7 +35,9 @@ static unsigned long indy_rtc_get_time(void) | |||
35 | { | 35 | { |
36 | unsigned int yrs, mon, day, hrs, min, sec; | 36 | unsigned int yrs, mon, day, hrs, min, sec; |
37 | unsigned int save_control; | 37 | unsigned int save_control; |
38 | unsigned long flags; | ||
38 | 39 | ||
40 | spin_lock_irqsave(&rtc_lock, flags); | ||
39 | save_control = hpc3c0->rtcregs[RTC_CMD] & 0xff; | 41 | save_control = hpc3c0->rtcregs[RTC_CMD] & 0xff; |
40 | hpc3c0->rtcregs[RTC_CMD] = save_control | RTC_TE; | 42 | hpc3c0->rtcregs[RTC_CMD] = save_control | RTC_TE; |
41 | 43 | ||
@@ -47,6 +49,7 @@ static unsigned long indy_rtc_get_time(void) | |||
47 | yrs = BCD2BIN(hpc3c0->rtcregs[RTC_YEAR] & 0xff); | 49 | yrs = BCD2BIN(hpc3c0->rtcregs[RTC_YEAR] & 0xff); |
48 | 50 | ||
49 | hpc3c0->rtcregs[RTC_CMD] = save_control; | 51 | hpc3c0->rtcregs[RTC_CMD] = save_control; |
52 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
50 | 53 | ||
51 | if (yrs < 45) | 54 | if (yrs < 45) |
52 | yrs += 30; | 55 | yrs += 30; |
@@ -60,6 +63,7 @@ static int indy_rtc_set_time(unsigned long tim) | |||
60 | { | 63 | { |
61 | struct rtc_time tm; | 64 | struct rtc_time tm; |
62 | unsigned int save_control; | 65 | unsigned int save_control; |
66 | unsigned long flags; | ||
63 | 67 | ||
64 | to_tm(tim, &tm); | 68 | to_tm(tim, &tm); |
65 | 69 | ||
@@ -68,6 +72,7 @@ static int indy_rtc_set_time(unsigned long tim) | |||
68 | if (tm.tm_year >= 100) | 72 | if (tm.tm_year >= 100) |
69 | tm.tm_year -= 100; | 73 | tm.tm_year -= 100; |
70 | 74 | ||
75 | spin_lock_irqsave(&rtc_lock, flags); | ||
71 | save_control = hpc3c0->rtcregs[RTC_CMD] & 0xff; | 76 | save_control = hpc3c0->rtcregs[RTC_CMD] & 0xff; |
72 | hpc3c0->rtcregs[RTC_CMD] = save_control | RTC_TE; | 77 | hpc3c0->rtcregs[RTC_CMD] = save_control | RTC_TE; |
73 | 78 | ||
@@ -80,6 +85,7 @@ static int indy_rtc_set_time(unsigned long tim) | |||
80 | hpc3c0->rtcregs[RTC_HUNDREDTH_SECOND] = 0; | 85 | hpc3c0->rtcregs[RTC_HUNDREDTH_SECOND] = 0; |
81 | 86 | ||
82 | hpc3c0->rtcregs[RTC_CMD] = save_control; | 87 | hpc3c0->rtcregs[RTC_CMD] = save_control; |
88 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
83 | 89 | ||
84 | return 0; | 90 | return 0; |
85 | } | 91 | } |
diff --git a/arch/mips/sibyte/swarm/rtc_m41t81.c b/arch/mips/sibyte/swarm/rtc_m41t81.c index 5b4fc26c1b36..c13914bdda59 100644 --- a/arch/mips/sibyte/swarm/rtc_m41t81.c +++ b/arch/mips/sibyte/swarm/rtc_m41t81.c | |||
@@ -144,6 +144,7 @@ static int m41t81_write(uint8_t addr, int b) | |||
144 | int m41t81_set_time(unsigned long t) | 144 | int m41t81_set_time(unsigned long t) |
145 | { | 145 | { |
146 | struct rtc_time tm; | 146 | struct rtc_time tm; |
147 | unsigned long flags; | ||
147 | 148 | ||
148 | to_tm(t, &tm); | 149 | to_tm(t, &tm); |
149 | 150 | ||
@@ -153,6 +154,7 @@ int m41t81_set_time(unsigned long t) | |||
153 | * believe we should finish writing min within a second. | 154 | * believe we should finish writing min within a second. |
154 | */ | 155 | */ |
155 | 156 | ||
157 | spin_lock_irqsave(&rtc_lock, flags); | ||
156 | tm.tm_sec = BIN2BCD(tm.tm_sec); | 158 | tm.tm_sec = BIN2BCD(tm.tm_sec); |
157 | m41t81_write(M41T81REG_SC, tm.tm_sec); | 159 | m41t81_write(M41T81REG_SC, tm.tm_sec); |
158 | 160 | ||
@@ -180,6 +182,7 @@ int m41t81_set_time(unsigned long t) | |||
180 | tm.tm_year %= 100; | 182 | tm.tm_year %= 100; |
181 | tm.tm_year = BIN2BCD(tm.tm_year); | 183 | tm.tm_year = BIN2BCD(tm.tm_year); |
182 | m41t81_write(M41T81REG_YR, tm.tm_year); | 184 | m41t81_write(M41T81REG_YR, tm.tm_year); |
185 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
183 | 186 | ||
184 | return 0; | 187 | return 0; |
185 | } | 188 | } |
@@ -187,19 +190,23 @@ int m41t81_set_time(unsigned long t) | |||
187 | unsigned long m41t81_get_time(void) | 190 | unsigned long m41t81_get_time(void) |
188 | { | 191 | { |
189 | unsigned int year, mon, day, hour, min, sec; | 192 | unsigned int year, mon, day, hour, min, sec; |
193 | unsigned long flags; | ||
190 | 194 | ||
191 | /* | 195 | /* |
192 | * min is valid if two reads of sec are the same. | 196 | * min is valid if two reads of sec are the same. |
193 | */ | 197 | */ |
194 | for (;;) { | 198 | for (;;) { |
199 | spin_lock_irqsave(&rtc_lock, flags); | ||
195 | sec = m41t81_read(M41T81REG_SC); | 200 | sec = m41t81_read(M41T81REG_SC); |
196 | min = m41t81_read(M41T81REG_MN); | 201 | min = m41t81_read(M41T81REG_MN); |
197 | if (sec == m41t81_read(M41T81REG_SC)) break; | 202 | if (sec == m41t81_read(M41T81REG_SC)) break; |
203 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
198 | } | 204 | } |
199 | hour = m41t81_read(M41T81REG_HR) & 0x3f; | 205 | hour = m41t81_read(M41T81REG_HR) & 0x3f; |
200 | day = m41t81_read(M41T81REG_DT); | 206 | day = m41t81_read(M41T81REG_DT); |
201 | mon = m41t81_read(M41T81REG_MO); | 207 | mon = m41t81_read(M41T81REG_MO); |
202 | year = m41t81_read(M41T81REG_YR); | 208 | year = m41t81_read(M41T81REG_YR); |
209 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
203 | 210 | ||
204 | sec = BCD2BIN(sec); | 211 | sec = BCD2BIN(sec); |
205 | min = BCD2BIN(min); | 212 | min = BCD2BIN(min); |
diff --git a/arch/mips/sibyte/swarm/rtc_xicor1241.c b/arch/mips/sibyte/swarm/rtc_xicor1241.c index d9ff9323f24e..f4a178836415 100644 --- a/arch/mips/sibyte/swarm/rtc_xicor1241.c +++ b/arch/mips/sibyte/swarm/rtc_xicor1241.c | |||
@@ -113,9 +113,11 @@ int xicor_set_time(unsigned long t) | |||
113 | { | 113 | { |
114 | struct rtc_time tm; | 114 | struct rtc_time tm; |
115 | int tmp; | 115 | int tmp; |
116 | unsigned long flags; | ||
116 | 117 | ||
117 | to_tm(t, &tm); | 118 | to_tm(t, &tm); |
118 | 119 | ||
120 | spin_lock_irqsave(&rtc_lock, flags); | ||
119 | /* unlock writes to the CCR */ | 121 | /* unlock writes to the CCR */ |
120 | xicor_write(X1241REG_SR, X1241REG_SR_WEL); | 122 | xicor_write(X1241REG_SR, X1241REG_SR_WEL); |
121 | xicor_write(X1241REG_SR, X1241REG_SR_WEL | X1241REG_SR_RWEL); | 123 | xicor_write(X1241REG_SR, X1241REG_SR_WEL | X1241REG_SR_RWEL); |
@@ -160,6 +162,7 @@ int xicor_set_time(unsigned long t) | |||
160 | xicor_write(X1241REG_HR, tmp); | 162 | xicor_write(X1241REG_HR, tmp); |
161 | 163 | ||
162 | xicor_write(X1241REG_SR, 0); | 164 | xicor_write(X1241REG_SR, 0); |
165 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
163 | 166 | ||
164 | return 0; | 167 | return 0; |
165 | } | 168 | } |
@@ -167,7 +170,9 @@ int xicor_set_time(unsigned long t) | |||
167 | unsigned long xicor_get_time(void) | 170 | unsigned long xicor_get_time(void) |
168 | { | 171 | { |
169 | unsigned int year, mon, day, hour, min, sec, y2k; | 172 | unsigned int year, mon, day, hour, min, sec, y2k; |
173 | unsigned long flags; | ||
170 | 174 | ||
175 | spin_lock_irqsave(&rtc_lock, flags); | ||
171 | sec = xicor_read(X1241REG_SC); | 176 | sec = xicor_read(X1241REG_SC); |
172 | min = xicor_read(X1241REG_MN); | 177 | min = xicor_read(X1241REG_MN); |
173 | hour = xicor_read(X1241REG_HR); | 178 | hour = xicor_read(X1241REG_HR); |
@@ -183,6 +188,7 @@ unsigned long xicor_get_time(void) | |||
183 | mon = xicor_read(X1241REG_MO); | 188 | mon = xicor_read(X1241REG_MO); |
184 | year = xicor_read(X1241REG_YR); | 189 | year = xicor_read(X1241REG_YR); |
185 | y2k = xicor_read(X1241REG_Y2K); | 190 | y2k = xicor_read(X1241REG_Y2K); |
191 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
186 | 192 | ||
187 | sec = BCD2BIN(sec); | 193 | sec = BCD2BIN(sec); |
188 | min = BCD2BIN(min); | 194 | min = BCD2BIN(min); |
diff --git a/drivers/media/video/indycam.c b/drivers/media/video/indycam.c index 26dd06ec89a2..deeef125eb92 100644 --- a/drivers/media/video/indycam.c +++ b/drivers/media/video/indycam.c | |||
@@ -27,15 +27,15 @@ | |||
27 | 27 | ||
28 | #include "indycam.h" | 28 | #include "indycam.h" |
29 | 29 | ||
30 | //#define INDYCAM_DEBUG | 30 | #define INDYCAM_MODULE_VERSION "0.0.5" |
31 | |||
32 | #define INDYCAM_MODULE_VERSION "0.0.3" | ||
33 | 31 | ||
34 | MODULE_DESCRIPTION("SGI IndyCam driver"); | 32 | MODULE_DESCRIPTION("SGI IndyCam driver"); |
35 | MODULE_VERSION(INDYCAM_MODULE_VERSION); | 33 | MODULE_VERSION(INDYCAM_MODULE_VERSION); |
36 | MODULE_AUTHOR("Mikael Nousiainen <tmnousia@cc.hut.fi>"); | 34 | MODULE_AUTHOR("Mikael Nousiainen <tmnousia@cc.hut.fi>"); |
37 | MODULE_LICENSE("GPL"); | 35 | MODULE_LICENSE("GPL"); |
38 | 36 | ||
37 | // #define INDYCAM_DEBUG | ||
38 | |||
39 | #ifdef INDYCAM_DEBUG | 39 | #ifdef INDYCAM_DEBUG |
40 | #define dprintk(x...) printk("IndyCam: " x); | 40 | #define dprintk(x...) printk("IndyCam: " x); |
41 | #define indycam_regdump(client) indycam_regdump_debug(client) | 41 | #define indycam_regdump(client) indycam_regdump_debug(client) |
@@ -46,14 +46,14 @@ MODULE_LICENSE("GPL"); | |||
46 | 46 | ||
47 | struct indycam { | 47 | struct indycam { |
48 | struct i2c_client *client; | 48 | struct i2c_client *client; |
49 | int version; | 49 | u8 version; |
50 | }; | 50 | }; |
51 | 51 | ||
52 | static struct i2c_driver i2c_driver_indycam; | 52 | static struct i2c_driver i2c_driver_indycam; |
53 | 53 | ||
54 | static const unsigned char initseq[] = { | 54 | static const u8 initseq[] = { |
55 | INDYCAM_CONTROL_AGCENA, /* INDYCAM_CONTROL */ | 55 | INDYCAM_CONTROL_AGCENA, /* INDYCAM_CONTROL */ |
56 | INDYCAM_SHUTTER_DEFAULT, /* INDYCAM_SHUTTER */ | 56 | INDYCAM_SHUTTER_60, /* INDYCAM_SHUTTER */ |
57 | INDYCAM_GAIN_DEFAULT, /* INDYCAM_GAIN */ | 57 | INDYCAM_GAIN_DEFAULT, /* INDYCAM_GAIN */ |
58 | 0x00, /* INDYCAM_BRIGHTNESS (read-only) */ | 58 | 0x00, /* INDYCAM_BRIGHTNESS (read-only) */ |
59 | INDYCAM_RED_BALANCE_DEFAULT, /* INDYCAM_RED_BALANCE */ | 59 | INDYCAM_RED_BALANCE_DEFAULT, /* INDYCAM_RED_BALANCE */ |
@@ -64,12 +64,11 @@ static const unsigned char initseq[] = { | |||
64 | 64 | ||
65 | /* IndyCam register handling */ | 65 | /* IndyCam register handling */ |
66 | 66 | ||
67 | static int indycam_read_reg(struct i2c_client *client, unsigned char reg, | 67 | static int indycam_read_reg(struct i2c_client *client, u8 reg, u8 *value) |
68 | unsigned char *value) | ||
69 | { | 68 | { |
70 | int ret; | 69 | int ret; |
71 | 70 | ||
72 | if (reg == INDYCAM_RESET) { | 71 | if (reg == INDYCAM_REG_RESET) { |
73 | dprintk("indycam_read_reg(): " | 72 | dprintk("indycam_read_reg(): " |
74 | "skipping write-only register %d\n", reg); | 73 | "skipping write-only register %d\n", reg); |
75 | *value = 0; | 74 | *value = 0; |
@@ -77,24 +76,24 @@ static int indycam_read_reg(struct i2c_client *client, unsigned char reg, | |||
77 | } | 76 | } |
78 | 77 | ||
79 | ret = i2c_smbus_read_byte_data(client, reg); | 78 | ret = i2c_smbus_read_byte_data(client, reg); |
79 | |||
80 | if (ret < 0) { | 80 | if (ret < 0) { |
81 | printk(KERN_ERR "IndyCam: indycam_read_reg(): read failed, " | 81 | printk(KERN_ERR "IndyCam: indycam_read_reg(): read failed, " |
82 | "register = 0x%02x\n", reg); | 82 | "register = 0x%02x\n", reg); |
83 | return ret; | 83 | return ret; |
84 | } | 84 | } |
85 | 85 | ||
86 | *value = (unsigned char)ret; | 86 | *value = (u8)ret; |
87 | 87 | ||
88 | return 0; | 88 | return 0; |
89 | } | 89 | } |
90 | 90 | ||
91 | static int indycam_write_reg(struct i2c_client *client, unsigned char reg, | 91 | static int indycam_write_reg(struct i2c_client *client, u8 reg, u8 value) |
92 | unsigned char value) | ||
93 | { | 92 | { |
94 | int err; | 93 | int err; |
95 | 94 | ||
96 | if ((reg == INDYCAM_BRIGHTNESS) | 95 | if ((reg == INDYCAM_REG_BRIGHTNESS) |
97 | || (reg == INDYCAM_VERSION)) { | 96 | || (reg == INDYCAM_REG_VERSION)) { |
98 | dprintk("indycam_write_reg(): " | 97 | dprintk("indycam_write_reg(): " |
99 | "skipping read-only register %d\n", reg); | 98 | "skipping read-only register %d\n", reg); |
100 | return 0; | 99 | return 0; |
@@ -102,6 +101,7 @@ static int indycam_write_reg(struct i2c_client *client, unsigned char reg, | |||
102 | 101 | ||
103 | dprintk("Writing Reg %d = 0x%02x\n", reg, value); | 102 | dprintk("Writing Reg %d = 0x%02x\n", reg, value); |
104 | err = i2c_smbus_write_byte_data(client, reg, value); | 103 | err = i2c_smbus_write_byte_data(client, reg, value); |
104 | |||
105 | if (err) { | 105 | if (err) { |
106 | printk(KERN_ERR "IndyCam: indycam_write_reg(): write failed, " | 106 | printk(KERN_ERR "IndyCam: indycam_write_reg(): write failed, " |
107 | "register = 0x%02x, value = 0x%02x\n", reg, value); | 107 | "register = 0x%02x, value = 0x%02x\n", reg, value); |
@@ -109,13 +109,12 @@ static int indycam_write_reg(struct i2c_client *client, unsigned char reg, | |||
109 | return err; | 109 | return err; |
110 | } | 110 | } |
111 | 111 | ||
112 | static int indycam_write_block(struct i2c_client *client, unsigned char reg, | 112 | static int indycam_write_block(struct i2c_client *client, u8 reg, |
113 | unsigned char length, unsigned char *data) | 113 | u8 length, u8 *data) |
114 | { | 114 | { |
115 | unsigned char i; | 115 | int i, err; |
116 | int err; | ||
117 | 116 | ||
118 | for (i = reg; i < length; i++) { | 117 | for (i = 0; i < length; i++) { |
119 | err = indycam_write_reg(client, reg + i, data[i]); | 118 | err = indycam_write_reg(client, reg + i, data[i]); |
120 | if (err) | 119 | if (err) |
121 | return err; | 120 | return err; |
@@ -130,7 +129,7 @@ static int indycam_write_block(struct i2c_client *client, unsigned char reg, | |||
130 | static void indycam_regdump_debug(struct i2c_client *client) | 129 | static void indycam_regdump_debug(struct i2c_client *client) |
131 | { | 130 | { |
132 | int i; | 131 | int i; |
133 | unsigned char val; | 132 | u8 val; |
134 | 133 | ||
135 | for (i = 0; i < 9; i++) { | 134 | for (i = 0; i < 9; i++) { |
136 | indycam_read_reg(client, i, &val); | 135 | indycam_read_reg(client, i, &val); |
@@ -139,76 +138,144 @@ static void indycam_regdump_debug(struct i2c_client *client) | |||
139 | } | 138 | } |
140 | #endif | 139 | #endif |
141 | 140 | ||
142 | static int indycam_get_controls(struct i2c_client *client, | 141 | static int indycam_get_control(struct i2c_client *client, |
143 | struct indycam_control *ctrl) | 142 | struct indycam_control *ctrl) |
144 | { | 143 | { |
145 | unsigned char ctrl_reg; | 144 | struct indycam *camera = i2c_get_clientdata(client); |
146 | 145 | u8 reg; | |
147 | indycam_read_reg(client, INDYCAM_CONTROL, &ctrl_reg); | 146 | int ret = 0; |
148 | ctrl->agc = (ctrl_reg & INDYCAM_CONTROL_AGCENA) | 147 | |
149 | ? INDYCAM_VALUE_ENABLED | 148 | switch (ctrl->type) { |
150 | : INDYCAM_VALUE_DISABLED; | 149 | case INDYCAM_CONTROL_AGC: |
151 | ctrl->awb = (ctrl_reg & INDYCAM_CONTROL_AWBCTL) | 150 | case INDYCAM_CONTROL_AWB: |
152 | ? INDYCAM_VALUE_ENABLED | 151 | ret = indycam_read_reg(client, INDYCAM_REG_CONTROL, ®); |
153 | : INDYCAM_VALUE_DISABLED; | 152 | if (ret) |
154 | indycam_read_reg(client, INDYCAM_SHUTTER, | 153 | return -EIO; |
155 | (unsigned char *)&ctrl->shutter); | 154 | if (ctrl->type == INDYCAM_CONTROL_AGC) |
156 | indycam_read_reg(client, INDYCAM_GAIN, | 155 | ctrl->value = (reg & INDYCAM_CONTROL_AGCENA) |
157 | (unsigned char *)&ctrl->gain); | 156 | ? 1 : 0; |
158 | indycam_read_reg(client, INDYCAM_RED_BALANCE, | 157 | else |
159 | (unsigned char *)&ctrl->red_balance); | 158 | ctrl->value = (reg & INDYCAM_CONTROL_AWBCTL) |
160 | indycam_read_reg(client, INDYCAM_BLUE_BALANCE, | 159 | ? 1 : 0; |
161 | (unsigned char *)&ctrl->blue_balance); | 160 | break; |
162 | indycam_read_reg(client, INDYCAM_RED_SATURATION, | 161 | case INDYCAM_CONTROL_SHUTTER: |
163 | (unsigned char *)&ctrl->red_saturation); | 162 | ret = indycam_read_reg(client, INDYCAM_REG_SHUTTER, ®); |
164 | indycam_read_reg(client, INDYCAM_BLUE_SATURATION, | 163 | if (ret) |
165 | (unsigned char *)&ctrl->blue_saturation); | 164 | return -EIO; |
166 | indycam_read_reg(client, INDYCAM_GAMMA, | 165 | ctrl->value = ((s32)reg == 0x00) ? 0xff : ((s32)reg - 1); |
167 | (unsigned char *)&ctrl->gamma); | 166 | break; |
167 | case INDYCAM_CONTROL_GAIN: | ||
168 | ret = indycam_read_reg(client, INDYCAM_REG_GAIN, ®); | ||
169 | if (ret) | ||
170 | return -EIO; | ||
171 | ctrl->value = (s32)reg; | ||
172 | break; | ||
173 | case INDYCAM_CONTROL_RED_BALANCE: | ||
174 | ret = indycam_read_reg(client, INDYCAM_REG_RED_BALANCE, ®); | ||
175 | if (ret) | ||
176 | return -EIO; | ||
177 | ctrl->value = (s32)reg; | ||
178 | break; | ||
179 | case INDYCAM_CONTROL_BLUE_BALANCE: | ||
180 | ret = indycam_read_reg(client, INDYCAM_REG_BLUE_BALANCE, ®); | ||
181 | if (ret) | ||
182 | return -EIO; | ||
183 | ctrl->value = (s32)reg; | ||
184 | break; | ||
185 | case INDYCAM_CONTROL_RED_SATURATION: | ||
186 | ret = indycam_read_reg(client, | ||
187 | INDYCAM_REG_RED_SATURATION, ®); | ||
188 | if (ret) | ||
189 | return -EIO; | ||
190 | ctrl->value = (s32)reg; | ||
191 | break; | ||
192 | case INDYCAM_CONTROL_BLUE_SATURATION: | ||
193 | ret = indycam_read_reg(client, | ||
194 | INDYCAM_REG_BLUE_SATURATION, ®); | ||
195 | if (ret) | ||
196 | return -EIO; | ||
197 | ctrl->value = (s32)reg; | ||
198 | break; | ||
199 | case INDYCAM_CONTROL_GAMMA: | ||
200 | if (camera->version == CAMERA_VERSION_MOOSE) { | ||
201 | ret = indycam_read_reg(client, | ||
202 | INDYCAM_REG_GAMMA, ®); | ||
203 | if (ret) | ||
204 | return -EIO; | ||
205 | ctrl->value = (s32)reg; | ||
206 | } else { | ||
207 | ctrl->value = INDYCAM_GAMMA_DEFAULT; | ||
208 | } | ||
209 | break; | ||
210 | default: | ||
211 | ret = -EINVAL; | ||
212 | } | ||
168 | 213 | ||
169 | return 0; | 214 | return ret; |
170 | } | 215 | } |
171 | 216 | ||
172 | static int indycam_set_controls(struct i2c_client *client, | 217 | static int indycam_set_control(struct i2c_client *client, |
173 | struct indycam_control *ctrl) | 218 | struct indycam_control *ctrl) |
174 | { | 219 | { |
175 | unsigned char ctrl_reg; | 220 | struct indycam *camera = i2c_get_clientdata(client); |
221 | u8 reg; | ||
222 | int ret = 0; | ||
223 | |||
224 | switch (ctrl->type) { | ||
225 | case INDYCAM_CONTROL_AGC: | ||
226 | case INDYCAM_CONTROL_AWB: | ||
227 | ret = indycam_read_reg(client, INDYCAM_REG_CONTROL, ®); | ||
228 | if (ret) | ||
229 | break; | ||
176 | 230 | ||
177 | indycam_read_reg(client, INDYCAM_CONTROL, &ctrl_reg); | 231 | if (ctrl->type == INDYCAM_CONTROL_AGC) { |
178 | if (ctrl->agc != INDYCAM_VALUE_UNCHANGED) { | 232 | if (ctrl->value) |
179 | if (ctrl->agc) | 233 | reg |= INDYCAM_CONTROL_AGCENA; |
180 | ctrl_reg |= INDYCAM_CONTROL_AGCENA; | 234 | else |
181 | else | 235 | reg &= ~INDYCAM_CONTROL_AGCENA; |
182 | ctrl_reg &= ~INDYCAM_CONTROL_AGCENA; | 236 | } else { |
183 | } | 237 | if (ctrl->value) |
184 | if (ctrl->awb != INDYCAM_VALUE_UNCHANGED) { | 238 | reg |= INDYCAM_CONTROL_AWBCTL; |
185 | if (ctrl->awb) | 239 | else |
186 | ctrl_reg |= INDYCAM_CONTROL_AWBCTL; | 240 | reg &= ~INDYCAM_CONTROL_AWBCTL; |
187 | else | 241 | } |
188 | ctrl_reg &= ~INDYCAM_CONTROL_AWBCTL; | 242 | |
243 | ret = indycam_write_reg(client, INDYCAM_REG_CONTROL, reg); | ||
244 | break; | ||
245 | case INDYCAM_CONTROL_SHUTTER: | ||
246 | reg = (ctrl->value == 0xff) ? 0x00 : (ctrl->value + 1); | ||
247 | ret = indycam_write_reg(client, INDYCAM_REG_SHUTTER, reg); | ||
248 | break; | ||
249 | case INDYCAM_CONTROL_GAIN: | ||
250 | ret = indycam_write_reg(client, INDYCAM_REG_GAIN, ctrl->value); | ||
251 | break; | ||
252 | case INDYCAM_CONTROL_RED_BALANCE: | ||
253 | ret = indycam_write_reg(client, INDYCAM_REG_RED_BALANCE, | ||
254 | ctrl->value); | ||
255 | break; | ||
256 | case INDYCAM_CONTROL_BLUE_BALANCE: | ||
257 | ret = indycam_write_reg(client, INDYCAM_REG_BLUE_BALANCE, | ||
258 | ctrl->value); | ||
259 | break; | ||
260 | case INDYCAM_CONTROL_RED_SATURATION: | ||
261 | ret = indycam_write_reg(client, INDYCAM_REG_RED_SATURATION, | ||
262 | ctrl->value); | ||
263 | break; | ||
264 | case INDYCAM_CONTROL_BLUE_SATURATION: | ||
265 | ret = indycam_write_reg(client, INDYCAM_REG_BLUE_SATURATION, | ||
266 | ctrl->value); | ||
267 | break; | ||
268 | case INDYCAM_CONTROL_GAMMA: | ||
269 | if (camera->version == CAMERA_VERSION_MOOSE) { | ||
270 | ret = indycam_write_reg(client, INDYCAM_REG_GAMMA, | ||
271 | ctrl->value); | ||
272 | } | ||
273 | break; | ||
274 | default: | ||
275 | ret = -EINVAL; | ||
189 | } | 276 | } |
190 | indycam_write_reg(client, INDYCAM_CONTROL, ctrl_reg); | ||
191 | |||
192 | if (ctrl->shutter >= 0) | ||
193 | indycam_write_reg(client, INDYCAM_SHUTTER, ctrl->shutter); | ||
194 | if (ctrl->gain >= 0) | ||
195 | indycam_write_reg(client, INDYCAM_GAIN, ctrl->gain); | ||
196 | if (ctrl->red_balance >= 0) | ||
197 | indycam_write_reg(client, INDYCAM_RED_BALANCE, | ||
198 | ctrl->red_balance); | ||
199 | if (ctrl->blue_balance >= 0) | ||
200 | indycam_write_reg(client, INDYCAM_BLUE_BALANCE, | ||
201 | ctrl->blue_balance); | ||
202 | if (ctrl->red_saturation >= 0) | ||
203 | indycam_write_reg(client, INDYCAM_RED_SATURATION, | ||
204 | ctrl->red_saturation); | ||
205 | if (ctrl->blue_saturation >= 0) | ||
206 | indycam_write_reg(client, INDYCAM_BLUE_SATURATION, | ||
207 | ctrl->blue_saturation); | ||
208 | if (ctrl->gamma >= 0) | ||
209 | indycam_write_reg(client, INDYCAM_GAMMA, ctrl->gamma); | ||
210 | 277 | ||
211 | return 0; | 278 | return ret; |
212 | } | 279 | } |
213 | 280 | ||
214 | /* I2C-interface */ | 281 | /* I2C-interface */ |
@@ -247,7 +314,8 @@ static int indycam_attach(struct i2c_adapter *adap, int addr, int kind) | |||
247 | if (err) | 314 | if (err) |
248 | goto out_free_camera; | 315 | goto out_free_camera; |
249 | 316 | ||
250 | camera->version = i2c_smbus_read_byte_data(client, INDYCAM_VERSION); | 317 | camera->version = i2c_smbus_read_byte_data(client, |
318 | INDYCAM_REG_VERSION); | ||
251 | if (camera->version != CAMERA_VERSION_INDY && | 319 | if (camera->version != CAMERA_VERSION_INDY && |
252 | camera->version != CAMERA_VERSION_MOOSE) { | 320 | camera->version != CAMERA_VERSION_MOOSE) { |
253 | err = -ENODEV; | 321 | err = -ENODEV; |
@@ -260,8 +328,7 @@ static int indycam_attach(struct i2c_adapter *adap, int addr, int kind) | |||
260 | indycam_regdump(client); | 328 | indycam_regdump(client); |
261 | 329 | ||
262 | // initialize | 330 | // initialize |
263 | err = indycam_write_block(client, 0, sizeof(initseq), | 331 | err = indycam_write_block(client, 0, sizeof(initseq), (u8 *)&initseq); |
264 | (unsigned char *)&initseq); | ||
265 | if (err) { | 332 | if (err) { |
266 | printk(KERN_ERR "IndyCam initalization failed\n"); | 333 | printk(KERN_ERR "IndyCam initalization failed\n"); |
267 | err = -EIO; | 334 | err = -EIO; |
@@ -271,11 +338,10 @@ static int indycam_attach(struct i2c_adapter *adap, int addr, int kind) | |||
271 | indycam_regdump(client); | 338 | indycam_regdump(client); |
272 | 339 | ||
273 | // white balance | 340 | // white balance |
274 | err = indycam_write_reg(client, INDYCAM_CONTROL, | 341 | err = indycam_write_reg(client, INDYCAM_REG_CONTROL, |
275 | INDYCAM_CONTROL_AGCENA | INDYCAM_CONTROL_AWBCTL); | 342 | INDYCAM_CONTROL_AGCENA | INDYCAM_CONTROL_AWBCTL); |
276 | if (err) { | 343 | if (err) { |
277 | printk(KERN_ERR "IndyCam white balance " | 344 | printk(KERN_ERR "IndyCam: White balancing camera failed\n"); |
278 | "initialization failed\n"); | ||
279 | err = -EIO; | 345 | err = -EIO; |
280 | goto out_detach_client; | 346 | goto out_detach_client; |
281 | } | 347 | } |
@@ -371,13 +437,11 @@ static int indycam_command(struct i2c_client *client, unsigned int cmd, | |||
371 | /* TODO: convert values for indycam_set_controls() */ | 437 | /* TODO: convert values for indycam_set_controls() */ |
372 | break; | 438 | break; |
373 | } | 439 | } |
374 | case DECODER_INDYCAM_GET_CONTROLS: { | 440 | case DECODER_INDYCAM_GET_CONTROL: { |
375 | struct indycam_control *ctrl = arg; | 441 | return indycam_get_control(client, arg); |
376 | indycam_get_controls(client, ctrl); | ||
377 | } | 442 | } |
378 | case DECODER_INDYCAM_SET_CONTROLS: { | 443 | case DECODER_INDYCAM_SET_CONTROL: { |
379 | struct indycam_control *ctrl = arg; | 444 | return indycam_set_control(client, arg); |
380 | indycam_set_controls(client, ctrl); | ||
381 | } | 445 | } |
382 | default: | 446 | default: |
383 | return -EINVAL; | 447 | return -EINVAL; |
@@ -388,12 +452,12 @@ static int indycam_command(struct i2c_client *client, unsigned int cmd, | |||
388 | 452 | ||
389 | static struct i2c_driver i2c_driver_indycam = { | 453 | static struct i2c_driver i2c_driver_indycam = { |
390 | .owner = THIS_MODULE, | 454 | .owner = THIS_MODULE, |
391 | .name = "indycam", | 455 | .name = "indycam", |
392 | .id = I2C_DRIVERID_INDYCAM, | 456 | .id = I2C_DRIVERID_INDYCAM, |
393 | .flags = I2C_DF_NOTIFY, | 457 | .flags = I2C_DF_NOTIFY, |
394 | .attach_adapter = indycam_probe, | 458 | .attach_adapter = indycam_probe, |
395 | .detach_client = indycam_detach, | 459 | .detach_client = indycam_detach, |
396 | .command = indycam_command, | 460 | .command = indycam_command, |
397 | }; | 461 | }; |
398 | 462 | ||
399 | static int __init indycam_init(void) | 463 | static int __init indycam_init(void) |
diff --git a/drivers/media/video/indycam.h b/drivers/media/video/indycam.h index d9ddb6b79a03..e6ee82063ed8 100644 --- a/drivers/media/video/indycam.h +++ b/drivers/media/video/indycam.h | |||
@@ -22,21 +22,21 @@ | |||
22 | #define INDYCAM_VERSION_MINOR(x) ((x) & 0x0f) | 22 | #define INDYCAM_VERSION_MINOR(x) ((x) & 0x0f) |
23 | 23 | ||
24 | /* Register bus addresses */ | 24 | /* Register bus addresses */ |
25 | #define INDYCAM_CONTROL 0x00 | 25 | #define INDYCAM_REG_CONTROL 0x00 |
26 | #define INDYCAM_SHUTTER 0x01 | 26 | #define INDYCAM_REG_SHUTTER 0x01 |
27 | #define INDYCAM_GAIN 0x02 | 27 | #define INDYCAM_REG_GAIN 0x02 |
28 | #define INDYCAM_BRIGHTNESS 0x03 /* read-only */ | 28 | #define INDYCAM_REG_BRIGHTNESS 0x03 /* read-only */ |
29 | #define INDYCAM_RED_BALANCE 0x04 | 29 | #define INDYCAM_REG_RED_BALANCE 0x04 |
30 | #define INDYCAM_BLUE_BALANCE 0x05 | 30 | #define INDYCAM_REG_BLUE_BALANCE 0x05 |
31 | #define INDYCAM_RED_SATURATION 0x06 | 31 | #define INDYCAM_REG_RED_SATURATION 0x06 |
32 | #define INDYCAM_BLUE_SATURATION 0x07 | 32 | #define INDYCAM_REG_BLUE_SATURATION 0x07 |
33 | #define INDYCAM_GAMMA 0x08 | 33 | #define INDYCAM_REG_GAMMA 0x08 |
34 | #define INDYCAM_VERSION 0x0e /* read-only */ | 34 | #define INDYCAM_REG_VERSION 0x0e /* read-only */ |
35 | #define INDYCAM_RESET 0x0f /* write-only */ | 35 | #define INDYCAM_REG_RESET 0x0f /* write-only */ |
36 | 36 | ||
37 | #define INDYCAM_LED 0x46 | 37 | #define INDYCAM_REG_LED 0x46 |
38 | #define INDYCAM_ORIENTATION 0x47 | 38 | #define INDYCAM_REG_ORIENTATION 0x47 |
39 | #define INDYCAM_BUTTON 0x48 | 39 | #define INDYCAM_REG_BUTTON 0x48 |
40 | 40 | ||
41 | /* Field definitions of registers */ | 41 | /* Field definitions of registers */ |
42 | #define INDYCAM_CONTROL_AGCENA (1<<0) /* automatic gain control */ | 42 | #define INDYCAM_CONTROL_AGCENA (1<<0) /* automatic gain control */ |
@@ -59,13 +59,14 @@ | |||
59 | #define INDYCAM_ORIENTATION_BOTTOM_TO_TOP 0x40 | 59 | #define INDYCAM_ORIENTATION_BOTTOM_TO_TOP 0x40 |
60 | #define INDYCAM_BUTTON_RELEASED 0x10 | 60 | #define INDYCAM_BUTTON_RELEASED 0x10 |
61 | 61 | ||
62 | /* Values for controls */ | ||
62 | #define INDYCAM_SHUTTER_MIN 0x00 | 63 | #define INDYCAM_SHUTTER_MIN 0x00 |
63 | #define INDYCAM_SHUTTER_MAX 0xff | 64 | #define INDYCAM_SHUTTER_MAX 0xff |
64 | #define INDYCAM_GAIN_MIN 0x00 | 65 | #define INDYCAM_GAIN_MIN 0x00 |
65 | #define INDYCAM_GAIN_MAX 0xff | 66 | #define INDYCAM_GAIN_MAX 0xff |
66 | #define INDYCAM_RED_BALANCE_MIN 0x00 /* the effect is the opposite? */ | 67 | #define INDYCAM_RED_BALANCE_MIN 0x00 |
67 | #define INDYCAM_RED_BALANCE_MAX 0xff | 68 | #define INDYCAM_RED_BALANCE_MAX 0xff |
68 | #define INDYCAM_BLUE_BALANCE_MIN 0x00 /* the effect is the opposite? */ | 69 | #define INDYCAM_BLUE_BALANCE_MIN 0x00 |
69 | #define INDYCAM_BLUE_BALANCE_MAX 0xff | 70 | #define INDYCAM_BLUE_BALANCE_MAX 0xff |
70 | #define INDYCAM_RED_SATURATION_MIN 0x00 | 71 | #define INDYCAM_RED_SATURATION_MIN 0x00 |
71 | #define INDYCAM_RED_SATURATION_MAX 0xff | 72 | #define INDYCAM_RED_SATURATION_MAX 0xff |
@@ -74,34 +75,9 @@ | |||
74 | #define INDYCAM_GAMMA_MIN 0x00 | 75 | #define INDYCAM_GAMMA_MIN 0x00 |
75 | #define INDYCAM_GAMMA_MAX 0xff | 76 | #define INDYCAM_GAMMA_MAX 0xff |
76 | 77 | ||
77 | /* Driver interface definitions */ | 78 | #define INDYCAM_AGC_DEFAULT 1 |
78 | 79 | #define INDYCAM_AWB_DEFAULT 0 | |
79 | #define INDYCAM_VALUE_ENABLED 1 | 80 | #define INDYCAM_SHUTTER_DEFAULT 0xff |
80 | #define INDYCAM_VALUE_DISABLED 0 | ||
81 | #define INDYCAM_VALUE_UNCHANGED -1 | ||
82 | |||
83 | /* When setting controls, a value of -1 leaves the control unchanged. */ | ||
84 | struct indycam_control { | ||
85 | int agc; /* boolean */ | ||
86 | int awb; /* boolean */ | ||
87 | int shutter; | ||
88 | int gain; | ||
89 | int red_balance; | ||
90 | int blue_balance; | ||
91 | int red_saturation; | ||
92 | int blue_saturation; | ||
93 | int gamma; | ||
94 | }; | ||
95 | |||
96 | #define DECODER_INDYCAM_GET_CONTROLS _IOR('d', 193, struct indycam_control) | ||
97 | #define DECODER_INDYCAM_SET_CONTROLS _IOW('d', 194, struct indycam_control) | ||
98 | |||
99 | /* Default values for controls */ | ||
100 | |||
101 | #define INDYCAM_AGC_DEFAULT INDYCAM_VALUE_ENABLED | ||
102 | #define INDYCAM_AWB_DEFAULT INDYCAM_VALUE_ENABLED | ||
103 | |||
104 | #define INDYCAM_SHUTTER_DEFAULT INDYCAM_SHUTTER_60 | ||
105 | #define INDYCAM_GAIN_DEFAULT 0x80 | 81 | #define INDYCAM_GAIN_DEFAULT 0x80 |
106 | #define INDYCAM_RED_BALANCE_DEFAULT 0x18 | 82 | #define INDYCAM_RED_BALANCE_DEFAULT 0x18 |
107 | #define INDYCAM_BLUE_BALANCE_DEFAULT 0xa4 | 83 | #define INDYCAM_BLUE_BALANCE_DEFAULT 0xa4 |
@@ -109,4 +85,24 @@ struct indycam_control { | |||
109 | #define INDYCAM_BLUE_SATURATION_DEFAULT 0xc0 | 85 | #define INDYCAM_BLUE_SATURATION_DEFAULT 0xc0 |
110 | #define INDYCAM_GAMMA_DEFAULT 0x80 | 86 | #define INDYCAM_GAMMA_DEFAULT 0x80 |
111 | 87 | ||
88 | /* Driver interface definitions */ | ||
89 | |||
90 | #define INDYCAM_CONTROL_AGC 0 /* boolean */ | ||
91 | #define INDYCAM_CONTROL_AWB 1 /* boolean */ | ||
92 | #define INDYCAM_CONTROL_SHUTTER 2 | ||
93 | #define INDYCAM_CONTROL_GAIN 3 | ||
94 | #define INDYCAM_CONTROL_RED_BALANCE 4 | ||
95 | #define INDYCAM_CONTROL_BLUE_BALANCE 5 | ||
96 | #define INDYCAM_CONTROL_RED_SATURATION 6 | ||
97 | #define INDYCAM_CONTROL_BLUE_SATURATION 7 | ||
98 | #define INDYCAM_CONTROL_GAMMA 8 | ||
99 | |||
100 | struct indycam_control { | ||
101 | u8 type; | ||
102 | s32 value; | ||
103 | }; | ||
104 | |||
105 | #define DECODER_INDYCAM_GET_CONTROL _IOR('d', 193, struct indycam_control) | ||
106 | #define DECODER_INDYCAM_SET_CONTROL _IOW('d', 194, struct indycam_control) | ||
107 | |||
112 | #endif | 108 | #endif |
diff --git a/drivers/media/video/saa7191.c b/drivers/media/video/saa7191.c index 3ddbb62312be..cbca896e8cfa 100644 --- a/drivers/media/video/saa7191.c +++ b/drivers/media/video/saa7191.c | |||
@@ -26,71 +26,95 @@ | |||
26 | 26 | ||
27 | #include "saa7191.h" | 27 | #include "saa7191.h" |
28 | 28 | ||
29 | #define SAA7191_MODULE_VERSION "0.0.3" | 29 | #define SAA7191_MODULE_VERSION "0.0.5" |
30 | 30 | ||
31 | MODULE_DESCRIPTION("Philips SAA7191 video decoder driver"); | 31 | MODULE_DESCRIPTION("Philips SAA7191 video decoder driver"); |
32 | MODULE_VERSION(SAA7191_MODULE_VERSION); | 32 | MODULE_VERSION(SAA7191_MODULE_VERSION); |
33 | MODULE_AUTHOR("Mikael Nousiainen <tmnousia@cc.hut.fi>"); | 33 | MODULE_AUTHOR("Mikael Nousiainen <tmnousia@cc.hut.fi>"); |
34 | MODULE_LICENSE("GPL"); | 34 | MODULE_LICENSE("GPL"); |
35 | 35 | ||
36 | // #define SAA7191_DEBUG | ||
37 | |||
38 | #ifdef SAA7191_DEBUG | ||
39 | #define dprintk(x...) printk("SAA7191: " x); | ||
40 | #else | ||
41 | #define dprintk(x...) | ||
42 | #endif | ||
43 | |||
44 | #define SAA7191_SYNC_COUNT 30 | ||
45 | #define SAA7191_SYNC_DELAY 100 /* milliseconds */ | ||
46 | |||
36 | struct saa7191 { | 47 | struct saa7191 { |
37 | struct i2c_client *client; | 48 | struct i2c_client *client; |
38 | 49 | ||
39 | /* the register values are stored here as the actual | 50 | /* the register values are stored here as the actual |
40 | * I2C-registers are write-only */ | 51 | * I2C-registers are write-only */ |
41 | unsigned char reg[25]; | 52 | u8 reg[25]; |
42 | 53 | ||
43 | unsigned char norm; | 54 | int input; |
44 | unsigned char input; | 55 | int norm; |
45 | }; | 56 | }; |
46 | 57 | ||
47 | static struct i2c_driver i2c_driver_saa7191; | 58 | static struct i2c_driver i2c_driver_saa7191; |
48 | 59 | ||
49 | static const unsigned char initseq[] = { | 60 | static const u8 initseq[] = { |
50 | 0, /* Subaddress */ | 61 | 0, /* Subaddress */ |
51 | 0x50, /* SAA7191_REG_IDEL */ | 62 | |
52 | 0x30, /* SAA7191_REG_HSYB */ | 63 | 0x50, /* (0x50) SAA7191_REG_IDEL */ |
53 | 0x00, /* SAA7191_REG_HSYS */ | 64 | |
54 | 0xe8, /* SAA7191_REG_HCLB */ | 65 | /* 50 Hz signal timing */ |
55 | 0xb6, /* SAA7191_REG_HCLS */ | 66 | 0x30, /* (0x30) SAA7191_REG_HSYB */ |
56 | 0xf4, /* SAA7191_REG_HPHI */ | 67 | 0x00, /* (0x00) SAA7191_REG_HSYS */ |
57 | 0x01, /* SAA7191_REG_LUMA - chrominance trap active (CVBS) */ | 68 | 0xe8, /* (0xe8) SAA7191_REG_HCLB */ |
58 | 0x00, /* SAA7191_REG_HUEC */ | 69 | 0xb6, /* (0xb6) SAA7191_REG_HCLS */ |
59 | 0xf8, /* SAA7191_REG_CKTQ */ | 70 | 0xf4, /* (0xf4) SAA7191_REG_HPHI */ |
60 | 0xf8, /* SAA7191_REG_CKTS */ | 71 | |
61 | 0x90, /* SAA7191_REG_PLSE */ | 72 | /* control */ |
62 | 0x90, /* SAA7191_REG_SESE */ | 73 | SAA7191_LUMA_APER_1, /* (0x01) SAA7191_REG_LUMA - CVBS mode */ |
63 | 0x00, /* SAA7191_REG_GAIN */ | 74 | 0x00, /* (0x00) SAA7191_REG_HUEC */ |
64 | 0x0c, /* SAA7191_REG_STDC - not SECAM, slow time constant */ | 75 | 0xf8, /* (0xf8) SAA7191_REG_CKTQ */ |
65 | 0x78, /* SAA7191_REG_IOCK - chrominance from CVBS, GPSW1 & 2 off */ | 76 | 0xf8, /* (0xf8) SAA7191_REG_CKTS */ |
66 | 0x99, /* SAA7191_REG_CTL3 - automatic field detection */ | 77 | 0x90, /* (0x90) SAA7191_REG_PLSE */ |
67 | 0x00, /* SAA7191_REG_CTL4 */ | 78 | 0x90, /* (0x90) SAA7191_REG_SESE */ |
68 | 0x2c, /* SAA7191_REG_CHCV */ | 79 | 0x00, /* (0x00) SAA7191_REG_GAIN */ |
80 | SAA7191_STDC_NFEN | SAA7191_STDC_HRMV, /* (0x0c) SAA7191_REG_STDC | ||
81 | * - not SECAM, | ||
82 | * slow time constant */ | ||
83 | SAA7191_IOCK_OEDC | SAA7191_IOCK_OEHS | SAA7191_IOCK_OEVS | ||
84 | | SAA7191_IOCK_OEDY, /* (0x78) SAA7191_REG_IOCK | ||
85 | * - chroma from CVBS, GPSW1 & 2 off */ | ||
86 | SAA7191_CTL3_AUFD | SAA7191_CTL3_SCEN | SAA7191_CTL3_OFTS | ||
87 | | SAA7191_CTL3_YDEL0, /* (0x99) SAA7191_REG_CTL3 | ||
88 | * - automatic field detection */ | ||
89 | 0x00, /* (0x00) SAA7191_REG_CTL4 */ | ||
90 | 0x2c, /* (0x2c) SAA7191_REG_CHCV - PAL nominal value */ | ||
69 | 0x00, /* unused */ | 91 | 0x00, /* unused */ |
70 | 0x00, /* unused */ | 92 | 0x00, /* unused */ |
71 | 0x34, /* SAA7191_REG_HS6B */ | 93 | |
72 | 0x0a, /* SAA7191_REG_HS6S */ | 94 | /* 60 Hz signal timing */ |
73 | 0xf4, /* SAA7191_REG_HC6B */ | 95 | 0x34, /* (0x34) SAA7191_REG_HS6B */ |
74 | 0xce, /* SAA7191_REG_HC6S */ | 96 | 0x0a, /* (0x0a) SAA7191_REG_HS6S */ |
75 | 0xf4, /* SAA7191_REG_HP6I */ | 97 | 0xf4, /* (0xf4) SAA7191_REG_HC6B */ |
98 | 0xce, /* (0xce) SAA7191_REG_HC6S */ | ||
99 | 0xf4, /* (0xf4) SAA7191_REG_HP6I */ | ||
76 | }; | 100 | }; |
77 | 101 | ||
78 | /* SAA7191 register handling */ | 102 | /* SAA7191 register handling */ |
79 | 103 | ||
80 | static unsigned char saa7191_read_reg(struct i2c_client *client, | 104 | static u8 saa7191_read_reg(struct i2c_client *client, |
81 | unsigned char reg) | 105 | u8 reg) |
82 | { | 106 | { |
83 | return ((struct saa7191 *)i2c_get_clientdata(client))->reg[reg]; | 107 | return ((struct saa7191 *)i2c_get_clientdata(client))->reg[reg]; |
84 | } | 108 | } |
85 | 109 | ||
86 | static int saa7191_read_status(struct i2c_client *client, | 110 | static int saa7191_read_status(struct i2c_client *client, |
87 | unsigned char *value) | 111 | u8 *value) |
88 | { | 112 | { |
89 | int ret; | 113 | int ret; |
90 | 114 | ||
91 | ret = i2c_master_recv(client, value, 1); | 115 | ret = i2c_master_recv(client, value, 1); |
92 | if (ret < 0) { | 116 | if (ret < 0) { |
93 | printk(KERN_ERR "SAA7191: saa7191_read_status(): read failed"); | 117 | printk(KERN_ERR "SAA7191: saa7191_read_status(): read failed\n"); |
94 | return ret; | 118 | return ret; |
95 | } | 119 | } |
96 | 120 | ||
@@ -98,17 +122,16 @@ static int saa7191_read_status(struct i2c_client *client, | |||
98 | } | 122 | } |
99 | 123 | ||
100 | 124 | ||
101 | static int saa7191_write_reg(struct i2c_client *client, unsigned char reg, | 125 | static int saa7191_write_reg(struct i2c_client *client, u8 reg, |
102 | unsigned char value) | 126 | u8 value) |
103 | { | 127 | { |
104 | |||
105 | ((struct saa7191 *)i2c_get_clientdata(client))->reg[reg] = value; | 128 | ((struct saa7191 *)i2c_get_clientdata(client))->reg[reg] = value; |
106 | return i2c_smbus_write_byte_data(client, reg, value); | 129 | return i2c_smbus_write_byte_data(client, reg, value); |
107 | } | 130 | } |
108 | 131 | ||
109 | /* the first byte of data must be the first subaddress number (register) */ | 132 | /* the first byte of data must be the first subaddress number (register) */ |
110 | static int saa7191_write_block(struct i2c_client *client, | 133 | static int saa7191_write_block(struct i2c_client *client, |
111 | unsigned char length, unsigned char *data) | 134 | u8 length, u8 *data) |
112 | { | 135 | { |
113 | int i; | 136 | int i; |
114 | int ret; | 137 | int ret; |
@@ -121,7 +144,7 @@ static int saa7191_write_block(struct i2c_client *client, | |||
121 | ret = i2c_master_send(client, data, length); | 144 | ret = i2c_master_send(client, data, length); |
122 | if (ret < 0) { | 145 | if (ret < 0) { |
123 | printk(KERN_ERR "SAA7191: saa7191_write_block(): " | 146 | printk(KERN_ERR "SAA7191: saa7191_write_block(): " |
124 | "write failed"); | 147 | "write failed\n"); |
125 | return ret; | 148 | return ret; |
126 | } | 149 | } |
127 | 150 | ||
@@ -132,8 +155,9 @@ static int saa7191_write_block(struct i2c_client *client, | |||
132 | 155 | ||
133 | static int saa7191_set_input(struct i2c_client *client, int input) | 156 | static int saa7191_set_input(struct i2c_client *client, int input) |
134 | { | 157 | { |
135 | unsigned char luma = saa7191_read_reg(client, SAA7191_REG_LUMA); | 158 | struct saa7191 *decoder = i2c_get_clientdata(client); |
136 | unsigned char iock = saa7191_read_reg(client, SAA7191_REG_IOCK); | 159 | u8 luma = saa7191_read_reg(client, SAA7191_REG_LUMA); |
160 | u8 iock = saa7191_read_reg(client, SAA7191_REG_IOCK); | ||
137 | int err; | 161 | int err; |
138 | 162 | ||
139 | switch (input) { | 163 | switch (input) { |
@@ -159,32 +183,20 @@ static int saa7191_set_input(struct i2c_client *client, int input) | |||
159 | if (err) | 183 | if (err) |
160 | return -EIO; | 184 | return -EIO; |
161 | 185 | ||
186 | decoder->input = input; | ||
187 | |||
162 | return 0; | 188 | return 0; |
163 | } | 189 | } |
164 | 190 | ||
165 | static int saa7191_set_norm(struct i2c_client *client, int norm) | 191 | static int saa7191_set_norm(struct i2c_client *client, int norm) |
166 | { | 192 | { |
167 | struct saa7191 *decoder = i2c_get_clientdata(client); | 193 | struct saa7191 *decoder = i2c_get_clientdata(client); |
168 | unsigned char stdc = saa7191_read_reg(client, SAA7191_REG_STDC); | 194 | u8 stdc = saa7191_read_reg(client, SAA7191_REG_STDC); |
169 | unsigned char ctl3 = saa7191_read_reg(client, SAA7191_REG_CTL3); | 195 | u8 ctl3 = saa7191_read_reg(client, SAA7191_REG_CTL3); |
170 | unsigned char chcv = saa7191_read_reg(client, SAA7191_REG_CHCV); | 196 | u8 chcv = saa7191_read_reg(client, SAA7191_REG_CHCV); |
171 | int err; | 197 | int err; |
172 | 198 | ||
173 | switch(norm) { | 199 | switch(norm) { |
174 | case SAA7191_NORM_AUTO: { | ||
175 | unsigned char status; | ||
176 | |||
177 | // does status depend on current norm ? | ||
178 | if (saa7191_read_status(client, &status)) | ||
179 | return -EIO; | ||
180 | |||
181 | stdc &= ~SAA7191_STDC_SECS; | ||
182 | ctl3 &= ~SAA7191_CTL3_FSEL; | ||
183 | ctl3 |= SAA7191_CTL3_AUFD; | ||
184 | chcv = (status & SAA7191_STATUS_FIDT) | ||
185 | ? SAA7191_CHCV_NTSC : SAA7191_CHCV_PAL; | ||
186 | break; | ||
187 | } | ||
188 | case SAA7191_NORM_PAL: | 200 | case SAA7191_NORM_PAL: |
189 | stdc &= ~SAA7191_STDC_SECS; | 201 | stdc &= ~SAA7191_STDC_SECS; |
190 | ctl3 &= ~(SAA7191_CTL3_AUFD | SAA7191_CTL3_FSEL); | 202 | ctl3 &= ~(SAA7191_CTL3_AUFD | SAA7191_CTL3_FSEL); |
@@ -217,60 +229,335 @@ static int saa7191_set_norm(struct i2c_client *client, int norm) | |||
217 | 229 | ||
218 | decoder->norm = norm; | 230 | decoder->norm = norm; |
219 | 231 | ||
232 | dprintk("ctl3: %02x stdc: %02x chcv: %02x\n", ctl3, | ||
233 | stdc, chcv); | ||
234 | dprintk("norm: %d\n", norm); | ||
235 | |||
220 | return 0; | 236 | return 0; |
221 | } | 237 | } |
222 | 238 | ||
223 | static int saa7191_get_controls(struct i2c_client *client, | 239 | static int saa7191_wait_for_signal(struct i2c_client *client, u8 *status) |
224 | struct saa7191_control *ctrl) | ||
225 | { | 240 | { |
226 | unsigned char hue = saa7191_read_reg(client, SAA7191_REG_HUEC); | 241 | int i = 0; |
227 | unsigned char stdc = saa7191_read_reg(client, SAA7191_REG_STDC); | ||
228 | 242 | ||
229 | if (hue < 0x80) { | 243 | dprintk("Checking for signal...\n"); |
230 | hue += 0x80; | 244 | |
231 | } else { | 245 | for (i = 0; i < SAA7191_SYNC_COUNT; i++) { |
232 | hue -= 0x80; | 246 | if (saa7191_read_status(client, status)) |
247 | return -EIO; | ||
248 | |||
249 | if (((*status) & SAA7191_STATUS_HLCK) == 0) { | ||
250 | dprintk("Signal found\n"); | ||
251 | return 0; | ||
252 | } | ||
253 | |||
254 | msleep(SAA7191_SYNC_DELAY); | ||
233 | } | 255 | } |
234 | ctrl->hue = hue; | ||
235 | 256 | ||
236 | ctrl->vtrc = (stdc & SAA7191_STDC_VTRC) | 257 | dprintk("No signal\n"); |
237 | ? SAA7191_VALUE_ENABLED : SAA7191_VALUE_DISABLED; | ||
238 | 258 | ||
239 | return 0; | 259 | return -EBUSY; |
240 | } | 260 | } |
241 | 261 | ||
242 | static int saa7191_set_controls(struct i2c_client *client, | 262 | static int saa7191_autodetect_norm_extended(struct i2c_client *client) |
243 | struct saa7191_control *ctrl) | ||
244 | { | 263 | { |
245 | int err; | 264 | u8 stdc = saa7191_read_reg(client, SAA7191_REG_STDC); |
265 | u8 ctl3 = saa7191_read_reg(client, SAA7191_REG_CTL3); | ||
266 | u8 status; | ||
267 | int err = 0; | ||
246 | 268 | ||
247 | if (ctrl->hue >= 0) { | 269 | dprintk("SAA7191 extended signal auto-detection...\n"); |
248 | unsigned char hue = ctrl->hue & 0xff; | 270 | |
249 | if (hue < 0x80) { | 271 | stdc &= ~SAA7191_STDC_SECS; |
250 | hue += 0x80; | 272 | ctl3 &= ~(SAA7191_CTL3_FSEL); |
251 | } else { | 273 | |
252 | hue -= 0x80; | 274 | err = saa7191_write_reg(client, SAA7191_REG_STDC, stdc); |
275 | if (err) { | ||
276 | err = -EIO; | ||
277 | goto out; | ||
278 | } | ||
279 | err = saa7191_write_reg(client, SAA7191_REG_CTL3, ctl3); | ||
280 | if (err) { | ||
281 | err = -EIO; | ||
282 | goto out; | ||
283 | } | ||
284 | |||
285 | ctl3 |= SAA7191_CTL3_AUFD; | ||
286 | err = saa7191_write_reg(client, SAA7191_REG_CTL3, ctl3); | ||
287 | if (err) { | ||
288 | err = -EIO; | ||
289 | goto out; | ||
290 | } | ||
291 | |||
292 | msleep(SAA7191_SYNC_DELAY); | ||
293 | |||
294 | err = saa7191_wait_for_signal(client, &status); | ||
295 | if (err) | ||
296 | goto out; | ||
297 | |||
298 | if (status & SAA7191_STATUS_FIDT) { | ||
299 | /* 60Hz signal -> NTSC */ | ||
300 | dprintk("60Hz signal: NTSC\n"); | ||
301 | return saa7191_set_norm(client, SAA7191_NORM_NTSC); | ||
302 | } | ||
303 | |||
304 | /* 50Hz signal */ | ||
305 | dprintk("50Hz signal: Trying PAL...\n"); | ||
306 | |||
307 | /* try PAL first */ | ||
308 | err = saa7191_set_norm(client, SAA7191_NORM_PAL); | ||
309 | if (err) | ||
310 | goto out; | ||
311 | |||
312 | msleep(SAA7191_SYNC_DELAY); | ||
313 | |||
314 | err = saa7191_wait_for_signal(client, &status); | ||
315 | if (err) | ||
316 | goto out; | ||
317 | |||
318 | /* not 50Hz ? */ | ||
319 | if (status & SAA7191_STATUS_FIDT) { | ||
320 | dprintk("No 50Hz signal\n"); | ||
321 | err = -EAGAIN; | ||
322 | goto out; | ||
323 | } | ||
324 | |||
325 | if (status & SAA7191_STATUS_CODE) { | ||
326 | dprintk("PAL\n"); | ||
327 | return 0; | ||
328 | } | ||
329 | |||
330 | dprintk("No color detected with PAL - Trying SECAM...\n"); | ||
331 | |||
332 | /* no color detected ? -> try SECAM */ | ||
333 | err = saa7191_set_norm(client, | ||
334 | SAA7191_NORM_SECAM); | ||
335 | if (err) | ||
336 | goto out; | ||
337 | |||
338 | msleep(SAA7191_SYNC_DELAY); | ||
339 | |||
340 | err = saa7191_wait_for_signal(client, &status); | ||
341 | if (err) | ||
342 | goto out; | ||
343 | |||
344 | /* not 50Hz ? */ | ||
345 | if (status & SAA7191_STATUS_FIDT) { | ||
346 | dprintk("No 50Hz signal\n"); | ||
347 | err = -EAGAIN; | ||
348 | goto out; | ||
349 | } | ||
350 | |||
351 | if (status & SAA7191_STATUS_CODE) { | ||
352 | /* Color detected -> SECAM */ | ||
353 | dprintk("SECAM\n"); | ||
354 | return 0; | ||
355 | } | ||
356 | |||
357 | dprintk("No color detected with SECAM - Going back to PAL.\n"); | ||
358 | |||
359 | /* still no color detected ? | ||
360 | * -> set norm back to PAL */ | ||
361 | err = saa7191_set_norm(client, | ||
362 | SAA7191_NORM_PAL); | ||
363 | if (err) | ||
364 | goto out; | ||
365 | |||
366 | out: | ||
367 | ctl3 = saa7191_read_reg(client, SAA7191_REG_CTL3); | ||
368 | if (ctl3 & SAA7191_CTL3_AUFD) { | ||
369 | ctl3 &= ~(SAA7191_CTL3_AUFD); | ||
370 | err = saa7191_write_reg(client, SAA7191_REG_CTL3, ctl3); | ||
371 | if (err) { | ||
372 | err = -EIO; | ||
253 | } | 373 | } |
254 | err = saa7191_write_reg(client, SAA7191_REG_HUEC, hue); | ||
255 | if (err) | ||
256 | return -EIO; | ||
257 | } | 374 | } |
258 | if (ctrl->vtrc >= 0) { | ||
259 | unsigned char stdc = | ||
260 | saa7191_read_reg(client, SAA7191_REG_STDC); | ||
261 | 375 | ||
262 | if (ctrl->vtrc) { | 376 | return err; |
263 | stdc |= SAA7191_STDC_VTRC; | 377 | } |
264 | } else { | 378 | |
265 | stdc &= ~SAA7191_STDC_VTRC; | 379 | static int saa7191_autodetect_norm(struct i2c_client *client) |
380 | { | ||
381 | u8 status; | ||
382 | |||
383 | dprintk("SAA7191 signal auto-detection...\n"); | ||
384 | |||
385 | dprintk("Reading status...\n"); | ||
386 | |||
387 | if (saa7191_read_status(client, &status)) | ||
388 | return -EIO; | ||
389 | |||
390 | dprintk("Checking for signal...\n"); | ||
391 | |||
392 | /* no signal ? */ | ||
393 | if (status & SAA7191_STATUS_HLCK) { | ||
394 | dprintk("No signal\n"); | ||
395 | return -EBUSY; | ||
396 | } | ||
397 | |||
398 | dprintk("Signal found\n"); | ||
399 | |||
400 | if (status & SAA7191_STATUS_FIDT) { | ||
401 | /* 60hz signal -> NTSC */ | ||
402 | dprintk("NTSC\n"); | ||
403 | return saa7191_set_norm(client, SAA7191_NORM_NTSC); | ||
404 | } else { | ||
405 | /* 50hz signal -> PAL */ | ||
406 | dprintk("PAL\n"); | ||
407 | return saa7191_set_norm(client, SAA7191_NORM_PAL); | ||
408 | } | ||
409 | } | ||
410 | |||
411 | static int saa7191_get_control(struct i2c_client *client, | ||
412 | struct saa7191_control *ctrl) | ||
413 | { | ||
414 | u8 reg; | ||
415 | int ret = 0; | ||
416 | |||
417 | switch (ctrl->type) { | ||
418 | case SAA7191_CONTROL_BANDPASS: | ||
419 | case SAA7191_CONTROL_BANDPASS_WEIGHT: | ||
420 | case SAA7191_CONTROL_CORING: | ||
421 | reg = saa7191_read_reg(client, SAA7191_REG_LUMA); | ||
422 | switch (ctrl->type) { | ||
423 | case SAA7191_CONTROL_BANDPASS: | ||
424 | ctrl->value = ((s32)reg & SAA7191_LUMA_BPSS_MASK) | ||
425 | >> SAA7191_LUMA_BPSS_SHIFT; | ||
426 | break; | ||
427 | case SAA7191_CONTROL_BANDPASS_WEIGHT: | ||
428 | ctrl->value = ((s32)reg & SAA7191_LUMA_APER_MASK) | ||
429 | >> SAA7191_LUMA_APER_SHIFT; | ||
430 | break; | ||
431 | case SAA7191_CONTROL_CORING: | ||
432 | ctrl->value = ((s32)reg & SAA7191_LUMA_CORI_MASK) | ||
433 | >> SAA7191_LUMA_CORI_SHIFT; | ||
434 | break; | ||
266 | } | 435 | } |
436 | break; | ||
437 | case SAA7191_CONTROL_FORCE_COLOUR: | ||
438 | case SAA7191_CONTROL_CHROMA_GAIN: | ||
439 | reg = saa7191_read_reg(client, SAA7191_REG_GAIN); | ||
440 | if (ctrl->type == SAA7191_CONTROL_FORCE_COLOUR) | ||
441 | ctrl->value = ((s32)reg & SAA7191_GAIN_COLO) ? 1 : 0; | ||
442 | else | ||
443 | ctrl->value = ((s32)reg & SAA7191_GAIN_LFIS_MASK) | ||
444 | >> SAA7191_GAIN_LFIS_SHIFT; | ||
445 | break; | ||
446 | case SAA7191_CONTROL_HUE: | ||
447 | reg = saa7191_read_reg(client, SAA7191_REG_HUEC); | ||
448 | if (reg < 0x80) | ||
449 | reg += 0x80; | ||
450 | else | ||
451 | reg -= 0x80; | ||
452 | ctrl->value = (s32)reg; | ||
453 | break; | ||
454 | case SAA7191_CONTROL_VTRC: | ||
455 | reg = saa7191_read_reg(client, SAA7191_REG_STDC); | ||
456 | ctrl->value = ((s32)reg & SAA7191_STDC_VTRC) ? 1 : 0; | ||
457 | break; | ||
458 | case SAA7191_CONTROL_LUMA_DELAY: | ||
459 | reg = saa7191_read_reg(client, SAA7191_REG_CTL3); | ||
460 | ctrl->value = ((s32)reg & SAA7191_CTL3_YDEL_MASK) | ||
461 | >> SAA7191_CTL3_YDEL_SHIFT; | ||
462 | if (ctrl->value >= 4) | ||
463 | ctrl->value -= 8; | ||
464 | break; | ||
465 | case SAA7191_CONTROL_VNR: | ||
466 | reg = saa7191_read_reg(client, SAA7191_REG_CTL4); | ||
467 | ctrl->value = ((s32)reg & SAA7191_CTL4_VNOI_MASK) | ||
468 | >> SAA7191_CTL4_VNOI_SHIFT; | ||
469 | break; | ||
470 | default: | ||
471 | ret = -EINVAL; | ||
472 | } | ||
267 | 473 | ||
268 | err = saa7191_write_reg(client, SAA7191_REG_STDC, stdc); | 474 | return ret; |
269 | if (err) | 475 | } |
270 | return -EIO; | 476 | |
477 | static int saa7191_set_control(struct i2c_client *client, | ||
478 | struct saa7191_control *ctrl) | ||
479 | { | ||
480 | u8 reg; | ||
481 | int ret = 0; | ||
482 | |||
483 | switch (ctrl->type) { | ||
484 | case SAA7191_CONTROL_BANDPASS: | ||
485 | case SAA7191_CONTROL_BANDPASS_WEIGHT: | ||
486 | case SAA7191_CONTROL_CORING: | ||
487 | reg = saa7191_read_reg(client, SAA7191_REG_LUMA); | ||
488 | switch (ctrl->type) { | ||
489 | case SAA7191_CONTROL_BANDPASS: | ||
490 | reg &= ~SAA7191_LUMA_BPSS_MASK; | ||
491 | reg |= (ctrl->value << SAA7191_LUMA_BPSS_SHIFT) | ||
492 | & SAA7191_LUMA_BPSS_MASK; | ||
493 | break; | ||
494 | case SAA7191_CONTROL_BANDPASS_WEIGHT: | ||
495 | reg &= ~SAA7191_LUMA_APER_MASK; | ||
496 | reg |= (ctrl->value << SAA7191_LUMA_APER_SHIFT) | ||
497 | & SAA7191_LUMA_APER_MASK; | ||
498 | break; | ||
499 | case SAA7191_CONTROL_CORING: | ||
500 | reg &= ~SAA7191_LUMA_CORI_MASK; | ||
501 | reg |= (ctrl->value << SAA7191_LUMA_CORI_SHIFT) | ||
502 | & SAA7191_LUMA_CORI_MASK; | ||
503 | break; | ||
504 | } | ||
505 | ret = saa7191_write_reg(client, SAA7191_REG_LUMA, reg); | ||
506 | break; | ||
507 | case SAA7191_CONTROL_FORCE_COLOUR: | ||
508 | case SAA7191_CONTROL_CHROMA_GAIN: | ||
509 | reg = saa7191_read_reg(client, SAA7191_REG_GAIN); | ||
510 | if (ctrl->type == SAA7191_CONTROL_FORCE_COLOUR) { | ||
511 | if (ctrl->value) | ||
512 | reg |= SAA7191_GAIN_COLO; | ||
513 | else | ||
514 | reg &= ~SAA7191_GAIN_COLO; | ||
515 | } else { | ||
516 | reg &= ~SAA7191_GAIN_LFIS_MASK; | ||
517 | reg |= (ctrl->value << SAA7191_GAIN_LFIS_SHIFT) | ||
518 | & SAA7191_GAIN_LFIS_MASK; | ||
519 | } | ||
520 | ret = saa7191_write_reg(client, SAA7191_REG_GAIN, reg); | ||
521 | break; | ||
522 | case SAA7191_CONTROL_HUE: | ||
523 | reg = ctrl->value & 0xff; | ||
524 | if (reg < 0x80) | ||
525 | reg += 0x80; | ||
526 | else | ||
527 | reg -= 0x80; | ||
528 | ret = saa7191_write_reg(client, SAA7191_REG_HUEC, reg); | ||
529 | break; | ||
530 | case SAA7191_CONTROL_VTRC: | ||
531 | reg = saa7191_read_reg(client, SAA7191_REG_STDC); | ||
532 | if (ctrl->value) | ||
533 | reg |= SAA7191_STDC_VTRC; | ||
534 | else | ||
535 | reg &= ~SAA7191_STDC_VTRC; | ||
536 | ret = saa7191_write_reg(client, SAA7191_REG_STDC, reg); | ||
537 | break; | ||
538 | case SAA7191_CONTROL_LUMA_DELAY: { | ||
539 | s32 value = ctrl->value; | ||
540 | if (value < 0) | ||
541 | value += 8; | ||
542 | reg = saa7191_read_reg(client, SAA7191_REG_CTL3); | ||
543 | reg &= ~SAA7191_CTL3_YDEL_MASK; | ||
544 | reg |= (value << SAA7191_CTL3_YDEL_SHIFT) | ||
545 | & SAA7191_CTL3_YDEL_MASK; | ||
546 | ret = saa7191_write_reg(client, SAA7191_REG_CTL3, reg); | ||
547 | break; | ||
548 | } | ||
549 | case SAA7191_CONTROL_VNR: | ||
550 | reg = saa7191_read_reg(client, SAA7191_REG_CTL4); | ||
551 | reg &= ~SAA7191_CTL4_VNOI_MASK; | ||
552 | reg |= (ctrl->value << SAA7191_CTL4_VNOI_SHIFT) | ||
553 | & SAA7191_CTL4_VNOI_MASK; | ||
554 | ret = saa7191_write_reg(client, SAA7191_REG_CTL4, reg); | ||
555 | break; | ||
556 | default: | ||
557 | ret = -EINVAL; | ||
271 | } | 558 | } |
272 | 559 | ||
273 | return 0; | 560 | return ret; |
274 | } | 561 | } |
275 | 562 | ||
276 | /* I2C-interface */ | 563 | /* I2C-interface */ |
@@ -309,11 +596,7 @@ static int saa7191_attach(struct i2c_adapter *adap, int addr, int kind) | |||
309 | if (err) | 596 | if (err) |
310 | goto out_free_decoder; | 597 | goto out_free_decoder; |
311 | 598 | ||
312 | decoder->input = SAA7191_INPUT_COMPOSITE; | 599 | err = saa7191_write_block(client, sizeof(initseq), (u8 *)initseq); |
313 | decoder->norm = SAA7191_NORM_AUTO; | ||
314 | |||
315 | err = saa7191_write_block(client, sizeof(initseq), | ||
316 | (unsigned char *)initseq); | ||
317 | if (err) { | 600 | if (err) { |
318 | printk(KERN_ERR "SAA7191 initialization failed\n"); | 601 | printk(KERN_ERR "SAA7191 initialization failed\n"); |
319 | goto out_detach_client; | 602 | goto out_detach_client; |
@@ -321,6 +604,14 @@ static int saa7191_attach(struct i2c_adapter *adap, int addr, int kind) | |||
321 | 604 | ||
322 | printk(KERN_INFO "SAA7191 initialized\n"); | 605 | printk(KERN_INFO "SAA7191 initialized\n"); |
323 | 606 | ||
607 | decoder->input = SAA7191_INPUT_COMPOSITE; | ||
608 | decoder->norm = SAA7191_NORM_PAL; | ||
609 | |||
610 | err = saa7191_autodetect_norm(client); | ||
611 | if (err && (err != -EBUSY)) { | ||
612 | printk(KERN_ERR "SAA7191: Signal auto-detection failed\n"); | ||
613 | } | ||
614 | |||
324 | return 0; | 615 | return 0; |
325 | 616 | ||
326 | out_detach_client: | 617 | out_detach_client: |
@@ -368,7 +659,7 @@ static int saa7191_command(struct i2c_client *client, unsigned int cmd, | |||
368 | } | 659 | } |
369 | case DECODER_GET_STATUS: { | 660 | case DECODER_GET_STATUS: { |
370 | int *iarg = arg; | 661 | int *iarg = arg; |
371 | unsigned char status; | 662 | u8 status; |
372 | int res = 0; | 663 | int res = 0; |
373 | 664 | ||
374 | if (saa7191_read_status(client, &status)) { | 665 | if (saa7191_read_status(client, &status)) { |
@@ -404,7 +695,7 @@ static int saa7191_command(struct i2c_client *client, unsigned int cmd, | |||
404 | 695 | ||
405 | switch (*iarg) { | 696 | switch (*iarg) { |
406 | case VIDEO_MODE_AUTO: | 697 | case VIDEO_MODE_AUTO: |
407 | return saa7191_set_norm(client, SAA7191_NORM_AUTO); | 698 | return saa7191_autodetect_norm(client); |
408 | case VIDEO_MODE_PAL: | 699 | case VIDEO_MODE_PAL: |
409 | return saa7191_set_norm(client, SAA7191_NORM_PAL); | 700 | return saa7191_set_norm(client, SAA7191_NORM_PAL); |
410 | case VIDEO_MODE_NTSC: | 701 | case VIDEO_MODE_NTSC: |
@@ -446,38 +737,48 @@ static int saa7191_command(struct i2c_client *client, unsigned int cmd, | |||
446 | int err; | 737 | int err; |
447 | 738 | ||
448 | val = (pic->hue >> 8) - 0x80; | 739 | val = (pic->hue >> 8) - 0x80; |
740 | |||
449 | err = saa7191_write_reg(client, SAA7191_REG_HUEC, val); | 741 | err = saa7191_write_reg(client, SAA7191_REG_HUEC, val); |
450 | if (err) | 742 | if (err) |
451 | return -EIO; | 743 | return -EIO; |
744 | |||
452 | break; | 745 | break; |
453 | } | 746 | } |
454 | case DECODER_SAA7191_GET_STATUS: { | 747 | case DECODER_SAA7191_GET_STATUS: { |
455 | struct saa7191_status *status = arg; | 748 | struct saa7191_status *status = arg; |
456 | unsigned char status_reg; | 749 | u8 status_reg; |
457 | 750 | ||
458 | if (saa7191_read_status(client, &status_reg)) | 751 | if (saa7191_read_status(client, &status_reg)) |
459 | return -EIO; | 752 | return -EIO; |
753 | |||
460 | status->signal = ((status_reg & SAA7191_STATUS_HLCK) == 0) | 754 | status->signal = ((status_reg & SAA7191_STATUS_HLCK) == 0) |
461 | ? SAA7191_VALUE_ENABLED : SAA7191_VALUE_DISABLED; | 755 | ? 1 : 0; |
462 | status->ntsc = (status_reg & SAA7191_STATUS_FIDT) | 756 | status->signal_60hz = (status_reg & SAA7191_STATUS_FIDT) |
463 | ? SAA7191_VALUE_ENABLED : SAA7191_VALUE_DISABLED; | 757 | ? 1 : 0; |
464 | status->color = (status_reg & SAA7191_STATUS_CODE) | 758 | status->color = (status_reg & SAA7191_STATUS_CODE) ? 1 : 0; |
465 | ? SAA7191_VALUE_ENABLED : SAA7191_VALUE_DISABLED; | ||
466 | 759 | ||
467 | status->input = decoder->input; | 760 | status->input = decoder->input; |
468 | status->norm = decoder->norm; | 761 | status->norm = decoder->norm; |
762 | |||
763 | break; | ||
469 | } | 764 | } |
470 | case DECODER_SAA7191_SET_NORM: { | 765 | case DECODER_SAA7191_SET_NORM: { |
471 | int *norm = arg; | 766 | int *norm = arg; |
472 | return saa7191_set_norm(client, *norm); | 767 | |
768 | switch (*norm) { | ||
769 | case SAA7191_NORM_AUTO: | ||
770 | return saa7191_autodetect_norm(client); | ||
771 | case SAA7191_NORM_AUTO_EXT: | ||
772 | return saa7191_autodetect_norm_extended(client); | ||
773 | default: | ||
774 | return saa7191_set_norm(client, *norm); | ||
775 | } | ||
473 | } | 776 | } |
474 | case DECODER_SAA7191_GET_CONTROLS: { | 777 | case DECODER_SAA7191_GET_CONTROL: { |
475 | struct saa7191_control *ctrl = arg; | 778 | return saa7191_get_control(client, arg); |
476 | return saa7191_get_controls(client, ctrl); | ||
477 | } | 779 | } |
478 | case DECODER_SAA7191_SET_CONTROLS: { | 780 | case DECODER_SAA7191_SET_CONTROL: { |
479 | struct saa7191_control *ctrl = arg; | 781 | return saa7191_set_control(client, arg); |
480 | return saa7191_set_controls(client, ctrl); | ||
481 | } | 782 | } |
482 | default: | 783 | default: |
483 | return -EINVAL; | 784 | return -EINVAL; |
@@ -488,12 +789,12 @@ static int saa7191_command(struct i2c_client *client, unsigned int cmd, | |||
488 | 789 | ||
489 | static struct i2c_driver i2c_driver_saa7191 = { | 790 | static struct i2c_driver i2c_driver_saa7191 = { |
490 | .owner = THIS_MODULE, | 791 | .owner = THIS_MODULE, |
491 | .name = "saa7191", | 792 | .name = "saa7191", |
492 | .id = I2C_DRIVERID_SAA7191, | 793 | .id = I2C_DRIVERID_SAA7191, |
493 | .flags = I2C_DF_NOTIFY, | 794 | .flags = I2C_DF_NOTIFY, |
494 | .attach_adapter = saa7191_probe, | 795 | .attach_adapter = saa7191_probe, |
495 | .detach_client = saa7191_detach, | 796 | .detach_client = saa7191_detach, |
496 | .command = saa7191_command | 797 | .command = saa7191_command |
497 | }; | 798 | }; |
498 | 799 | ||
499 | static int saa7191_init(void) | 800 | static int saa7191_init(void) |
diff --git a/drivers/media/video/saa7191.h b/drivers/media/video/saa7191.h index 272045031435..a2310da1940d 100644 --- a/drivers/media/video/saa7191.h +++ b/drivers/media/video/saa7191.h | |||
@@ -24,8 +24,8 @@ | |||
24 | #define SAA7191_REG_HPHI 0x05 | 24 | #define SAA7191_REG_HPHI 0x05 |
25 | #define SAA7191_REG_LUMA 0x06 | 25 | #define SAA7191_REG_LUMA 0x06 |
26 | #define SAA7191_REG_HUEC 0x07 | 26 | #define SAA7191_REG_HUEC 0x07 |
27 | #define SAA7191_REG_CKTQ 0x08 | 27 | #define SAA7191_REG_CKTQ 0x08 /* bits 3-7 */ |
28 | #define SAA7191_REG_CKTS 0x09 | 28 | #define SAA7191_REG_CKTS 0x09 /* bits 3-7 */ |
29 | #define SAA7191_REG_PLSE 0x0a | 29 | #define SAA7191_REG_PLSE 0x0a |
30 | #define SAA7191_REG_SESE 0x0b | 30 | #define SAA7191_REG_SESE 0x0b |
31 | #define SAA7191_REG_GAIN 0x0c | 31 | #define SAA7191_REG_GAIN 0x0c |
@@ -43,30 +43,82 @@ | |||
43 | 43 | ||
44 | /* Status Register definitions */ | 44 | /* Status Register definitions */ |
45 | #define SAA7191_STATUS_CODE 0x01 /* color detected flag */ | 45 | #define SAA7191_STATUS_CODE 0x01 /* color detected flag */ |
46 | #define SAA7191_STATUS_FIDT 0x20 /* format type NTSC/PAL */ | 46 | #define SAA7191_STATUS_FIDT 0x20 /* signal type 50/60 Hz */ |
47 | #define SAA7191_STATUS_HLCK 0x40 /* PLL unlocked/locked */ | 47 | #define SAA7191_STATUS_HLCK 0x40 /* PLL unlocked(1)/locked(0) */ |
48 | #define SAA7191_STATUS_STTC 0x80 /* tv/vtr time constant */ | 48 | #define SAA7191_STATUS_STTC 0x80 /* tv/vtr time constant */ |
49 | 49 | ||
50 | /* Luminance Control Register definitions */ | 50 | /* Luminance Control Register definitions */ |
51 | /* input mode select bit: | ||
52 | * 0=CVBS (chrominance trap active), 1=S-Video (trap bypassed) */ | ||
51 | #define SAA7191_LUMA_BYPS 0x80 | 53 | #define SAA7191_LUMA_BYPS 0x80 |
52 | 54 | /* pre-filter (only when chrominance trap is active) */ | |
53 | /* Chroma Gain Control Settings Register definitions */ | 55 | #define SAA7191_LUMA_PREF 0x40 |
54 | /* 0=automatic colour-killer enabled, 1=forced colour on */ | 56 | /* aperture bandpass to select different characteristics with maximums |
57 | * (bits 4-5) */ | ||
58 | #define SAA7191_LUMA_BPSS_MASK 0x30 | ||
59 | #define SAA7191_LUMA_BPSS_SHIFT 4 | ||
60 | #define SAA7191_LUMA_BPSS_3 0x30 | ||
61 | #define SAA7191_LUMA_BPSS_2 0x20 | ||
62 | #define SAA7191_LUMA_BPSS_1 0x10 | ||
63 | #define SAA7191_LUMA_BPSS_0 0x00 | ||
64 | /* coring range for high frequency components according to 8-bit luminance | ||
65 | * (bits 2-3) | ||
66 | * 0=coring off, n= (+-)n LSB */ | ||
67 | #define SAA7191_LUMA_CORI_MASK 0x0c | ||
68 | #define SAA7191_LUMA_CORI_SHIFT 2 | ||
69 | #define SAA7191_LUMA_CORI_3 0x0c | ||
70 | #define SAA7191_LUMA_CORI_2 0x08 | ||
71 | #define SAA7191_LUMA_CORI_1 0x04 | ||
72 | #define SAA7191_LUMA_CORI_0 0x00 | ||
73 | /* aperture bandpass filter weights high frequency components of luminance | ||
74 | * signal (bits 0-1) | ||
75 | * 0=factor 0, 1=0.25, 2=0.5, 3=1 */ | ||
76 | #define SAA7191_LUMA_APER_MASK 0x03 | ||
77 | #define SAA7191_LUMA_APER_SHIFT 0 | ||
78 | #define SAA7191_LUMA_APER_3 0x03 | ||
79 | #define SAA7191_LUMA_APER_2 0x02 | ||
80 | #define SAA7191_LUMA_APER_1 0x01 | ||
81 | #define SAA7191_LUMA_APER_0 0x00 | ||
82 | |||
83 | /* Chrominance Gain Control Settings Register definitions */ | ||
84 | /* colour on: 0=automatic colour-killer enabled, 1=forced colour on */ | ||
55 | #define SAA7191_GAIN_COLO 0x80 | 85 | #define SAA7191_GAIN_COLO 0x80 |
86 | /* chrominance gain control (AGC filter) | ||
87 | * 0=loop filter time constant slow, 1=medium, 2=fast, 3=actual gain */ | ||
88 | #define SAA7191_GAIN_LFIS_MASK 0x60 | ||
89 | #define SAA7191_GAIN_LFIS_SHIFT 5 | ||
90 | #define SAA7191_GAIN_LFIS_3 0x60 | ||
91 | #define SAA7191_GAIN_LFIS_2 0x40 | ||
92 | #define SAA7191_GAIN_LFIS_1 0x20 | ||
93 | #define SAA7191_GAIN_LFIS_0 0x00 | ||
56 | 94 | ||
57 | /* Standard/Mode Control Register definitions */ | 95 | /* Standard/Mode Control Register definitions */ |
58 | /* tv/vtr mode bit: 0=TV mode (slow time constant), | 96 | /* tv/vtr mode bit: 0=TV mode (slow time constant), |
59 | * 1=VTR mode (fast time constant) */ | 97 | * 1=VTR mode (fast time constant) */ |
60 | #define SAA7191_STDC_VTRC 0x80 | 98 | #define SAA7191_STDC_VTRC 0x80 |
99 | /* SAA7191B-specific functions enable (RTCO, ODD and GPSW0 outputs) | ||
100 | * 0=outputs set to high-impedance (circuit equals SAA7191), 1=enabled */ | ||
101 | #define SAA7191_STDC_NFEN 0x08 | ||
102 | /* HREF generation: 0=like SAA7191, 1=HREF is 8xLLC2 clocks earlier */ | ||
103 | #define SAA7191_STDC_HRMV 0x04 | ||
104 | /* general purpose switch 0 | ||
105 | * (not used with VINO afaik) */ | ||
106 | #define SAA7191_STDC_GPSW0 0x02 | ||
61 | /* SECAM mode bit: 0=other standards, 1=SECAM */ | 107 | /* SECAM mode bit: 0=other standards, 1=SECAM */ |
62 | #define SAA7191_STDC_SECS 0x01 | 108 | #define SAA7191_STDC_SECS 0x01 |
63 | /* the bit fields above must be or'd with this value */ | ||
64 | #define SAA7191_STDC_VALUE 0x0c | ||
65 | 109 | ||
66 | /* I/O and Clock Control Register definitions */ | 110 | /* I/O and Clock Control Register definitions */ |
67 | /* horizontal clock PLL: 0=PLL closed, | 111 | /* horizontal clock PLL: 0=PLL closed, |
68 | * 1=PLL circuit open and horizontal freq fixed */ | 112 | * 1=PLL circuit open and horizontal freq fixed */ |
69 | #define SAA7191_IOCK_HPLL 0x80 | 113 | #define SAA7191_IOCK_HPLL 0x80 |
114 | /* colour-difference output enable (outputs UV0-UV7) */ | ||
115 | #define SAA7191_IOCK_OEDC 0x40 | ||
116 | /* H-sync output enable */ | ||
117 | #define SAA7191_IOCK_OEHS 0x20 | ||
118 | /* V-sync output enable */ | ||
119 | #define SAA7191_IOCK_OEVS 0x10 | ||
120 | /* luminance output enable (outputs Y0-Y7) */ | ||
121 | #define SAA7191_IOCK_OEDY 0x08 | ||
70 | /* S-VHS bit (chrominance from CVBS or from chrominance input): | 122 | /* S-VHS bit (chrominance from CVBS or from chrominance input): |
71 | * 0=controlled by BYPS-bit, 1=from chrominance input */ | 123 | * 0=controlled by BYPS-bit, 1=from chrominance input */ |
72 | #define SAA7191_IOCK_CHRS 0x04 | 124 | #define SAA7191_IOCK_CHRS 0x04 |
@@ -83,11 +135,40 @@ | |||
83 | /* field select: (if AUFD=0) | 135 | /* field select: (if AUFD=0) |
84 | * 0=50Hz (625 lines), 1=60Hz (525 lines) */ | 136 | * 0=50Hz (625 lines), 1=60Hz (525 lines) */ |
85 | #define SAA7191_CTL3_FSEL 0x40 | 137 | #define SAA7191_CTL3_FSEL 0x40 |
86 | /* the bit fields above must be or'd with this value */ | 138 | /* SECAM cross-colour reduction enable */ |
87 | #define SAA7191_CTL3_VALUE 0x19 | 139 | #define SAA7191_CTL3_SXCR 0x20 |
140 | /* sync and clamping pulse enable (HCL and HSY outputs) */ | ||
141 | #define SAA7191_CTL3_SCEN 0x10 | ||
142 | /* output format: 0=4:1:1, 1=4:2:2 (4:2:2 for VINO) */ | ||
143 | #define SAA7191_CTL3_OFTS 0x08 | ||
144 | /* luminance delay compensation | ||
145 | * 0=0*2/LLC, 1=+1*2/LLC, 2=+2*2/LLC, 3=+3*2/LLC, | ||
146 | * 4=-4*2/LLC, 5=-3*2/LLC, 6=-2*2/LLC, 7=-1*2/LLC | ||
147 | * step size = 2/LLC = 67.8ns for 50Hz, 81.5ns for 60Hz */ | ||
148 | #define SAA7191_CTL3_YDEL_MASK 0x07 | ||
149 | #define SAA7191_CTL3_YDEL_SHIFT 0 | ||
150 | #define SAA7191_CTL3_YDEL2 0x04 | ||
151 | #define SAA7191_CTL3_YDEL1 0x02 | ||
152 | #define SAA7191_CTL3_YDEL0 0x01 | ||
153 | |||
154 | /* Miscellaneous Control #2 Register definitions */ | ||
155 | /* select HREF position | ||
156 | * 0=normal, HREF is matched to YUV output port, | ||
157 | * 1=HREF is matched to CVBS input port */ | ||
158 | #define SAA7191_CTL4_HRFS 0x04 | ||
159 | /* vertical noise reduction | ||
160 | * 0=normal, 1=searching window, 2=auto-deflection, 3=reduction bypassed */ | ||
161 | #define SAA7191_CTL4_VNOI_MASK 0x03 | ||
162 | #define SAA7191_CTL4_VNOI_SHIFT 0 | ||
163 | #define SAA7191_CTL4_VNOI_3 0x03 | ||
164 | #define SAA7191_CTL4_VNOI_2 0x02 | ||
165 | #define SAA7191_CTL4_VNOI_1 0x01 | ||
166 | #define SAA7191_CTL4_VNOI_0 0x00 | ||
88 | 167 | ||
89 | /* Chrominance Gain Control Register definitions | 168 | /* Chrominance Gain Control Register definitions |
90 | * (nominal value for UV CCIR level) */ | 169 | * - for QAM-modulated input signals, effects output amplitude |
170 | * (SECAM gain fixed) | ||
171 | * (nominal values for UV CCIR level) */ | ||
91 | #define SAA7191_CHCV_NTSC 0x2c | 172 | #define SAA7191_CHCV_NTSC 0x2c |
92 | #define SAA7191_CHCV_PAL 0x59 | 173 | #define SAA7191_CHCV_PAL 0x59 |
93 | 174 | ||
@@ -99,16 +180,13 @@ | |||
99 | #define SAA7191_NORM_PAL 1 | 180 | #define SAA7191_NORM_PAL 1 |
100 | #define SAA7191_NORM_NTSC 2 | 181 | #define SAA7191_NORM_NTSC 2 |
101 | #define SAA7191_NORM_SECAM 3 | 182 | #define SAA7191_NORM_SECAM 3 |
102 | 183 | #define SAA7191_NORM_AUTO_EXT 4 /* extended auto-detection */ | |
103 | #define SAA7191_VALUE_ENABLED 1 | ||
104 | #define SAA7191_VALUE_DISABLED 0 | ||
105 | #define SAA7191_VALUE_UNCHANGED -1 | ||
106 | 184 | ||
107 | struct saa7191_status { | 185 | struct saa7191_status { |
108 | /* 0=no signal, 1=signal active*/ | 186 | /* 0=no signal, 1=signal detected */ |
109 | int signal; | 187 | int signal; |
110 | /* 0=50hz (pal) signal, 1=60hz (ntsc) signal */ | 188 | /* 0=50hz (pal) signal, 1=60hz (ntsc) signal */ |
111 | int ntsc; | 189 | int signal_60hz; |
112 | /* 0=no color detected, 1=color detected */ | 190 | /* 0=no color detected, 1=color detected */ |
113 | int color; | 191 | int color; |
114 | 192 | ||
@@ -118,22 +196,60 @@ struct saa7191_status { | |||
118 | int norm; | 196 | int norm; |
119 | }; | 197 | }; |
120 | 198 | ||
121 | #define SAA7191_HUE_MIN 0x00 | 199 | #define SAA7191_BANDPASS_MIN 0x00 |
122 | #define SAA7191_HUE_MAX 0xff | 200 | #define SAA7191_BANDPASS_MAX 0x03 |
123 | #define SAA7191_HUE_DEFAULT 0x80 | 201 | #define SAA7191_BANDPASS_DEFAULT 0x00 |
202 | |||
203 | #define SAA7191_BANDPASS_WEIGHT_MIN 0x00 | ||
204 | #define SAA7191_BANDPASS_WEIGHT_MAX 0x03 | ||
205 | #define SAA7191_BANDPASS_WEIGHT_DEFAULT 0x01 | ||
206 | |||
207 | #define SAA7191_CORING_MIN 0x00 | ||
208 | #define SAA7191_CORING_MAX 0x03 | ||
209 | #define SAA7191_CORING_DEFAULT 0x00 | ||
210 | |||
211 | #define SAA7191_HUE_MIN 0x00 | ||
212 | #define SAA7191_HUE_MAX 0xff | ||
213 | #define SAA7191_HUE_DEFAULT 0x80 | ||
214 | |||
215 | #define SAA7191_VTRC_MIN 0x00 | ||
216 | #define SAA7191_VTRC_MAX 0x01 | ||
217 | #define SAA7191_VTRC_DEFAULT 0x00 | ||
218 | |||
219 | #define SAA7191_FORCE_COLOUR_MIN 0x00 | ||
220 | #define SAA7191_FORCE_COLOUR_MAX 0x01 | ||
221 | #define SAA7191_FORCE_COLOUR_DEFAULT 0x00 | ||
222 | |||
223 | #define SAA7191_CHROMA_GAIN_MIN 0x00 | ||
224 | #define SAA7191_CHROMA_GAIN_MAX 0x03 | ||
225 | #define SAA7191_CHROMA_GAIN_DEFAULT 0x00 | ||
226 | |||
227 | #define SAA7191_LUMA_DELAY_MIN -0x04 | ||
228 | #define SAA7191_LUMA_DELAY_MAX 0x03 | ||
229 | #define SAA7191_LUMA_DELAY_DEFAULT 0x01 | ||
230 | |||
231 | #define SAA7191_VNR_MIN 0x00 | ||
232 | #define SAA7191_VNR_MAX 0x03 | ||
233 | #define SAA7191_VNR_DEFAULT 0x00 | ||
124 | 234 | ||
125 | #define SAA7191_VTRC_MIN 0x00 | 235 | #define SAA7191_CONTROL_BANDPASS 0 |
126 | #define SAA7191_VTRC_MAX 0x01 | 236 | #define SAA7191_CONTROL_BANDPASS_WEIGHT 1 |
127 | #define SAA7191_VTRC_DEFAULT 0x00 | 237 | #define SAA7191_CONTROL_CORING 2 |
238 | #define SAA7191_CONTROL_FORCE_COLOUR 3 /* boolean */ | ||
239 | #define SAA7191_CONTROL_CHROMA_GAIN 4 | ||
240 | #define SAA7191_CONTROL_HUE 5 | ||
241 | #define SAA7191_CONTROL_VTRC 6 /* boolean */ | ||
242 | #define SAA7191_CONTROL_LUMA_DELAY 7 | ||
243 | #define SAA7191_CONTROL_VNR 8 | ||
128 | 244 | ||
129 | struct saa7191_control { | 245 | struct saa7191_control { |
130 | int hue; | 246 | u8 type; |
131 | int vtrc; | 247 | s32 value; |
132 | }; | 248 | }; |
133 | 249 | ||
134 | #define DECODER_SAA7191_GET_STATUS _IOR('d', 195, struct saa7191_status) | 250 | #define DECODER_SAA7191_GET_STATUS _IOR('d', 195, struct saa7191_status) |
135 | #define DECODER_SAA7191_SET_NORM _IOW('d', 196, int) | 251 | #define DECODER_SAA7191_SET_NORM _IOW('d', 196, int) |
136 | #define DECODER_SAA7191_GET_CONTROLS _IOR('d', 197, struct saa7191_control) | 252 | #define DECODER_SAA7191_GET_CONTROL _IOR('d', 197, struct saa7191_control) |
137 | #define DECODER_SAA7191_SET_CONTROLS _IOW('d', 198, struct saa7191_control) | 253 | #define DECODER_SAA7191_SET_CONTROL _IOW('d', 198, struct saa7191_control) |
138 | 254 | ||
139 | #endif | 255 | #endif |
diff --git a/drivers/media/video/vino.c b/drivers/media/video/vino.c index ed4394e854ab..71b28e9e0850 100644 --- a/drivers/media/video/vino.c +++ b/drivers/media/video/vino.c | |||
@@ -12,15 +12,11 @@ | |||
12 | 12 | ||
13 | /* | 13 | /* |
14 | * TODO: | 14 | * TODO: |
15 | * - remove "hacks" from memory allocation code and implement nopage() | 15 | * - remove "mark pages reserved-hacks" from memory allocation code |
16 | * and implement nopage() | ||
16 | * - check decimation, calculating and reporting image size when | 17 | * - check decimation, calculating and reporting image size when |
17 | * using decimation | 18 | * using decimation |
18 | * - check vino_acquire_input(), vino_set_input() and channel | 19 | * - implement read(), user mode buffers and overlay (?) |
19 | * ownership handling | ||
20 | * - report VINO error-interrupts via ioctls ? | ||
21 | * - implement picture controls (all implemented?) | ||
22 | * - use macros for boolean values (?) | ||
23 | * - implement user mode buffers and overlay (?) | ||
24 | */ | 20 | */ |
25 | 21 | ||
26 | #include <linux/init.h> | 22 | #include <linux/init.h> |
@@ -60,18 +56,16 @@ | |||
60 | * debug info. | 56 | * debug info. |
61 | * Note that the debug output also slows down the driver significantly */ | 57 | * Note that the debug output also slows down the driver significantly */ |
62 | // #define VINO_DEBUG | 58 | // #define VINO_DEBUG |
59 | // #define VINO_DEBUG_INT | ||
63 | 60 | ||
64 | #define VINO_MODULE_VERSION "0.0.3" | 61 | #define VINO_MODULE_VERSION "0.0.5" |
65 | #define VINO_VERSION_CODE KERNEL_VERSION(0, 0, 3) | 62 | #define VINO_VERSION_CODE KERNEL_VERSION(0, 0, 5) |
66 | 63 | ||
67 | MODULE_DESCRIPTION("SGI VINO Video4Linux2 driver"); | 64 | MODULE_DESCRIPTION("SGI VINO Video4Linux2 driver"); |
68 | MODULE_VERSION(VINO_MODULE_VERSION); | 65 | MODULE_VERSION(VINO_MODULE_VERSION); |
69 | MODULE_AUTHOR("Mikael Nousiainen <tmnousia@cc.hut.fi>"); | 66 | MODULE_AUTHOR("Mikael Nousiainen <tmnousia@cc.hut.fi>"); |
70 | MODULE_LICENSE("GPL"); | 67 | MODULE_LICENSE("GPL"); |
71 | 68 | ||
72 | #define mem_map_reserve(p) set_bit(PG_reserved, &((p)->flags)) | ||
73 | #define mem_map_unreserve(p) clear_bit(PG_reserved, &((p)->flags)) | ||
74 | |||
75 | #ifdef VINO_DEBUG | 69 | #ifdef VINO_DEBUG |
76 | #define dprintk(x...) printk("VINO: " x); | 70 | #define dprintk(x...) printk("VINO: " x); |
77 | #else | 71 | #else |
@@ -91,15 +85,16 @@ MODULE_LICENSE("GPL"); | |||
91 | #define VINO_MIN_HEIGHT 32 | 85 | #define VINO_MIN_HEIGHT 32 |
92 | 86 | ||
93 | #define VINO_CLIPPING_START_ODD_D1 1 | 87 | #define VINO_CLIPPING_START_ODD_D1 1 |
94 | #define VINO_CLIPPING_START_ODD_PAL 1 | 88 | #define VINO_CLIPPING_START_ODD_PAL 15 |
95 | #define VINO_CLIPPING_START_ODD_NTSC 1 | 89 | #define VINO_CLIPPING_START_ODD_NTSC 12 |
96 | 90 | ||
97 | #define VINO_CLIPPING_START_EVEN_D1 2 | 91 | #define VINO_CLIPPING_START_EVEN_D1 2 |
98 | #define VINO_CLIPPING_START_EVEN_PAL 2 | 92 | #define VINO_CLIPPING_START_EVEN_PAL 15 |
99 | #define VINO_CLIPPING_START_EVEN_NTSC 2 | 93 | #define VINO_CLIPPING_START_EVEN_NTSC 12 |
100 | 94 | ||
101 | #define VINO_INPUT_CHANNEL_COUNT 3 | 95 | #define VINO_INPUT_CHANNEL_COUNT 3 |
102 | 96 | ||
97 | /* the number is the index for vino_inputs */ | ||
103 | #define VINO_INPUT_NONE -1 | 98 | #define VINO_INPUT_NONE -1 |
104 | #define VINO_INPUT_COMPOSITE 0 | 99 | #define VINO_INPUT_COMPOSITE 0 |
105 | #define VINO_INPUT_SVIDEO 1 | 100 | #define VINO_INPUT_SVIDEO 1 |
@@ -107,15 +102,13 @@ MODULE_LICENSE("GPL"); | |||
107 | 102 | ||
108 | #define VINO_PAGE_RATIO (PAGE_SIZE / VINO_PAGE_SIZE) | 103 | #define VINO_PAGE_RATIO (PAGE_SIZE / VINO_PAGE_SIZE) |
109 | 104 | ||
110 | #define VINO_FIFO_THRESHOLD_DEFAULT 512 | 105 | #define VINO_FIFO_THRESHOLD_DEFAULT 16 |
111 | 106 | ||
112 | /*#define VINO_FRAMEBUFFER_SIZE (VINO_PAL_WIDTH * VINO_PAL_HEIGHT * 4 \ | ||
113 | + 2 * PAGE_SIZE)*/ | ||
114 | #define VINO_FRAMEBUFFER_SIZE ((VINO_PAL_WIDTH \ | 107 | #define VINO_FRAMEBUFFER_SIZE ((VINO_PAL_WIDTH \ |
115 | * VINO_PAL_HEIGHT * 4 \ | 108 | * VINO_PAL_HEIGHT * 4 \ |
116 | + 3 * PAGE_SIZE) & ~(PAGE_SIZE - 1)) | 109 | + 3 * PAGE_SIZE) & ~(PAGE_SIZE - 1)) |
117 | 110 | ||
118 | #define VINO_FRAMEBUFFER_MAX_COUNT 8 | 111 | #define VINO_FRAMEBUFFER_COUNT_MAX 8 |
119 | 112 | ||
120 | #define VINO_FRAMEBUFFER_UNUSED 0 | 113 | #define VINO_FRAMEBUFFER_UNUSED 0 |
121 | #define VINO_FRAMEBUFFER_IN_USE 1 | 114 | #define VINO_FRAMEBUFFER_IN_USE 1 |
@@ -131,24 +124,27 @@ MODULE_LICENSE("GPL"); | |||
131 | #define VINO_DUMMY_DESC_COUNT 4 | 124 | #define VINO_DUMMY_DESC_COUNT 4 |
132 | #define VINO_DESC_FETCH_DELAY 5 /* microseconds */ | 125 | #define VINO_DESC_FETCH_DELAY 5 /* microseconds */ |
133 | 126 | ||
127 | #define VINO_MAX_FRAME_SKIP_COUNT 128 | ||
128 | |||
134 | /* the number is the index for vino_data_formats */ | 129 | /* the number is the index for vino_data_formats */ |
135 | #define VINO_DATA_FMT_NONE -1 | 130 | #define VINO_DATA_FMT_NONE -1 |
136 | #define VINO_DATA_FMT_GREY 0 | 131 | #define VINO_DATA_FMT_GREY 0 |
137 | #define VINO_DATA_FMT_RGB332 1 | 132 | #define VINO_DATA_FMT_RGB332 1 |
138 | #define VINO_DATA_FMT_RGB32 2 | 133 | #define VINO_DATA_FMT_RGB32 2 |
139 | #define VINO_DATA_FMT_YUV 3 | 134 | #define VINO_DATA_FMT_YUV 3 |
140 | //#define VINO_DATA_FMT_RGB24 4 | ||
141 | 135 | ||
142 | #define VINO_DATA_FMT_COUNT 4 | 136 | #define VINO_DATA_FMT_COUNT 4 |
143 | 137 | ||
138 | /* the number is the index for vino_data_norms */ | ||
144 | #define VINO_DATA_NORM_NONE -1 | 139 | #define VINO_DATA_NORM_NONE -1 |
145 | #define VINO_DATA_NORM_NTSC 0 | 140 | #define VINO_DATA_NORM_NTSC 0 |
146 | #define VINO_DATA_NORM_PAL 1 | 141 | #define VINO_DATA_NORM_PAL 1 |
147 | #define VINO_DATA_NORM_SECAM 2 | 142 | #define VINO_DATA_NORM_SECAM 2 |
148 | #define VINO_DATA_NORM_D1 3 | 143 | #define VINO_DATA_NORM_D1 3 |
149 | /* The following is a special entry that can be used to | 144 | /* The following are special entries that can be used to |
150 | * autodetect the norm. */ | 145 | * autodetect the norm. */ |
151 | #define VINO_DATA_NORM_AUTO 0xff | 146 | #define VINO_DATA_NORM_AUTO 0xfe |
147 | #define VINO_DATA_NORM_AUTO_EXT 0xff | ||
152 | 148 | ||
153 | #define VINO_DATA_NORM_COUNT 4 | 149 | #define VINO_DATA_NORM_COUNT 4 |
154 | 150 | ||
@@ -232,7 +228,7 @@ struct vino_framebuffer_fifo { | |||
232 | unsigned int head; | 228 | unsigned int head; |
233 | unsigned int tail; | 229 | unsigned int tail; |
234 | 230 | ||
235 | unsigned int data[VINO_FRAMEBUFFER_MAX_COUNT]; | 231 | unsigned int data[VINO_FRAMEBUFFER_COUNT_MAX]; |
236 | }; | 232 | }; |
237 | 233 | ||
238 | struct vino_framebuffer_queue { | 234 | struct vino_framebuffer_queue { |
@@ -246,13 +242,20 @@ struct vino_framebuffer_queue { | |||
246 | struct vino_framebuffer_fifo in; | 242 | struct vino_framebuffer_fifo in; |
247 | struct vino_framebuffer_fifo out; | 243 | struct vino_framebuffer_fifo out; |
248 | 244 | ||
249 | struct vino_framebuffer *buffer[VINO_FRAMEBUFFER_MAX_COUNT]; | 245 | struct vino_framebuffer *buffer[VINO_FRAMEBUFFER_COUNT_MAX]; |
250 | 246 | ||
251 | spinlock_t queue_lock; | 247 | spinlock_t queue_lock; |
252 | struct semaphore queue_sem; | 248 | struct semaphore queue_sem; |
253 | wait_queue_head_t frame_wait_queue; | 249 | wait_queue_head_t frame_wait_queue; |
254 | }; | 250 | }; |
255 | 251 | ||
252 | struct vino_interrupt_data { | ||
253 | struct timeval timestamp; | ||
254 | unsigned int frame_counter; | ||
255 | unsigned int skip_count; | ||
256 | unsigned int skip; | ||
257 | }; | ||
258 | |||
256 | struct vino_channel_settings { | 259 | struct vino_channel_settings { |
257 | unsigned int channel; | 260 | unsigned int channel; |
258 | 261 | ||
@@ -285,6 +288,8 @@ struct vino_channel_settings { | |||
285 | 288 | ||
286 | unsigned int users; | 289 | unsigned int users; |
287 | 290 | ||
291 | struct vino_interrupt_data int_data; | ||
292 | |||
288 | /* V4L support */ | 293 | /* V4L support */ |
289 | struct video_device *v4l_device; | 294 | struct video_device *v4l_device; |
290 | }; | 295 | }; |
@@ -315,7 +320,7 @@ struct vino_settings { | |||
315 | /* Module parameters */ | 320 | /* Module parameters */ |
316 | 321 | ||
317 | /* | 322 | /* |
318 | * Using vino_pixel_conversion the ARGB32-format pixels supplied | 323 | * Using vino_pixel_conversion the ABGR32-format pixels supplied |
319 | * by the VINO chip can be converted to more common formats | 324 | * by the VINO chip can be converted to more common formats |
320 | * like RGBA32 (or probably RGB24 in the future). This way we | 325 | * like RGBA32 (or probably RGB24 in the future). This way we |
321 | * can give out data that can be specified correctly with | 326 | * can give out data that can be specified correctly with |
@@ -329,7 +334,9 @@ struct vino_settings { | |||
329 | * Use non-zero value to enable conversion. | 334 | * Use non-zero value to enable conversion. |
330 | */ | 335 | */ |
331 | static int vino_pixel_conversion = 0; | 336 | static int vino_pixel_conversion = 0; |
337 | |||
332 | module_param_named(pixelconv, vino_pixel_conversion, int, 0); | 338 | module_param_named(pixelconv, vino_pixel_conversion, int, 0); |
339 | |||
333 | MODULE_PARM_DESC(pixelconv, | 340 | MODULE_PARM_DESC(pixelconv, |
334 | "enable pixel conversion (non-zero value enables)"); | 341 | "enable pixel conversion (non-zero value enables)"); |
335 | 342 | ||
@@ -345,15 +352,22 @@ static const char *vino_bus_name = "GIO64 bus"; | |||
345 | static const char *vino_v4l_device_name_a = "SGI VINO Channel A"; | 352 | static const char *vino_v4l_device_name_a = "SGI VINO Channel A"; |
346 | static const char *vino_v4l_device_name_b = "SGI VINO Channel B"; | 353 | static const char *vino_v4l_device_name_b = "SGI VINO Channel B"; |
347 | 354 | ||
355 | static void vino_capture_tasklet(unsigned long channel); | ||
356 | |||
357 | DECLARE_TASKLET(vino_tasklet_a, vino_capture_tasklet, VINO_CHANNEL_A); | ||
358 | DECLARE_TASKLET(vino_tasklet_b, vino_capture_tasklet, VINO_CHANNEL_B); | ||
359 | |||
348 | static const struct vino_input vino_inputs[] = { | 360 | static const struct vino_input vino_inputs[] = { |
349 | { | 361 | { |
350 | .name = "Composite", | 362 | .name = "Composite", |
351 | .std = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM, | 363 | .std = V4L2_STD_NTSC | V4L2_STD_PAL |
364 | | V4L2_STD_SECAM, | ||
352 | },{ | 365 | },{ |
353 | .name = "S-Video", | 366 | .name = "S-Video", |
354 | .std = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM, | 367 | .std = V4L2_STD_NTSC | V4L2_STD_PAL |
368 | | V4L2_STD_SECAM, | ||
355 | },{ | 369 | },{ |
356 | .name = "D1 (IndyCam)", | 370 | .name = "D1/IndyCam", |
357 | .std = V4L2_STD_NTSC, | 371 | .std = V4L2_STD_NTSC, |
358 | } | 372 | } |
359 | }; | 373 | }; |
@@ -376,15 +390,10 @@ static const struct vino_data_format vino_data_formats[] = { | |||
376 | .colorspace = V4L2_COLORSPACE_SRGB, | 390 | .colorspace = V4L2_COLORSPACE_SRGB, |
377 | },{ | 391 | },{ |
378 | .description = "YUV 4:2:2", | 392 | .description = "YUV 4:2:2", |
379 | .bpp = 4, | 393 | .bpp = 2, |
380 | .pixelformat = V4L2_PIX_FMT_YUYV, // XXX: swapped? | 394 | .pixelformat = V4L2_PIX_FMT_YUYV, // XXX: swapped? |
381 | .colorspace = V4L2_COLORSPACE_SMPTE170M, | 395 | .colorspace = V4L2_COLORSPACE_SMPTE170M, |
382 | }/*,{ | 396 | } |
383 | .description = "24-bit RGB", | ||
384 | .bpp = 3, | ||
385 | .pixelformat = V4L2_PIX_FMT_RGB24, | ||
386 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
387 | }*/ | ||
388 | }; | 397 | }; |
389 | 398 | ||
390 | static const struct vino_data_norm vino_data_norms[] = { | 399 | static const struct vino_data_norm vino_data_norms[] = { |
@@ -397,18 +406,18 @@ static const struct vino_data_norm vino_data_norms[] = { | |||
397 | .width = VINO_NTSC_WIDTH, | 406 | .width = VINO_NTSC_WIDTH, |
398 | .height = VINO_NTSC_HEIGHT, | 407 | .height = VINO_NTSC_HEIGHT, |
399 | .odd = { | 408 | .odd = { |
400 | .top = VINO_CLIPPING_START_ODD_NTSC, | 409 | .top = VINO_CLIPPING_START_ODD_NTSC, |
401 | .left = 0, | 410 | .left = 0, |
402 | .bottom = VINO_CLIPPING_START_ODD_NTSC | 411 | .bottom = VINO_CLIPPING_START_ODD_NTSC |
403 | + VINO_NTSC_HEIGHT / 2 - 1, | 412 | + VINO_NTSC_HEIGHT / 2 - 1, |
404 | .right = VINO_NTSC_WIDTH, | 413 | .right = VINO_NTSC_WIDTH, |
405 | }, | 414 | }, |
406 | .even = { | 415 | .even = { |
407 | .top = VINO_CLIPPING_START_EVEN_NTSC, | 416 | .top = VINO_CLIPPING_START_EVEN_NTSC, |
408 | .left = 0, | 417 | .left = 0, |
409 | .bottom = VINO_CLIPPING_START_EVEN_NTSC | 418 | .bottom = VINO_CLIPPING_START_EVEN_NTSC |
410 | + VINO_NTSC_HEIGHT / 2 - 1, | 419 | + VINO_NTSC_HEIGHT / 2 - 1, |
411 | .right = VINO_NTSC_WIDTH, | 420 | .right = VINO_NTSC_WIDTH, |
412 | }, | 421 | }, |
413 | },{ | 422 | },{ |
414 | .description = "PAL", | 423 | .description = "PAL", |
@@ -419,18 +428,18 @@ static const struct vino_data_norm vino_data_norms[] = { | |||
419 | .width = VINO_PAL_WIDTH, | 428 | .width = VINO_PAL_WIDTH, |
420 | .height = VINO_PAL_HEIGHT, | 429 | .height = VINO_PAL_HEIGHT, |
421 | .odd = { | 430 | .odd = { |
422 | .top = VINO_CLIPPING_START_ODD_PAL, | 431 | .top = VINO_CLIPPING_START_ODD_PAL, |
423 | .left = 0, | 432 | .left = 0, |
424 | .bottom = VINO_CLIPPING_START_ODD_PAL | 433 | .bottom = VINO_CLIPPING_START_ODD_PAL |
425 | + VINO_PAL_HEIGHT / 2 - 1, | 434 | + VINO_PAL_HEIGHT / 2 - 1, |
426 | .right = VINO_PAL_WIDTH, | 435 | .right = VINO_PAL_WIDTH, |
427 | }, | 436 | }, |
428 | .even = { | 437 | .even = { |
429 | .top = VINO_CLIPPING_START_EVEN_PAL, | 438 | .top = VINO_CLIPPING_START_EVEN_PAL, |
430 | .left = 0, | 439 | .left = 0, |
431 | .bottom = VINO_CLIPPING_START_EVEN_PAL | 440 | .bottom = VINO_CLIPPING_START_EVEN_PAL |
432 | + VINO_PAL_HEIGHT / 2 - 1, | 441 | + VINO_PAL_HEIGHT / 2 - 1, |
433 | .right = VINO_PAL_WIDTH, | 442 | .right = VINO_PAL_WIDTH, |
434 | }, | 443 | }, |
435 | },{ | 444 | },{ |
436 | .description = "SECAM", | 445 | .description = "SECAM", |
@@ -441,21 +450,21 @@ static const struct vino_data_norm vino_data_norms[] = { | |||
441 | .width = VINO_PAL_WIDTH, | 450 | .width = VINO_PAL_WIDTH, |
442 | .height = VINO_PAL_HEIGHT, | 451 | .height = VINO_PAL_HEIGHT, |
443 | .odd = { | 452 | .odd = { |
444 | .top = VINO_CLIPPING_START_ODD_PAL, | 453 | .top = VINO_CLIPPING_START_ODD_PAL, |
445 | .left = 0, | 454 | .left = 0, |
446 | .bottom = VINO_CLIPPING_START_ODD_PAL | 455 | .bottom = VINO_CLIPPING_START_ODD_PAL |
447 | + VINO_PAL_HEIGHT / 2 - 1, | 456 | + VINO_PAL_HEIGHT / 2 - 1, |
448 | .right = VINO_PAL_WIDTH, | 457 | .right = VINO_PAL_WIDTH, |
449 | }, | 458 | }, |
450 | .even = { | 459 | .even = { |
451 | .top = VINO_CLIPPING_START_EVEN_PAL, | 460 | .top = VINO_CLIPPING_START_EVEN_PAL, |
452 | .left = 0, | 461 | .left = 0, |
453 | .bottom = VINO_CLIPPING_START_EVEN_PAL | 462 | .bottom = VINO_CLIPPING_START_EVEN_PAL |
454 | + VINO_PAL_HEIGHT / 2 - 1, | 463 | + VINO_PAL_HEIGHT / 2 - 1, |
455 | .right = VINO_PAL_WIDTH, | 464 | .right = VINO_PAL_WIDTH, |
456 | }, | 465 | }, |
457 | },{ | 466 | },{ |
458 | .description = "NTSC (D1 input)", | 467 | .description = "NTSC/D1", |
459 | .std = V4L2_STD_NTSC, | 468 | .std = V4L2_STD_NTSC, |
460 | .fps_min = 6, | 469 | .fps_min = 6, |
461 | .fps_max = 30, | 470 | .fps_max = 30, |
@@ -463,18 +472,18 @@ static const struct vino_data_norm vino_data_norms[] = { | |||
463 | .width = VINO_NTSC_WIDTH, | 472 | .width = VINO_NTSC_WIDTH, |
464 | .height = VINO_NTSC_HEIGHT, | 473 | .height = VINO_NTSC_HEIGHT, |
465 | .odd = { | 474 | .odd = { |
466 | .top = VINO_CLIPPING_START_ODD_D1, | 475 | .top = VINO_CLIPPING_START_ODD_D1, |
467 | .left = 0, | 476 | .left = 0, |
468 | .bottom = VINO_CLIPPING_START_ODD_D1 | 477 | .bottom = VINO_CLIPPING_START_ODD_D1 |
469 | + VINO_NTSC_HEIGHT / 2 - 1, | 478 | + VINO_NTSC_HEIGHT / 2 - 1, |
470 | .right = VINO_NTSC_WIDTH, | 479 | .right = VINO_NTSC_WIDTH, |
471 | }, | 480 | }, |
472 | .even = { | 481 | .even = { |
473 | .top = VINO_CLIPPING_START_EVEN_D1, | 482 | .top = VINO_CLIPPING_START_EVEN_D1, |
474 | .left = 0, | 483 | .left = 0, |
475 | .bottom = VINO_CLIPPING_START_EVEN_D1 | 484 | .bottom = VINO_CLIPPING_START_EVEN_D1 |
476 | + VINO_NTSC_HEIGHT / 2 - 1, | 485 | + VINO_NTSC_HEIGHT / 2 - 1, |
477 | .right = VINO_NTSC_WIDTH, | 486 | .right = VINO_NTSC_WIDTH, |
478 | }, | 487 | }, |
479 | } | 488 | } |
480 | }; | 489 | }; |
@@ -491,7 +500,7 @@ struct v4l2_queryctrl vino_indycam_v4l2_controls[] = { | |||
491 | .step = 1, | 500 | .step = 1, |
492 | .default_value = INDYCAM_AGC_DEFAULT, | 501 | .default_value = INDYCAM_AGC_DEFAULT, |
493 | .flags = 0, | 502 | .flags = 0, |
494 | .reserved = { 0, 0 }, | 503 | .reserved = { INDYCAM_CONTROL_AGC, 0 }, |
495 | },{ | 504 | },{ |
496 | .id = V4L2_CID_AUTO_WHITE_BALANCE, | 505 | .id = V4L2_CID_AUTO_WHITE_BALANCE, |
497 | .type = V4L2_CTRL_TYPE_BOOLEAN, | 506 | .type = V4L2_CTRL_TYPE_BOOLEAN, |
@@ -501,7 +510,7 @@ struct v4l2_queryctrl vino_indycam_v4l2_controls[] = { | |||
501 | .step = 1, | 510 | .step = 1, |
502 | .default_value = INDYCAM_AWB_DEFAULT, | 511 | .default_value = INDYCAM_AWB_DEFAULT, |
503 | .flags = 0, | 512 | .flags = 0, |
504 | .reserved = { 0, 0 }, | 513 | .reserved = { INDYCAM_CONTROL_AWB, 0 }, |
505 | },{ | 514 | },{ |
506 | .id = V4L2_CID_GAIN, | 515 | .id = V4L2_CID_GAIN, |
507 | .type = V4L2_CTRL_TYPE_INTEGER, | 516 | .type = V4L2_CTRL_TYPE_INTEGER, |
@@ -511,7 +520,7 @@ struct v4l2_queryctrl vino_indycam_v4l2_controls[] = { | |||
511 | .step = 1, | 520 | .step = 1, |
512 | .default_value = INDYCAM_GAIN_DEFAULT, | 521 | .default_value = INDYCAM_GAIN_DEFAULT, |
513 | .flags = 0, | 522 | .flags = 0, |
514 | .reserved = { 0, 0 }, | 523 | .reserved = { INDYCAM_CONTROL_GAIN, 0 }, |
515 | },{ | 524 | },{ |
516 | .id = V4L2_CID_PRIVATE_BASE, | 525 | .id = V4L2_CID_PRIVATE_BASE, |
517 | .type = V4L2_CTRL_TYPE_INTEGER, | 526 | .type = V4L2_CTRL_TYPE_INTEGER, |
@@ -521,7 +530,7 @@ struct v4l2_queryctrl vino_indycam_v4l2_controls[] = { | |||
521 | .step = 1, | 530 | .step = 1, |
522 | .default_value = INDYCAM_RED_SATURATION_DEFAULT, | 531 | .default_value = INDYCAM_RED_SATURATION_DEFAULT, |
523 | .flags = 0, | 532 | .flags = 0, |
524 | .reserved = { 0, 0 }, | 533 | .reserved = { INDYCAM_CONTROL_RED_SATURATION, 0 }, |
525 | },{ | 534 | },{ |
526 | .id = V4L2_CID_PRIVATE_BASE + 1, | 535 | .id = V4L2_CID_PRIVATE_BASE + 1, |
527 | .type = V4L2_CTRL_TYPE_INTEGER, | 536 | .type = V4L2_CTRL_TYPE_INTEGER, |
@@ -531,7 +540,7 @@ struct v4l2_queryctrl vino_indycam_v4l2_controls[] = { | |||
531 | .step = 1, | 540 | .step = 1, |
532 | .default_value = INDYCAM_BLUE_SATURATION_DEFAULT, | 541 | .default_value = INDYCAM_BLUE_SATURATION_DEFAULT, |
533 | .flags = 0, | 542 | .flags = 0, |
534 | .reserved = { 0, 0 }, | 543 | .reserved = { INDYCAM_CONTROL_BLUE_SATURATION, 0 }, |
535 | },{ | 544 | },{ |
536 | .id = V4L2_CID_RED_BALANCE, | 545 | .id = V4L2_CID_RED_BALANCE, |
537 | .type = V4L2_CTRL_TYPE_INTEGER, | 546 | .type = V4L2_CTRL_TYPE_INTEGER, |
@@ -541,7 +550,7 @@ struct v4l2_queryctrl vino_indycam_v4l2_controls[] = { | |||
541 | .step = 1, | 550 | .step = 1, |
542 | .default_value = INDYCAM_RED_BALANCE_DEFAULT, | 551 | .default_value = INDYCAM_RED_BALANCE_DEFAULT, |
543 | .flags = 0, | 552 | .flags = 0, |
544 | .reserved = { 0, 0 }, | 553 | .reserved = { INDYCAM_CONTROL_RED_BALANCE, 0 }, |
545 | },{ | 554 | },{ |
546 | .id = V4L2_CID_BLUE_BALANCE, | 555 | .id = V4L2_CID_BLUE_BALANCE, |
547 | .type = V4L2_CTRL_TYPE_INTEGER, | 556 | .type = V4L2_CTRL_TYPE_INTEGER, |
@@ -551,7 +560,7 @@ struct v4l2_queryctrl vino_indycam_v4l2_controls[] = { | |||
551 | .step = 1, | 560 | .step = 1, |
552 | .default_value = INDYCAM_BLUE_BALANCE_DEFAULT, | 561 | .default_value = INDYCAM_BLUE_BALANCE_DEFAULT, |
553 | .flags = 0, | 562 | .flags = 0, |
554 | .reserved = { 0, 0 }, | 563 | .reserved = { INDYCAM_CONTROL_BLUE_BALANCE, 0 }, |
555 | },{ | 564 | },{ |
556 | .id = V4L2_CID_EXPOSURE, | 565 | .id = V4L2_CID_EXPOSURE, |
557 | .type = V4L2_CTRL_TYPE_INTEGER, | 566 | .type = V4L2_CTRL_TYPE_INTEGER, |
@@ -561,7 +570,7 @@ struct v4l2_queryctrl vino_indycam_v4l2_controls[] = { | |||
561 | .step = 1, | 570 | .step = 1, |
562 | .default_value = INDYCAM_SHUTTER_DEFAULT, | 571 | .default_value = INDYCAM_SHUTTER_DEFAULT, |
563 | .flags = 0, | 572 | .flags = 0, |
564 | .reserved = { 0, 0 }, | 573 | .reserved = { INDYCAM_CONTROL_SHUTTER, 0 }, |
565 | },{ | 574 | },{ |
566 | .id = V4L2_CID_GAMMA, | 575 | .id = V4L2_CID_GAMMA, |
567 | .type = V4L2_CTRL_TYPE_INTEGER, | 576 | .type = V4L2_CTRL_TYPE_INTEGER, |
@@ -571,11 +580,11 @@ struct v4l2_queryctrl vino_indycam_v4l2_controls[] = { | |||
571 | .step = 1, | 580 | .step = 1, |
572 | .default_value = INDYCAM_GAMMA_DEFAULT, | 581 | .default_value = INDYCAM_GAMMA_DEFAULT, |
573 | .flags = 0, | 582 | .flags = 0, |
574 | .reserved = { 0, 0 }, | 583 | .reserved = { INDYCAM_CONTROL_GAMMA, 0 }, |
575 | } | 584 | } |
576 | }; | 585 | }; |
577 | 586 | ||
578 | #define VINO_SAA7191_V4L2_CONTROL_COUNT 2 | 587 | #define VINO_SAA7191_V4L2_CONTROL_COUNT 9 |
579 | 588 | ||
580 | struct v4l2_queryctrl vino_saa7191_v4l2_controls[] = { | 589 | struct v4l2_queryctrl vino_saa7191_v4l2_controls[] = { |
581 | { | 590 | { |
@@ -587,9 +596,59 @@ struct v4l2_queryctrl vino_saa7191_v4l2_controls[] = { | |||
587 | .step = 1, | 596 | .step = 1, |
588 | .default_value = SAA7191_HUE_DEFAULT, | 597 | .default_value = SAA7191_HUE_DEFAULT, |
589 | .flags = 0, | 598 | .flags = 0, |
590 | .reserved = { 0, 0 }, | 599 | .reserved = { SAA7191_CONTROL_HUE, 0 }, |
591 | },{ | 600 | },{ |
592 | .id = V4L2_CID_PRIVATE_BASE, | 601 | .id = V4L2_CID_PRIVATE_BASE, |
602 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
603 | .name = "Luminance Bandpass", | ||
604 | .minimum = SAA7191_BANDPASS_MIN, | ||
605 | .maximum = SAA7191_BANDPASS_MAX, | ||
606 | .step = 1, | ||
607 | .default_value = SAA7191_BANDPASS_DEFAULT, | ||
608 | .flags = 0, | ||
609 | .reserved = { SAA7191_CONTROL_BANDPASS, 0 }, | ||
610 | },{ | ||
611 | .id = V4L2_CID_PRIVATE_BASE + 1, | ||
612 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
613 | .name = "Luminance Bandpass Weight", | ||
614 | .minimum = SAA7191_BANDPASS_WEIGHT_MIN, | ||
615 | .maximum = SAA7191_BANDPASS_WEIGHT_MAX, | ||
616 | .step = 1, | ||
617 | .default_value = SAA7191_BANDPASS_WEIGHT_DEFAULT, | ||
618 | .flags = 0, | ||
619 | .reserved = { SAA7191_CONTROL_BANDPASS_WEIGHT, 0 }, | ||
620 | },{ | ||
621 | .id = V4L2_CID_PRIVATE_BASE + 2, | ||
622 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
623 | .name = "HF Luminance Coring", | ||
624 | .minimum = SAA7191_CORING_MIN, | ||
625 | .maximum = SAA7191_CORING_MAX, | ||
626 | .step = 1, | ||
627 | .default_value = SAA7191_CORING_DEFAULT, | ||
628 | .flags = 0, | ||
629 | .reserved = { SAA7191_CONTROL_CORING, 0 }, | ||
630 | },{ | ||
631 | .id = V4L2_CID_PRIVATE_BASE + 3, | ||
632 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
633 | .name = "Force Colour", | ||
634 | .minimum = SAA7191_FORCE_COLOUR_MIN, | ||
635 | .maximum = SAA7191_FORCE_COLOUR_MAX, | ||
636 | .step = 1, | ||
637 | .default_value = SAA7191_FORCE_COLOUR_DEFAULT, | ||
638 | .flags = 0, | ||
639 | .reserved = { SAA7191_CONTROL_FORCE_COLOUR, 0 }, | ||
640 | },{ | ||
641 | .id = V4L2_CID_PRIVATE_BASE + 4, | ||
642 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
643 | .name = "Chrominance Gain Control", | ||
644 | .minimum = SAA7191_CHROMA_GAIN_MIN, | ||
645 | .maximum = SAA7191_CHROMA_GAIN_MAX, | ||
646 | .step = 1, | ||
647 | .default_value = SAA7191_CHROMA_GAIN_DEFAULT, | ||
648 | .flags = 0, | ||
649 | .reserved = { SAA7191_CONTROL_CHROMA_GAIN, 0 }, | ||
650 | },{ | ||
651 | .id = V4L2_CID_PRIVATE_BASE + 5, | ||
593 | .type = V4L2_CTRL_TYPE_BOOLEAN, | 652 | .type = V4L2_CTRL_TYPE_BOOLEAN, |
594 | .name = "VTR Time Constant", | 653 | .name = "VTR Time Constant", |
595 | .minimum = SAA7191_VTRC_MIN, | 654 | .minimum = SAA7191_VTRC_MIN, |
@@ -597,7 +656,27 @@ struct v4l2_queryctrl vino_saa7191_v4l2_controls[] = { | |||
597 | .step = 1, | 656 | .step = 1, |
598 | .default_value = SAA7191_VTRC_DEFAULT, | 657 | .default_value = SAA7191_VTRC_DEFAULT, |
599 | .flags = 0, | 658 | .flags = 0, |
600 | .reserved = { 0, 0 }, | 659 | .reserved = { SAA7191_CONTROL_VTRC, 0 }, |
660 | },{ | ||
661 | .id = V4L2_CID_PRIVATE_BASE + 6, | ||
662 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
663 | .name = "Luminance Delay Compensation", | ||
664 | .minimum = SAA7191_LUMA_DELAY_MIN, | ||
665 | .maximum = SAA7191_LUMA_DELAY_MAX, | ||
666 | .step = 1, | ||
667 | .default_value = SAA7191_LUMA_DELAY_DEFAULT, | ||
668 | .flags = 0, | ||
669 | .reserved = { SAA7191_CONTROL_LUMA_DELAY, 0 }, | ||
670 | },{ | ||
671 | .id = V4L2_CID_PRIVATE_BASE + 7, | ||
672 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
673 | .name = "Vertical Noise Reduction", | ||
674 | .minimum = SAA7191_VNR_MIN, | ||
675 | .maximum = SAA7191_VNR_MAX, | ||
676 | .step = 1, | ||
677 | .default_value = SAA7191_VNR_DEFAULT, | ||
678 | .flags = 0, | ||
679 | .reserved = { SAA7191_CONTROL_VNR, 0 }, | ||
601 | } | 680 | } |
602 | }; | 681 | }; |
603 | 682 | ||
@@ -639,9 +718,10 @@ static struct i2c_algo_sgi_data i2c_sgi_vino_data = | |||
639 | */ | 718 | */ |
640 | static int i2c_vino_client_reg(struct i2c_client *client) | 719 | static int i2c_vino_client_reg(struct i2c_client *client) |
641 | { | 720 | { |
721 | unsigned long flags; | ||
642 | int ret = 0; | 722 | int ret = 0; |
643 | 723 | ||
644 | spin_lock(&vino_drvdata->input_lock); | 724 | spin_lock_irqsave(&vino_drvdata->input_lock, flags); |
645 | switch (client->driver->id) { | 725 | switch (client->driver->id) { |
646 | case I2C_DRIVERID_SAA7191: | 726 | case I2C_DRIVERID_SAA7191: |
647 | if (vino_drvdata->decoder.driver) | 727 | if (vino_drvdata->decoder.driver) |
@@ -658,16 +738,17 @@ static int i2c_vino_client_reg(struct i2c_client *client) | |||
658 | default: | 738 | default: |
659 | ret = -ENODEV; | 739 | ret = -ENODEV; |
660 | } | 740 | } |
661 | spin_unlock(&vino_drvdata->input_lock); | 741 | spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); |
662 | 742 | ||
663 | return ret; | 743 | return ret; |
664 | } | 744 | } |
665 | 745 | ||
666 | static int i2c_vino_client_unreg(struct i2c_client *client) | 746 | static int i2c_vino_client_unreg(struct i2c_client *client) |
667 | { | 747 | { |
748 | unsigned long flags; | ||
668 | int ret = 0; | 749 | int ret = 0; |
669 | 750 | ||
670 | spin_lock(&vino_drvdata->input_lock); | 751 | spin_lock_irqsave(&vino_drvdata->input_lock, flags); |
671 | if (client == vino_drvdata->decoder.driver) { | 752 | if (client == vino_drvdata->decoder.driver) { |
672 | if (vino_drvdata->decoder.owner != VINO_NO_CHANNEL) | 753 | if (vino_drvdata->decoder.owner != VINO_NO_CHANNEL) |
673 | ret = -EBUSY; | 754 | ret = -EBUSY; |
@@ -679,7 +760,7 @@ static int i2c_vino_client_unreg(struct i2c_client *client) | |||
679 | else | 760 | else |
680 | vino_drvdata->camera.driver = NULL; | 761 | vino_drvdata->camera.driver = NULL; |
681 | } | 762 | } |
682 | spin_unlock(&vino_drvdata->input_lock); | 763 | spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); |
683 | 764 | ||
684 | return ret; | 765 | return ret; |
685 | } | 766 | } |
@@ -727,7 +808,7 @@ static void vino_free_buffer_with_count(struct vino_framebuffer *fb, | |||
727 | dprintk("vino_free_buffer_with_count(): count = %d\n", count); | 808 | dprintk("vino_free_buffer_with_count(): count = %d\n", count); |
728 | 809 | ||
729 | for (i = 0; i < count; i++) { | 810 | for (i = 0; i < count; i++) { |
730 | mem_map_unreserve(virt_to_page(fb->desc_table.virtual[i])); | 811 | ClearPageReserved(virt_to_page(fb->desc_table.virtual[i])); |
731 | dma_unmap_single(NULL, | 812 | dma_unmap_single(NULL, |
732 | fb->desc_table.dma_cpu[VINO_PAGE_RATIO * i], | 813 | fb->desc_table.dma_cpu[VINO_PAGE_RATIO * i], |
733 | PAGE_SIZE, DMA_FROM_DEVICE); | 814 | PAGE_SIZE, DMA_FROM_DEVICE); |
@@ -805,7 +886,7 @@ static int vino_allocate_buffer(struct vino_framebuffer *fb, | |||
805 | dma_data_addr + VINO_PAGE_SIZE * j; | 886 | dma_data_addr + VINO_PAGE_SIZE * j; |
806 | } | 887 | } |
807 | 888 | ||
808 | mem_map_reserve(virt_to_page(fb->desc_table.virtual[i])); | 889 | SetPageReserved(virt_to_page(fb->desc_table.virtual[i])); |
809 | } | 890 | } |
810 | 891 | ||
811 | /* page_count needs to be set anyway, because the descriptor table has | 892 | /* page_count needs to be set anyway, because the descriptor table has |
@@ -892,7 +973,7 @@ static int vino_prepare_user_buffer(struct vino_framebuffer *fb, | |||
892 | dma_data_addr + VINO_PAGE_SIZE * j; | 973 | dma_data_addr + VINO_PAGE_SIZE * j; |
893 | } | 974 | } |
894 | 975 | ||
895 | mem_map_reserve(virt_to_page(fb->desc_table.virtual[i])); | 976 | SetPageReserved(virt_to_page(fb->desc_table.virtual[i])); |
896 | } | 977 | } |
897 | 978 | ||
898 | /* page_count needs to be set anyway, because the descriptor table has | 979 | /* page_count needs to be set anyway, because the descriptor table has |
@@ -933,7 +1014,7 @@ static void vino_sync_buffer(struct vino_framebuffer *fb) | |||
933 | 1014 | ||
934 | /* Framebuffer fifo functions (need to be locked externally) */ | 1015 | /* Framebuffer fifo functions (need to be locked externally) */ |
935 | 1016 | ||
936 | static void vino_fifo_init(struct vino_framebuffer_fifo *f, | 1017 | static inline void vino_fifo_init(struct vino_framebuffer_fifo *f, |
937 | unsigned int length) | 1018 | unsigned int length) |
938 | { | 1019 | { |
939 | f->length = 0; | 1020 | f->length = 0; |
@@ -941,16 +1022,18 @@ static void vino_fifo_init(struct vino_framebuffer_fifo *f, | |||
941 | f->head = 0; | 1022 | f->head = 0; |
942 | f->tail = 0; | 1023 | f->tail = 0; |
943 | 1024 | ||
944 | if (length > VINO_FRAMEBUFFER_MAX_COUNT) | 1025 | if (length > VINO_FRAMEBUFFER_COUNT_MAX) |
945 | length = VINO_FRAMEBUFFER_MAX_COUNT; | 1026 | length = VINO_FRAMEBUFFER_COUNT_MAX; |
946 | 1027 | ||
947 | f->length = length; | 1028 | f->length = length; |
948 | } | 1029 | } |
949 | 1030 | ||
950 | /* returns true/false */ | 1031 | /* returns true/false */ |
951 | static int vino_fifo_has_id(struct vino_framebuffer_fifo *f, unsigned int id) | 1032 | static inline int vino_fifo_has_id(struct vino_framebuffer_fifo *f, |
1033 | unsigned int id) | ||
952 | { | 1034 | { |
953 | unsigned int i; | 1035 | unsigned int i; |
1036 | |||
954 | for (i = f->head; i == (f->tail - 1); i = (i + 1) % f->length) { | 1037 | for (i = f->head; i == (f->tail - 1); i = (i + 1) % f->length) { |
955 | if (f->data[i] == id) | 1038 | if (f->data[i] == id) |
956 | return 1; | 1039 | return 1; |
@@ -959,13 +1042,15 @@ static int vino_fifo_has_id(struct vino_framebuffer_fifo *f, unsigned int id) | |||
959 | return 0; | 1042 | return 0; |
960 | } | 1043 | } |
961 | 1044 | ||
1045 | #if 0 | ||
962 | /* returns true/false */ | 1046 | /* returns true/false */ |
963 | static int vino_fifo_full(struct vino_framebuffer_fifo *f) | 1047 | static inline int vino_fifo_full(struct vino_framebuffer_fifo *f) |
964 | { | 1048 | { |
965 | return (f->used == f->length); | 1049 | return (f->used == f->length); |
966 | } | 1050 | } |
1051 | #endif | ||
967 | 1052 | ||
968 | static unsigned int vino_fifo_get_used(struct vino_framebuffer_fifo *f) | 1053 | static inline unsigned int vino_fifo_get_used(struct vino_framebuffer_fifo *f) |
969 | { | 1054 | { |
970 | return f->used; | 1055 | return f->used; |
971 | } | 1056 | } |
@@ -1076,8 +1161,8 @@ static int vino_queue_init(struct vino_framebuffer_queue *q, | |||
1076 | 1161 | ||
1077 | down(&q->queue_sem); | 1162 | down(&q->queue_sem); |
1078 | 1163 | ||
1079 | if (*length > VINO_FRAMEBUFFER_MAX_COUNT) | 1164 | if (*length > VINO_FRAMEBUFFER_COUNT_MAX) |
1080 | *length = VINO_FRAMEBUFFER_MAX_COUNT; | 1165 | *length = VINO_FRAMEBUFFER_COUNT_MAX; |
1081 | 1166 | ||
1082 | q->length = 0; | 1167 | q->length = 0; |
1083 | 1168 | ||
@@ -1313,6 +1398,7 @@ out: | |||
1313 | return ret; | 1398 | return ret; |
1314 | } | 1399 | } |
1315 | 1400 | ||
1401 | #if 0 | ||
1316 | static int vino_queue_get_total(struct vino_framebuffer_queue *q, | 1402 | static int vino_queue_get_total(struct vino_framebuffer_queue *q, |
1317 | unsigned int *total) | 1403 | unsigned int *total) |
1318 | { | 1404 | { |
@@ -1338,6 +1424,7 @@ out: | |||
1338 | 1424 | ||
1339 | return ret; | 1425 | return ret; |
1340 | } | 1426 | } |
1427 | #endif | ||
1341 | 1428 | ||
1342 | static struct vino_framebuffer *vino_queue_peek(struct | 1429 | static struct vino_framebuffer *vino_queue_peek(struct |
1343 | vino_framebuffer_queue *q, | 1430 | vino_framebuffer_queue *q, |
@@ -1471,12 +1558,14 @@ static void vino_update_line_size(struct vino_channel_settings *vcs) | |||
1471 | 1558 | ||
1472 | dprintk("update_line_size(): before: w = %d, d = %d, " | 1559 | dprintk("update_line_size(): before: w = %d, d = %d, " |
1473 | "line_size = %d\n", w, d, vcs->line_size); | 1560 | "line_size = %d\n", w, d, vcs->line_size); |
1561 | |||
1474 | /* line size must be multiple of 8 bytes */ | 1562 | /* line size must be multiple of 8 bytes */ |
1475 | lsize = (bpp * (w / d)) & ~7; | 1563 | lsize = (bpp * (w / d)) & ~7; |
1476 | w = (lsize / bpp) * d; | 1564 | w = (lsize / bpp) * d; |
1477 | 1565 | ||
1478 | vcs->clipping.right = vcs->clipping.left + w; | 1566 | vcs->clipping.right = vcs->clipping.left + w; |
1479 | vcs->line_size = lsize; | 1567 | vcs->line_size = lsize; |
1568 | |||
1480 | dprintk("update_line_size(): after: w = %d, d = %d, " | 1569 | dprintk("update_line_size(): after: w = %d, d = %d, " |
1481 | "line_size = %d\n", w, d, vcs->line_size); | 1570 | "line_size = %d\n", w, d, vcs->line_size); |
1482 | } | 1571 | } |
@@ -1532,7 +1621,7 @@ static void vino_set_clipping(struct vino_channel_settings *vcs, | |||
1532 | } | 1621 | } |
1533 | 1622 | ||
1534 | /* execute with input_lock locked */ | 1623 | /* execute with input_lock locked */ |
1535 | static void vino_set_default_clipping(struct vino_channel_settings *vcs) | 1624 | static inline void vino_set_default_clipping(struct vino_channel_settings *vcs) |
1536 | { | 1625 | { |
1537 | vino_set_clipping(vcs, 0, 0, vino_data_norms[vcs->data_norm].width, | 1626 | vino_set_clipping(vcs, 0, 0, vino_data_norms[vcs->data_norm].width, |
1538 | vino_data_norms[vcs->data_norm].height); | 1627 | vino_data_norms[vcs->data_norm].height); |
@@ -1556,8 +1645,7 @@ static void vino_set_scaling(struct vino_channel_settings *vcs, | |||
1556 | 1645 | ||
1557 | if (d < 1) { | 1646 | if (d < 1) { |
1558 | d = 1; | 1647 | d = 1; |
1559 | } | 1648 | } else if (d > 8) { |
1560 | if (d > 8) { | ||
1561 | d = 8; | 1649 | d = 8; |
1562 | } | 1650 | } |
1563 | 1651 | ||
@@ -1570,7 +1658,7 @@ static void vino_set_scaling(struct vino_channel_settings *vcs, | |||
1570 | } | 1658 | } |
1571 | 1659 | ||
1572 | /* execute with input_lock locked */ | 1660 | /* execute with input_lock locked */ |
1573 | static void vino_reset_scaling(struct vino_channel_settings *vcs) | 1661 | static inline void vino_set_default_scaling(struct vino_channel_settings *vcs) |
1574 | { | 1662 | { |
1575 | vino_set_scaling(vcs, vcs->clipping.right - vcs->clipping.left, | 1663 | vino_set_scaling(vcs, vcs->clipping.right - vcs->clipping.left, |
1576 | vcs->clipping.bottom - vcs->clipping.top); | 1664 | vcs->clipping.bottom - vcs->clipping.top); |
@@ -1649,7 +1737,8 @@ static void vino_set_framerate(struct vino_channel_settings *vcs, | |||
1649 | } | 1737 | } |
1650 | 1738 | ||
1651 | /* execute with input_lock locked */ | 1739 | /* execute with input_lock locked */ |
1652 | static void vino_set_default_framerate(struct vino_channel_settings *vcs) | 1740 | static inline void vino_set_default_framerate(struct |
1741 | vino_channel_settings *vcs) | ||
1653 | { | 1742 | { |
1654 | vino_set_framerate(vcs, vino_data_norms[vcs->data_norm].fps_max); | 1743 | vino_set_framerate(vcs, vino_data_norms[vcs->data_norm].fps_max); |
1655 | } | 1744 | } |
@@ -1687,6 +1776,9 @@ static int vino_dma_setup(struct vino_channel_settings *vcs, | |||
1687 | * should be more than enough time */ | 1776 | * should be more than enough time */ |
1688 | udelay(VINO_DESC_FETCH_DELAY); | 1777 | udelay(VINO_DESC_FETCH_DELAY); |
1689 | 1778 | ||
1779 | dprintk("vino_dma_setup(): start desc = %08x, next 4 desc = %08x\n", | ||
1780 | ch->start_desc_tbl, ch->next_4_desc); | ||
1781 | |||
1690 | /* set the alpha register */ | 1782 | /* set the alpha register */ |
1691 | ch->alpha = vcs->alpha; | 1783 | ch->alpha = vcs->alpha; |
1692 | 1784 | ||
@@ -1700,9 +1792,6 @@ static int vino_dma_setup(struct vino_channel_settings *vcs, | |||
1700 | VINO_CLIP_EVEN(norm->even.top + | 1792 | VINO_CLIP_EVEN(norm->even.top + |
1701 | vcs->clipping.bottom / 2 - 1) | | 1793 | vcs->clipping.bottom / 2 - 1) | |
1702 | VINO_CLIP_X(vcs->clipping.right); | 1794 | VINO_CLIP_X(vcs->clipping.right); |
1703 | /* FIXME: end-of-field bug workaround | ||
1704 | VINO_CLIP_X(VINO_PAL_WIDTH); | ||
1705 | */ | ||
1706 | 1795 | ||
1707 | /* set the size of actual content in the buffer (DECIMATION !) */ | 1796 | /* set the size of actual content in the buffer (DECIMATION !) */ |
1708 | fb->data_size = ((vcs->clipping.right - vcs->clipping.left) / | 1797 | fb->data_size = ((vcs->clipping.right - vcs->clipping.left) / |
@@ -1802,7 +1891,7 @@ static int vino_dma_setup(struct vino_channel_settings *vcs, | |||
1802 | } | 1891 | } |
1803 | 1892 | ||
1804 | /* (execute only with vino_lock locked) */ | 1893 | /* (execute only with vino_lock locked) */ |
1805 | static void vino_dma_start(struct vino_channel_settings *vcs) | 1894 | static inline void vino_dma_start(struct vino_channel_settings *vcs) |
1806 | { | 1895 | { |
1807 | u32 ctrl = vino->control; | 1896 | u32 ctrl = vino->control; |
1808 | 1897 | ||
@@ -1813,12 +1902,14 @@ static void vino_dma_start(struct vino_channel_settings *vcs) | |||
1813 | } | 1902 | } |
1814 | 1903 | ||
1815 | /* (execute only with vino_lock locked) */ | 1904 | /* (execute only with vino_lock locked) */ |
1816 | static void vino_dma_stop(struct vino_channel_settings *vcs) | 1905 | static inline void vino_dma_stop(struct vino_channel_settings *vcs) |
1817 | { | 1906 | { |
1818 | u32 ctrl = vino->control; | 1907 | u32 ctrl = vino->control; |
1819 | 1908 | ||
1820 | ctrl &= (vcs->channel == VINO_CHANNEL_A) ? | 1909 | ctrl &= (vcs->channel == VINO_CHANNEL_A) ? |
1821 | ~VINO_CTRL_A_DMA_ENBL : ~VINO_CTRL_B_DMA_ENBL; | 1910 | ~VINO_CTRL_A_DMA_ENBL : ~VINO_CTRL_B_DMA_ENBL; |
1911 | ctrl &= (vcs->channel == VINO_CHANNEL_A) ? | ||
1912 | ~VINO_CTRL_A_INT : ~VINO_CTRL_B_INT; | ||
1822 | vino->control = ctrl; | 1913 | vino->control = ctrl; |
1823 | dprintk("vino_dma_stop():\n"); | 1914 | dprintk("vino_dma_stop():\n"); |
1824 | } | 1915 | } |
@@ -1902,7 +1993,7 @@ static int vino_capture_next(struct vino_channel_settings *vcs, int start) | |||
1902 | struct vino_framebuffer *fb; | 1993 | struct vino_framebuffer *fb; |
1903 | unsigned int incoming, id; | 1994 | unsigned int incoming, id; |
1904 | int err = 0; | 1995 | int err = 0; |
1905 | unsigned long flags, flags2; | 1996 | unsigned long flags; |
1906 | 1997 | ||
1907 | dprintk("vino_capture_next():\n"); | 1998 | dprintk("vino_capture_next():\n"); |
1908 | 1999 | ||
@@ -1943,10 +2034,6 @@ static int vino_capture_next(struct vino_channel_settings *vcs, int start) | |||
1943 | goto out; | 2034 | goto out; |
1944 | } | 2035 | } |
1945 | 2036 | ||
1946 | spin_lock_irqsave(&fb->state_lock, flags2); | ||
1947 | fb->state = VINO_FRAMEBUFFER_UNUSED; | ||
1948 | spin_unlock_irqrestore(&fb->state_lock, flags2); | ||
1949 | |||
1950 | if (start) { | 2037 | if (start) { |
1951 | vcs->capturing = 1; | 2038 | vcs->capturing = 1; |
1952 | } | 2039 | } |
@@ -1964,7 +2051,7 @@ out: | |||
1964 | return err; | 2051 | return err; |
1965 | } | 2052 | } |
1966 | 2053 | ||
1967 | static int vino_is_capturing(struct vino_channel_settings *vcs) | 2054 | static inline int vino_is_capturing(struct vino_channel_settings *vcs) |
1968 | { | 2055 | { |
1969 | int ret; | 2056 | int ret; |
1970 | unsigned long flags; | 2057 | unsigned long flags; |
@@ -2076,6 +2163,7 @@ static void vino_capture_stop(struct vino_channel_settings *vcs) | |||
2076 | dprintk("vino_capture_stop():\n"); | 2163 | dprintk("vino_capture_stop():\n"); |
2077 | 2164 | ||
2078 | spin_lock_irqsave(&vcs->capture_lock, flags); | 2165 | spin_lock_irqsave(&vcs->capture_lock, flags); |
2166 | |||
2079 | /* unset capturing to stop queue processing */ | 2167 | /* unset capturing to stop queue processing */ |
2080 | vcs->capturing = 0; | 2168 | vcs->capturing = 0; |
2081 | 2169 | ||
@@ -2121,6 +2209,7 @@ out: | |||
2121 | spin_unlock_irqrestore(&vcs->capture_lock, flags); | 2209 | spin_unlock_irqrestore(&vcs->capture_lock, flags); |
2122 | } | 2210 | } |
2123 | 2211 | ||
2212 | #if 0 | ||
2124 | static int vino_capture_failed(struct vino_channel_settings *vcs) | 2213 | static int vino_capture_failed(struct vino_channel_settings *vcs) |
2125 | { | 2214 | { |
2126 | struct vino_framebuffer *fb; | 2215 | struct vino_framebuffer *fb; |
@@ -2165,9 +2254,31 @@ static int vino_capture_failed(struct vino_channel_settings *vcs) | |||
2165 | 2254 | ||
2166 | return 0; | 2255 | return 0; |
2167 | } | 2256 | } |
2257 | #endif | ||
2258 | |||
2259 | static void vino_skip_frame(struct vino_channel_settings *vcs) | ||
2260 | { | ||
2261 | struct vino_framebuffer *fb; | ||
2262 | unsigned long flags; | ||
2263 | unsigned int id; | ||
2264 | |||
2265 | spin_lock_irqsave(&vcs->capture_lock, flags); | ||
2266 | fb = vino_queue_peek(&vcs->fb_queue, &id); | ||
2267 | if (!fb) { | ||
2268 | spin_unlock_irqrestore(&vcs->capture_lock, flags); | ||
2269 | dprintk("vino_skip_frame(): vino_queue_peek() failed!\n"); | ||
2270 | return; | ||
2271 | } | ||
2272 | spin_unlock_irqrestore(&vcs->capture_lock, flags); | ||
2273 | |||
2274 | spin_lock_irqsave(&fb->state_lock, flags); | ||
2275 | fb->state = VINO_FRAMEBUFFER_UNUSED; | ||
2276 | spin_unlock_irqrestore(&fb->state_lock, flags); | ||
2277 | |||
2278 | vino_capture_next(vcs, 0); | ||
2279 | } | ||
2168 | 2280 | ||
2169 | static void vino_frame_done(struct vino_channel_settings *vcs, | 2281 | static void vino_frame_done(struct vino_channel_settings *vcs) |
2170 | unsigned int fc) | ||
2171 | { | 2282 | { |
2172 | struct vino_framebuffer *fb; | 2283 | struct vino_framebuffer *fb; |
2173 | unsigned long flags; | 2284 | unsigned long flags; |
@@ -2181,8 +2292,9 @@ static void vino_frame_done(struct vino_channel_settings *vcs, | |||
2181 | } | 2292 | } |
2182 | spin_unlock_irqrestore(&vcs->capture_lock, flags); | 2293 | spin_unlock_irqrestore(&vcs->capture_lock, flags); |
2183 | 2294 | ||
2184 | fb->frame_counter = fc; | 2295 | fb->frame_counter = vcs->int_data.frame_counter; |
2185 | do_gettimeofday(&fb->timestamp); | 2296 | memcpy(&fb->timestamp, &vcs->int_data.timestamp, |
2297 | sizeof(struct timeval)); | ||
2186 | 2298 | ||
2187 | spin_lock_irqsave(&fb->state_lock, flags); | 2299 | spin_lock_irqsave(&fb->state_lock, flags); |
2188 | if (fb->state == VINO_FRAMEBUFFER_IN_USE) | 2300 | if (fb->state == VINO_FRAMEBUFFER_IN_USE) |
@@ -2194,72 +2306,175 @@ static void vino_frame_done(struct vino_channel_settings *vcs, | |||
2194 | vino_capture_next(vcs, 0); | 2306 | vino_capture_next(vcs, 0); |
2195 | } | 2307 | } |
2196 | 2308 | ||
2309 | static void vino_capture_tasklet(unsigned long channel) { | ||
2310 | struct vino_channel_settings *vcs; | ||
2311 | |||
2312 | vcs = (channel == VINO_CHANNEL_A) | ||
2313 | ? &vino_drvdata->a : &vino_drvdata->b; | ||
2314 | |||
2315 | if (vcs->int_data.skip) | ||
2316 | vcs->int_data.skip_count++; | ||
2317 | |||
2318 | if (vcs->int_data.skip && (vcs->int_data.skip_count | ||
2319 | <= VINO_MAX_FRAME_SKIP_COUNT)) { | ||
2320 | vino_skip_frame(vcs); | ||
2321 | } else { | ||
2322 | vcs->int_data.skip_count = 0; | ||
2323 | vino_frame_done(vcs); | ||
2324 | } | ||
2325 | } | ||
2326 | |||
2197 | static irqreturn_t vino_interrupt(int irq, void *dev_id, struct pt_regs *regs) | 2327 | static irqreturn_t vino_interrupt(int irq, void *dev_id, struct pt_regs *regs) |
2198 | { | 2328 | { |
2199 | u32 intr; | 2329 | u32 ctrl, intr; |
2200 | unsigned int fc_a, fc_b; | 2330 | unsigned int fc_a, fc_b; |
2201 | int done_a = 0; | 2331 | int handled_a = 0, skip_a = 0, done_a = 0; |
2202 | int done_b = 0; | 2332 | int handled_b = 0, skip_b = 0, done_b = 0; |
2333 | |||
2334 | #ifdef VINO_DEBUG_INT | ||
2335 | int loop = 0; | ||
2336 | unsigned int line_count = vino->a.line_count, | ||
2337 | page_index = vino->a.page_index, | ||
2338 | field_counter = vino->a.field_counter, | ||
2339 | start_desc_tbl = vino->a.start_desc_tbl, | ||
2340 | next_4_desc = vino->a.next_4_desc; | ||
2341 | unsigned int line_count_2, | ||
2342 | page_index_2, | ||
2343 | field_counter_2, | ||
2344 | start_desc_tbl_2, | ||
2345 | next_4_desc_2; | ||
2346 | #endif | ||
2203 | 2347 | ||
2204 | spin_lock(&vino_drvdata->vino_lock); | 2348 | spin_lock(&vino_drvdata->vino_lock); |
2205 | 2349 | ||
2206 | intr = vino->intr_status; | 2350 | while ((intr = vino->intr_status)) { |
2207 | fc_a = vino->a.field_counter / 2; | 2351 | fc_a = vino->a.field_counter >> 1; |
2208 | fc_b = vino->b.field_counter / 2; | 2352 | fc_b = vino->b.field_counter >> 1; |
2209 | 2353 | ||
2210 | // TODO: handle error-interrupts in some special way ? | 2354 | /* handle error-interrupts in some special way ? |
2211 | 2355 | * --> skips frames */ | |
2212 | if (intr & VINO_INTSTAT_A) { | 2356 | if (intr & VINO_INTSTAT_A) { |
2213 | if (intr & VINO_INTSTAT_A_EOF) { | 2357 | if (intr & VINO_INTSTAT_A_EOF) { |
2214 | vino_drvdata->a.field++; | 2358 | vino_drvdata->a.field++; |
2215 | if (vino_drvdata->a.field > 1) { | 2359 | if (vino_drvdata->a.field > 1) { |
2360 | vino_dma_stop(&vino_drvdata->a); | ||
2361 | vino_clear_interrupt(&vino_drvdata->a); | ||
2362 | vino_drvdata->a.field = 0; | ||
2363 | done_a = 1; | ||
2364 | } else { | ||
2365 | if (vino->a.page_index | ||
2366 | != vino_drvdata->a.line_size) { | ||
2367 | vino->a.line_count = 0; | ||
2368 | vino->a.page_index = | ||
2369 | vino_drvdata-> | ||
2370 | a.line_size; | ||
2371 | vino->a.next_4_desc = | ||
2372 | vino->a.start_desc_tbl; | ||
2373 | } | ||
2374 | } | ||
2375 | dprintk("channel A end-of-field " | ||
2376 | "interrupt: %04x\n", intr); | ||
2377 | } else { | ||
2216 | vino_dma_stop(&vino_drvdata->a); | 2378 | vino_dma_stop(&vino_drvdata->a); |
2217 | vino_clear_interrupt(&vino_drvdata->a); | 2379 | vino_clear_interrupt(&vino_drvdata->a); |
2218 | vino_drvdata->a.field = 0; | 2380 | vino_drvdata->a.field = 0; |
2219 | done_a = 1; | 2381 | skip_a = 1; |
2382 | dprintk("channel A error interrupt: %04x\n", | ||
2383 | intr); | ||
2220 | } | 2384 | } |
2221 | dprintk("intr: channel A end-of-field interrupt: " | 2385 | |
2222 | "%04x\n", intr); | 2386 | #ifdef VINO_DEBUG_INT |
2223 | } else { | 2387 | line_count_2 = vino->a.line_count; |
2224 | vino_dma_stop(&vino_drvdata->a); | 2388 | page_index_2 = vino->a.page_index; |
2225 | vino_clear_interrupt(&vino_drvdata->a); | 2389 | field_counter_2 = vino->a.field_counter; |
2226 | done_a = 1; | 2390 | start_desc_tbl_2 = vino->a.start_desc_tbl; |
2227 | dprintk("channel A error interrupt: %04x\n", intr); | 2391 | next_4_desc_2 = vino->a.next_4_desc; |
2392 | |||
2393 | printk("intr = %04x, loop = %d, field = %d\n", | ||
2394 | intr, loop, vino_drvdata->a.field); | ||
2395 | printk("1- line count = %04d, page index = %04d, " | ||
2396 | "start = %08x, next = %08x\n" | ||
2397 | " fieldc = %d, framec = %d\n", | ||
2398 | line_count, page_index, start_desc_tbl, | ||
2399 | next_4_desc, field_counter, fc_a); | ||
2400 | printk("12-line count = %04d, page index = %04d, " | ||
2401 | " start = %08x, next = %08x\n", | ||
2402 | line_count_2, page_index_2, start_desc_tbl_2, | ||
2403 | next_4_desc_2); | ||
2404 | |||
2405 | if (done_a) | ||
2406 | printk("\n"); | ||
2407 | #endif | ||
2228 | } | 2408 | } |
2229 | } | 2409 | |
2230 | if (intr & VINO_INTSTAT_B) { | 2410 | if (intr & VINO_INTSTAT_B) { |
2231 | if (intr & VINO_INTSTAT_B_EOF) { | 2411 | if (intr & VINO_INTSTAT_B_EOF) { |
2232 | vino_drvdata->b.field++; | 2412 | vino_drvdata->b.field++; |
2233 | if (vino_drvdata->b.field > 1) { | 2413 | if (vino_drvdata->b.field > 1) { |
2414 | vino_dma_stop(&vino_drvdata->b); | ||
2415 | vino_clear_interrupt(&vino_drvdata->b); | ||
2416 | vino_drvdata->b.field = 0; | ||
2417 | done_b = 1; | ||
2418 | } | ||
2419 | dprintk("channel B end-of-field " | ||
2420 | "interrupt: %04x\n", intr); | ||
2421 | } else { | ||
2234 | vino_dma_stop(&vino_drvdata->b); | 2422 | vino_dma_stop(&vino_drvdata->b); |
2235 | vino_clear_interrupt(&vino_drvdata->b); | 2423 | vino_clear_interrupt(&vino_drvdata->b); |
2236 | vino_drvdata->b.field = 0; | 2424 | vino_drvdata->b.field = 0; |
2237 | done_b = 1; | 2425 | skip_b = 1; |
2426 | dprintk("channel B error interrupt: %04x\n", | ||
2427 | intr); | ||
2238 | } | 2428 | } |
2239 | dprintk("intr: channel B end-of-field interrupt: " | ||
2240 | "%04x\n", intr); | ||
2241 | } else { | ||
2242 | vino_dma_stop(&vino_drvdata->b); | ||
2243 | vino_clear_interrupt(&vino_drvdata->b); | ||
2244 | done_b = 1; | ||
2245 | dprintk("channel B error interrupt: %04x\n", intr); | ||
2246 | } | 2429 | } |
2247 | } | ||
2248 | 2430 | ||
2249 | /* always remember to clear interrupt status */ | 2431 | /* Always remember to clear interrupt status. |
2250 | vino->intr_status = ~intr; | 2432 | * Disable VINO interrupts while we do this. */ |
2433 | ctrl = vino->control; | ||
2434 | vino->control = ctrl & ~(VINO_CTRL_A_INT | VINO_CTRL_B_INT); | ||
2435 | vino->intr_status = ~intr; | ||
2436 | vino->control = ctrl; | ||
2251 | 2437 | ||
2252 | spin_unlock(&vino_drvdata->vino_lock); | 2438 | spin_unlock(&vino_drvdata->vino_lock); |
2253 | 2439 | ||
2254 | if (done_a) { | 2440 | if ((!handled_a) && (done_a || skip_a)) { |
2255 | vino_frame_done(&vino_drvdata->a, fc_a); | 2441 | if (!skip_a) { |
2256 | dprintk("channel A frame done, interrupt: %d\n", intr); | 2442 | do_gettimeofday(&vino_drvdata-> |
2257 | } | 2443 | a.int_data.timestamp); |
2258 | if (done_b) { | 2444 | vino_drvdata->a.int_data.frame_counter = fc_a; |
2259 | vino_frame_done(&vino_drvdata->b, fc_b); | 2445 | } |
2260 | dprintk("channel B frame done, interrupt: %d\n", intr); | 2446 | vino_drvdata->a.int_data.skip = skip_a; |
2447 | |||
2448 | dprintk("channel A %s, interrupt: %d\n", | ||
2449 | skip_a ? "skipping frame" : "frame done", | ||
2450 | intr); | ||
2451 | tasklet_hi_schedule(&vino_tasklet_a); | ||
2452 | handled_a = 1; | ||
2453 | } | ||
2454 | |||
2455 | if ((!handled_b) && (done_b || skip_b)) { | ||
2456 | if (!skip_b) { | ||
2457 | do_gettimeofday(&vino_drvdata-> | ||
2458 | b.int_data.timestamp); | ||
2459 | vino_drvdata->b.int_data.frame_counter = fc_b; | ||
2460 | } | ||
2461 | vino_drvdata->b.int_data.skip = skip_b; | ||
2462 | |||
2463 | dprintk("channel B %s, interrupt: %d\n", | ||
2464 | skip_b ? "skipping frame" : "frame done", | ||
2465 | intr); | ||
2466 | tasklet_hi_schedule(&vino_tasklet_b); | ||
2467 | handled_b = 1; | ||
2468 | } | ||
2469 | |||
2470 | #ifdef VINO_DEBUG_INT | ||
2471 | loop++; | ||
2472 | #endif | ||
2473 | spin_lock(&vino_drvdata->vino_lock); | ||
2261 | } | 2474 | } |
2262 | 2475 | ||
2476 | spin_unlock(&vino_drvdata->vino_lock); | ||
2477 | |||
2263 | return IRQ_HANDLED; | 2478 | return IRQ_HANDLED; |
2264 | } | 2479 | } |
2265 | 2480 | ||
@@ -2279,11 +2494,13 @@ static int vino_get_saa7191_input(int input) | |||
2279 | } | 2494 | } |
2280 | } | 2495 | } |
2281 | 2496 | ||
2282 | static int vino_get_saa7191_norm(int norm) | 2497 | static int vino_get_saa7191_norm(unsigned int data_norm) |
2283 | { | 2498 | { |
2284 | switch (norm) { | 2499 | switch (data_norm) { |
2285 | case VINO_DATA_NORM_AUTO: | 2500 | case VINO_DATA_NORM_AUTO: |
2286 | return SAA7191_NORM_AUTO; | 2501 | return SAA7191_NORM_AUTO; |
2502 | case VINO_DATA_NORM_AUTO_EXT: | ||
2503 | return SAA7191_NORM_AUTO_EXT; | ||
2287 | case VINO_DATA_NORM_PAL: | 2504 | case VINO_DATA_NORM_PAL: |
2288 | return SAA7191_NORM_PAL; | 2505 | return SAA7191_NORM_PAL; |
2289 | case VINO_DATA_NORM_NTSC: | 2506 | case VINO_DATA_NORM_NTSC: |
@@ -2297,6 +2514,57 @@ static int vino_get_saa7191_norm(int norm) | |||
2297 | } | 2514 | } |
2298 | } | 2515 | } |
2299 | 2516 | ||
2517 | static int vino_get_from_saa7191_norm(int saa7191_norm) | ||
2518 | { | ||
2519 | switch (saa7191_norm) { | ||
2520 | case SAA7191_NORM_PAL: | ||
2521 | return VINO_DATA_NORM_PAL; | ||
2522 | case SAA7191_NORM_NTSC: | ||
2523 | return VINO_DATA_NORM_NTSC; | ||
2524 | case SAA7191_NORM_SECAM: | ||
2525 | return VINO_DATA_NORM_SECAM; | ||
2526 | default: | ||
2527 | printk(KERN_ERR "VINO: vino_get_from_saa7191_norm(): " | ||
2528 | "invalid norm!\n"); | ||
2529 | return VINO_DATA_NORM_NONE; | ||
2530 | } | ||
2531 | } | ||
2532 | |||
2533 | static int vino_saa7191_set_norm(unsigned int *data_norm) | ||
2534 | { | ||
2535 | int saa7191_norm, new_data_norm; | ||
2536 | int err = 0; | ||
2537 | |||
2538 | saa7191_norm = vino_get_saa7191_norm(*data_norm); | ||
2539 | |||
2540 | err = i2c_decoder_command(DECODER_SAA7191_SET_NORM, | ||
2541 | &saa7191_norm); | ||
2542 | if (err) | ||
2543 | goto out; | ||
2544 | |||
2545 | if ((*data_norm == VINO_DATA_NORM_AUTO) | ||
2546 | || (*data_norm == VINO_DATA_NORM_AUTO_EXT)) { | ||
2547 | struct saa7191_status status; | ||
2548 | |||
2549 | err = i2c_decoder_command(DECODER_SAA7191_GET_STATUS, | ||
2550 | &status); | ||
2551 | if (err) | ||
2552 | goto out; | ||
2553 | |||
2554 | new_data_norm = | ||
2555 | vino_get_from_saa7191_norm(status.norm); | ||
2556 | if (new_data_norm == VINO_DATA_NORM_NONE) { | ||
2557 | err = -EINVAL; | ||
2558 | goto out; | ||
2559 | } | ||
2560 | |||
2561 | *data_norm = (unsigned int)new_data_norm; | ||
2562 | } | ||
2563 | |||
2564 | out: | ||
2565 | return err; | ||
2566 | } | ||
2567 | |||
2300 | /* execute with input_lock locked */ | 2568 | /* execute with input_lock locked */ |
2301 | static int vino_is_input_owner(struct vino_channel_settings *vcs) | 2569 | static int vino_is_input_owner(struct vino_channel_settings *vcs) |
2302 | { | 2570 | { |
@@ -2313,11 +2581,12 @@ static int vino_is_input_owner(struct vino_channel_settings *vcs) | |||
2313 | 2581 | ||
2314 | static int vino_acquire_input(struct vino_channel_settings *vcs) | 2582 | static int vino_acquire_input(struct vino_channel_settings *vcs) |
2315 | { | 2583 | { |
2584 | unsigned long flags; | ||
2316 | int ret = 0; | 2585 | int ret = 0; |
2317 | 2586 | ||
2318 | dprintk("vino_acquire_input():\n"); | 2587 | dprintk("vino_acquire_input():\n"); |
2319 | 2588 | ||
2320 | spin_lock(&vino_drvdata->input_lock); | 2589 | spin_lock_irqsave(&vino_drvdata->input_lock, flags); |
2321 | 2590 | ||
2322 | /* First try D1 and then SAA7191 */ | 2591 | /* First try D1 and then SAA7191 */ |
2323 | if (vino_drvdata->camera.driver | 2592 | if (vino_drvdata->camera.driver |
@@ -2332,23 +2601,48 @@ static int vino_acquire_input(struct vino_channel_settings *vcs) | |||
2332 | vcs->data_norm = VINO_DATA_NORM_D1; | 2601 | vcs->data_norm = VINO_DATA_NORM_D1; |
2333 | } else if (vino_drvdata->decoder.driver | 2602 | } else if (vino_drvdata->decoder.driver |
2334 | && (vino_drvdata->decoder.owner == VINO_NO_CHANNEL)) { | 2603 | && (vino_drvdata->decoder.owner == VINO_NO_CHANNEL)) { |
2604 | int input, data_norm; | ||
2335 | int saa7191_input; | 2605 | int saa7191_input; |
2336 | int saa7191_norm; | ||
2337 | 2606 | ||
2338 | if (i2c_use_client(vino_drvdata->decoder.driver)) { | 2607 | if (i2c_use_client(vino_drvdata->decoder.driver)) { |
2339 | ret = -ENODEV; | 2608 | ret = -ENODEV; |
2340 | goto out; | 2609 | goto out; |
2341 | } | 2610 | } |
2342 | 2611 | ||
2343 | vino_drvdata->decoder.owner = vcs->channel; | 2612 | input = VINO_INPUT_COMPOSITE; |
2344 | vcs->input = VINO_INPUT_COMPOSITE; | 2613 | |
2345 | vcs->data_norm = VINO_DATA_NORM_PAL; | 2614 | saa7191_input = vino_get_saa7191_input(input); |
2615 | ret = i2c_decoder_command(DECODER_SET_INPUT, | ||
2616 | &saa7191_input); | ||
2617 | if (ret) { | ||
2618 | ret = -EINVAL; | ||
2619 | goto out; | ||
2620 | } | ||
2621 | |||
2622 | spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); | ||
2346 | 2623 | ||
2347 | saa7191_input = vino_get_saa7191_input(vcs->input); | 2624 | /* Don't hold spinlocks while auto-detecting norm |
2348 | i2c_decoder_command(DECODER_SET_INPUT, &saa7191_input); | 2625 | * as it may take a while... */ |
2349 | 2626 | ||
2350 | saa7191_norm = vino_get_saa7191_norm(vcs->data_norm); | 2627 | data_norm = VINO_DATA_NORM_AUTO_EXT; |
2351 | i2c_decoder_command(DECODER_SAA7191_SET_NORM, &saa7191_norm); | 2628 | |
2629 | ret = vino_saa7191_set_norm(&data_norm); | ||
2630 | if ((ret == -EBUSY) || (ret == -EAGAIN)) { | ||
2631 | data_norm = VINO_DATA_NORM_PAL; | ||
2632 | ret = vino_saa7191_set_norm(&data_norm); | ||
2633 | } | ||
2634 | |||
2635 | spin_lock_irqsave(&vino_drvdata->input_lock, flags); | ||
2636 | |||
2637 | if (ret) { | ||
2638 | ret = -EINVAL; | ||
2639 | goto out; | ||
2640 | } | ||
2641 | |||
2642 | vino_drvdata->decoder.owner = vcs->channel; | ||
2643 | |||
2644 | vcs->input = input; | ||
2645 | vcs->data_norm = data_norm; | ||
2352 | } else { | 2646 | } else { |
2353 | vcs->input = (vcs->channel == VINO_CHANNEL_A) ? | 2647 | vcs->input = (vcs->channel == VINO_CHANNEL_A) ? |
2354 | vino_drvdata->b.input : vino_drvdata->a.input; | 2648 | vino_drvdata->b.input : vino_drvdata->a.input; |
@@ -2361,15 +2655,14 @@ static int vino_acquire_input(struct vino_channel_settings *vcs) | |||
2361 | goto out; | 2655 | goto out; |
2362 | } | 2656 | } |
2363 | 2657 | ||
2364 | if (vino_is_input_owner(vcs)) { | 2658 | vino_set_default_clipping(vcs); |
2365 | vino_set_default_clipping(vcs); | 2659 | vino_set_default_scaling(vcs); |
2366 | vino_set_default_framerate(vcs); | 2660 | vino_set_default_framerate(vcs); |
2367 | } | ||
2368 | 2661 | ||
2369 | dprintk("vino_acquire_input(): %s\n", vino_inputs[vcs->input].name); | 2662 | dprintk("vino_acquire_input(): %s\n", vino_inputs[vcs->input].name); |
2370 | 2663 | ||
2371 | out: | 2664 | out: |
2372 | spin_unlock(&vino_drvdata->input_lock); | 2665 | spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); |
2373 | 2666 | ||
2374 | return ret; | 2667 | return ret; |
2375 | } | 2668 | } |
@@ -2378,16 +2671,17 @@ static int vino_set_input(struct vino_channel_settings *vcs, int input) | |||
2378 | { | 2671 | { |
2379 | struct vino_channel_settings *vcs2 = (vcs->channel == VINO_CHANNEL_A) ? | 2672 | struct vino_channel_settings *vcs2 = (vcs->channel == VINO_CHANNEL_A) ? |
2380 | &vino_drvdata->b : &vino_drvdata->a; | 2673 | &vino_drvdata->b : &vino_drvdata->a; |
2674 | unsigned long flags; | ||
2381 | int ret = 0; | 2675 | int ret = 0; |
2382 | 2676 | ||
2383 | dprintk("vino_set_input():\n"); | 2677 | dprintk("vino_set_input():\n"); |
2384 | 2678 | ||
2385 | spin_lock(&vino_drvdata->input_lock); | 2679 | spin_lock_irqsave(&vino_drvdata->input_lock, flags); |
2386 | 2680 | ||
2387 | if (vcs->input == input) | 2681 | if (vcs->input == input) |
2388 | goto out; | 2682 | goto out; |
2389 | 2683 | ||
2390 | switch(input) { | 2684 | switch (input) { |
2391 | case VINO_INPUT_COMPOSITE: | 2685 | case VINO_INPUT_COMPOSITE: |
2392 | case VINO_INPUT_SVIDEO: | 2686 | case VINO_INPUT_SVIDEO: |
2393 | if (!vino_drvdata->decoder.driver) { | 2687 | if (!vino_drvdata->decoder.driver) { |
@@ -2404,19 +2698,43 @@ static int vino_set_input(struct vino_channel_settings *vcs, int input) | |||
2404 | } | 2698 | } |
2405 | 2699 | ||
2406 | if (vino_drvdata->decoder.owner == vcs->channel) { | 2700 | if (vino_drvdata->decoder.owner == vcs->channel) { |
2701 | int data_norm; | ||
2407 | int saa7191_input; | 2702 | int saa7191_input; |
2408 | int saa7191_norm; | ||
2409 | 2703 | ||
2410 | vcs->input = input; | 2704 | saa7191_input = vino_get_saa7191_input(input); |
2411 | vcs->data_norm = VINO_DATA_NORM_PAL; | 2705 | ret = i2c_decoder_command(DECODER_SET_INPUT, |
2706 | &saa7191_input); | ||
2707 | if (ret) { | ||
2708 | vino_drvdata->decoder.owner = VINO_NO_CHANNEL; | ||
2709 | ret = -EINVAL; | ||
2710 | goto out; | ||
2711 | } | ||
2712 | |||
2713 | spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); | ||
2714 | |||
2715 | /* Don't hold spinlocks while auto-detecting norm | ||
2716 | * as it may take a while... */ | ||
2717 | |||
2718 | data_norm = VINO_DATA_NORM_AUTO_EXT; | ||
2719 | |||
2720 | ret = vino_saa7191_set_norm(&data_norm); | ||
2721 | if ((ret == -EBUSY) || (ret == -EAGAIN)) { | ||
2722 | data_norm = VINO_DATA_NORM_PAL; | ||
2723 | ret = vino_saa7191_set_norm(&data_norm); | ||
2724 | } | ||
2412 | 2725 | ||
2413 | saa7191_input = vino_get_saa7191_input(vcs->input); | 2726 | spin_lock_irqsave(&vino_drvdata->input_lock, flags); |
2414 | i2c_decoder_command(DECODER_SET_INPUT, &saa7191_input); | 2727 | |
2415 | saa7191_norm = vino_get_saa7191_norm(vcs->data_norm); | 2728 | if (ret) { |
2416 | i2c_decoder_command(DECODER_SAA7191_SET_NORM, | 2729 | vino_drvdata->decoder.owner = VINO_NO_CHANNEL; |
2417 | &saa7191_norm); | 2730 | ret = -EINVAL; |
2731 | goto out; | ||
2732 | } | ||
2733 | |||
2734 | vcs->input = input; | ||
2735 | vcs->data_norm = data_norm; | ||
2418 | } else { | 2736 | } else { |
2419 | if (vcs2->input != input) { | 2737 | if (input != vcs2->input) { |
2420 | ret = -EBUSY; | 2738 | ret = -EBUSY; |
2421 | goto out; | 2739 | goto out; |
2422 | } | 2740 | } |
@@ -2471,12 +2789,13 @@ static int vino_set_input(struct vino_channel_settings *vcs, int input) | |||
2471 | } | 2789 | } |
2472 | 2790 | ||
2473 | vino_set_default_clipping(vcs); | 2791 | vino_set_default_clipping(vcs); |
2792 | vino_set_default_scaling(vcs); | ||
2474 | vino_set_default_framerate(vcs); | 2793 | vino_set_default_framerate(vcs); |
2475 | 2794 | ||
2476 | dprintk("vino_set_input(): %s\n", vino_inputs[vcs->input].name); | 2795 | dprintk("vino_set_input(): %s\n", vino_inputs[vcs->input].name); |
2477 | 2796 | ||
2478 | out: | 2797 | out: |
2479 | spin_unlock(&vino_drvdata->input_lock); | 2798 | spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); |
2480 | 2799 | ||
2481 | return ret; | 2800 | return ret; |
2482 | } | 2801 | } |
@@ -2485,10 +2804,11 @@ static void vino_release_input(struct vino_channel_settings *vcs) | |||
2485 | { | 2804 | { |
2486 | struct vino_channel_settings *vcs2 = (vcs->channel == VINO_CHANNEL_A) ? | 2805 | struct vino_channel_settings *vcs2 = (vcs->channel == VINO_CHANNEL_A) ? |
2487 | &vino_drvdata->b : &vino_drvdata->a; | 2806 | &vino_drvdata->b : &vino_drvdata->a; |
2807 | unsigned long flags; | ||
2488 | 2808 | ||
2489 | dprintk("vino_release_input():\n"); | 2809 | dprintk("vino_release_input():\n"); |
2490 | 2810 | ||
2491 | spin_lock(&vino_drvdata->input_lock); | 2811 | spin_lock_irqsave(&vino_drvdata->input_lock, flags); |
2492 | 2812 | ||
2493 | /* Release ownership of the channel | 2813 | /* Release ownership of the channel |
2494 | * and if the other channel takes input from | 2814 | * and if the other channel takes input from |
@@ -2511,34 +2831,61 @@ static void vino_release_input(struct vino_channel_settings *vcs) | |||
2511 | } | 2831 | } |
2512 | vcs->input = VINO_INPUT_NONE; | 2832 | vcs->input = VINO_INPUT_NONE; |
2513 | 2833 | ||
2514 | spin_unlock(&vino_drvdata->input_lock); | 2834 | spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); |
2515 | } | 2835 | } |
2516 | 2836 | ||
2517 | /* execute with input_lock locked */ | 2837 | /* execute with input_lock locked */ |
2518 | static int vino_set_data_norm(struct vino_channel_settings *vcs, | 2838 | static int vino_set_data_norm(struct vino_channel_settings *vcs, |
2519 | unsigned int data_norm) | 2839 | unsigned int data_norm, |
2840 | unsigned long *flags) | ||
2520 | { | 2841 | { |
2521 | int saa7191_norm; | 2842 | int err = 0; |
2843 | |||
2844 | if (data_norm == vcs->data_norm) | ||
2845 | return 0; | ||
2522 | 2846 | ||
2523 | switch (vcs->input) { | 2847 | switch (vcs->input) { |
2524 | case VINO_INPUT_D1: | 2848 | case VINO_INPUT_D1: |
2525 | /* only one "norm" supported */ | 2849 | /* only one "norm" supported */ |
2526 | if (data_norm != VINO_DATA_NORM_D1) | 2850 | if ((data_norm != VINO_DATA_NORM_D1) |
2851 | && (data_norm != VINO_DATA_NORM_AUTO) | ||
2852 | && (data_norm != VINO_DATA_NORM_AUTO_EXT)) | ||
2527 | return -EINVAL; | 2853 | return -EINVAL; |
2528 | break; | 2854 | break; |
2529 | case VINO_INPUT_COMPOSITE: | 2855 | case VINO_INPUT_COMPOSITE: |
2530 | case VINO_INPUT_SVIDEO: | 2856 | case VINO_INPUT_SVIDEO: { |
2857 | if ((data_norm != VINO_DATA_NORM_PAL) | ||
2858 | && (data_norm != VINO_DATA_NORM_NTSC) | ||
2859 | && (data_norm != VINO_DATA_NORM_SECAM) | ||
2860 | && (data_norm != VINO_DATA_NORM_AUTO) | ||
2861 | && (data_norm != VINO_DATA_NORM_AUTO_EXT)) | ||
2862 | return -EINVAL; | ||
2531 | 2863 | ||
2532 | saa7191_norm = vino_get_saa7191_norm(data_norm); | 2864 | spin_unlock_irqrestore(&vino_drvdata->input_lock, *flags); |
2865 | |||
2866 | /* Don't hold spinlocks while setting norm | ||
2867 | * as it may take a while... */ | ||
2868 | |||
2869 | err = vino_saa7191_set_norm(&data_norm); | ||
2870 | |||
2871 | spin_lock_irqsave(&vino_drvdata->input_lock, *flags); | ||
2872 | |||
2873 | if (err) | ||
2874 | goto out; | ||
2533 | 2875 | ||
2534 | i2c_decoder_command(DECODER_SAA7191_SET_NORM, &saa7191_norm); | ||
2535 | vcs->data_norm = data_norm; | 2876 | vcs->data_norm = data_norm; |
2877 | |||
2878 | vino_set_default_clipping(vcs); | ||
2879 | vino_set_default_scaling(vcs); | ||
2880 | vino_set_default_framerate(vcs); | ||
2536 | break; | 2881 | break; |
2882 | } | ||
2537 | default: | 2883 | default: |
2538 | return -EINVAL; | 2884 | return -EINVAL; |
2539 | } | 2885 | } |
2540 | 2886 | ||
2541 | return 0; | 2887 | out: |
2888 | return err; | ||
2542 | } | 2889 | } |
2543 | 2890 | ||
2544 | /* V4L2 helper functions */ | 2891 | /* V4L2 helper functions */ |
@@ -2558,8 +2905,9 @@ static int vino_find_data_format(__u32 pixelformat) | |||
2558 | static int vino_enum_data_norm(struct vino_channel_settings *vcs, __u32 index) | 2905 | static int vino_enum_data_norm(struct vino_channel_settings *vcs, __u32 index) |
2559 | { | 2906 | { |
2560 | int data_norm = VINO_DATA_NORM_NONE; | 2907 | int data_norm = VINO_DATA_NORM_NONE; |
2908 | unsigned long flags; | ||
2561 | 2909 | ||
2562 | spin_lock(&vino_drvdata->input_lock); | 2910 | spin_lock_irqsave(&vino_drvdata->input_lock, flags); |
2563 | switch(vcs->input) { | 2911 | switch(vcs->input) { |
2564 | case VINO_INPUT_COMPOSITE: | 2912 | case VINO_INPUT_COMPOSITE: |
2565 | case VINO_INPUT_SVIDEO: | 2913 | case VINO_INPUT_SVIDEO: |
@@ -2577,7 +2925,7 @@ static int vino_enum_data_norm(struct vino_channel_settings *vcs, __u32 index) | |||
2577 | } | 2925 | } |
2578 | break; | 2926 | break; |
2579 | } | 2927 | } |
2580 | spin_unlock(&vino_drvdata->input_lock); | 2928 | spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); |
2581 | 2929 | ||
2582 | return data_norm; | 2930 | return data_norm; |
2583 | } | 2931 | } |
@@ -2585,8 +2933,9 @@ static int vino_enum_data_norm(struct vino_channel_settings *vcs, __u32 index) | |||
2585 | static int vino_enum_input(struct vino_channel_settings *vcs, __u32 index) | 2933 | static int vino_enum_input(struct vino_channel_settings *vcs, __u32 index) |
2586 | { | 2934 | { |
2587 | int input = VINO_INPUT_NONE; | 2935 | int input = VINO_INPUT_NONE; |
2936 | unsigned long flags; | ||
2588 | 2937 | ||
2589 | spin_lock(&vino_drvdata->input_lock); | 2938 | spin_lock_irqsave(&vino_drvdata->input_lock, flags); |
2590 | if (vino_drvdata->decoder.driver && vino_drvdata->camera.driver) { | 2939 | if (vino_drvdata->decoder.driver && vino_drvdata->camera.driver) { |
2591 | switch (index) { | 2940 | switch (index) { |
2592 | case 0: | 2941 | case 0: |
@@ -2615,7 +2964,7 @@ static int vino_enum_input(struct vino_channel_settings *vcs, __u32 index) | |||
2615 | break; | 2964 | break; |
2616 | } | 2965 | } |
2617 | } | 2966 | } |
2618 | spin_unlock(&vino_drvdata->input_lock); | 2967 | spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); |
2619 | 2968 | ||
2620 | return input; | 2969 | return input; |
2621 | } | 2970 | } |
@@ -2704,15 +3053,16 @@ static int vino_v4l2_enuminput(struct vino_channel_settings *vcs, | |||
2704 | } | 3053 | } |
2705 | 3054 | ||
2706 | static int vino_v4l2_g_input(struct vino_channel_settings *vcs, | 3055 | static int vino_v4l2_g_input(struct vino_channel_settings *vcs, |
2707 | struct v4l2_input *i) | 3056 | unsigned int *i) |
2708 | { | 3057 | { |
2709 | __u32 index; | 3058 | __u32 index; |
2710 | int input; | 3059 | int input; |
3060 | unsigned long flags; | ||
2711 | 3061 | ||
2712 | spin_lock(&vino_drvdata->input_lock); | 3062 | spin_lock_irqsave(&vino_drvdata->input_lock, flags); |
2713 | input = vcs->input; | 3063 | input = vcs->input; |
2714 | index = vino_find_input_index(vcs); | 3064 | index = vino_find_input_index(vcs); |
2715 | spin_unlock(&vino_drvdata->input_lock); | 3065 | spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); |
2716 | 3066 | ||
2717 | dprintk("input = %d\n", input); | 3067 | dprintk("input = %d\n", input); |
2718 | 3068 | ||
@@ -2720,23 +3070,18 @@ static int vino_v4l2_g_input(struct vino_channel_settings *vcs, | |||
2720 | return -EINVAL; | 3070 | return -EINVAL; |
2721 | } | 3071 | } |
2722 | 3072 | ||
2723 | memset(i, 0, sizeof(struct v4l2_input)); | 3073 | *i = index; |
2724 | |||
2725 | i->index = index; | ||
2726 | i->type = V4L2_INPUT_TYPE_CAMERA; | ||
2727 | i->std = vino_inputs[input].std; | ||
2728 | strcpy(i->name, vino_inputs[input].name); | ||
2729 | 3074 | ||
2730 | return 0; | 3075 | return 0; |
2731 | } | 3076 | } |
2732 | 3077 | ||
2733 | static int vino_v4l2_s_input(struct vino_channel_settings *vcs, | 3078 | static int vino_v4l2_s_input(struct vino_channel_settings *vcs, |
2734 | struct v4l2_input *i) | 3079 | unsigned int *i) |
2735 | { | 3080 | { |
2736 | int input; | 3081 | int input; |
2737 | dprintk("requested input = %d\n", i->index); | 3082 | dprintk("requested input = %d\n", *i); |
2738 | 3083 | ||
2739 | input = vino_enum_input(vcs, i->index); | 3084 | input = vino_enum_input(vcs, *i); |
2740 | if (input == VINO_INPUT_NONE) | 3085 | if (input == VINO_INPUT_NONE) |
2741 | return -EINVAL; | 3086 | return -EINVAL; |
2742 | 3087 | ||
@@ -2747,7 +3092,9 @@ static int vino_v4l2_enumstd(struct vino_channel_settings *vcs, | |||
2747 | struct v4l2_standard *s) | 3092 | struct v4l2_standard *s) |
2748 | { | 3093 | { |
2749 | int index = s->index; | 3094 | int index = s->index; |
2750 | int data_norm = vino_enum_data_norm(vcs, index); | 3095 | int data_norm; |
3096 | |||
3097 | data_norm = vino_enum_data_norm(vcs, index); | ||
2751 | dprintk("standard index = %d\n", index); | 3098 | dprintk("standard index = %d\n", index); |
2752 | 3099 | ||
2753 | if (data_norm == VINO_DATA_NORM_NONE) | 3100 | if (data_norm == VINO_DATA_NORM_NONE) |
@@ -2771,13 +3118,55 @@ static int vino_v4l2_enumstd(struct vino_channel_settings *vcs, | |||
2771 | return 0; | 3118 | return 0; |
2772 | } | 3119 | } |
2773 | 3120 | ||
3121 | static int vino_v4l2_querystd(struct vino_channel_settings *vcs, | ||
3122 | v4l2_std_id *std) | ||
3123 | { | ||
3124 | unsigned long flags; | ||
3125 | int err = 0; | ||
3126 | |||
3127 | spin_lock_irqsave(&vino_drvdata->input_lock, flags); | ||
3128 | |||
3129 | switch (vcs->input) { | ||
3130 | case VINO_INPUT_D1: | ||
3131 | *std = vino_inputs[vcs->input].std; | ||
3132 | break; | ||
3133 | case VINO_INPUT_COMPOSITE: | ||
3134 | case VINO_INPUT_SVIDEO: { | ||
3135 | struct saa7191_status status; | ||
3136 | |||
3137 | i2c_decoder_command(DECODER_SAA7191_GET_STATUS, &status); | ||
3138 | |||
3139 | if (status.signal) { | ||
3140 | if (status.signal_60hz) { | ||
3141 | *std = V4L2_STD_NTSC; | ||
3142 | } else { | ||
3143 | *std = V4L2_STD_PAL | V4L2_STD_SECAM; | ||
3144 | } | ||
3145 | } else { | ||
3146 | *std = vino_inputs[vcs->input].std; | ||
3147 | } | ||
3148 | break; | ||
3149 | } | ||
3150 | default: | ||
3151 | err = -EINVAL; | ||
3152 | } | ||
3153 | |||
3154 | spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); | ||
3155 | |||
3156 | return err; | ||
3157 | } | ||
3158 | |||
2774 | static int vino_v4l2_g_std(struct vino_channel_settings *vcs, | 3159 | static int vino_v4l2_g_std(struct vino_channel_settings *vcs, |
2775 | v4l2_std_id *std) | 3160 | v4l2_std_id *std) |
2776 | { | 3161 | { |
2777 | spin_lock(&vino_drvdata->input_lock); | 3162 | unsigned long flags; |
2778 | dprintk("current standard = %d\n", vcs->data_norm); | 3163 | |
3164 | spin_lock_irqsave(&vino_drvdata->input_lock, flags); | ||
3165 | |||
2779 | *std = vino_data_norms[vcs->data_norm].std; | 3166 | *std = vino_data_norms[vcs->data_norm].std; |
2780 | spin_unlock(&vino_drvdata->input_lock); | 3167 | dprintk("current standard = %d\n", vcs->data_norm); |
3168 | |||
3169 | spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); | ||
2781 | 3170 | ||
2782 | return 0; | 3171 | return 0; |
2783 | } | 3172 | } |
@@ -2785,13 +3174,18 @@ static int vino_v4l2_g_std(struct vino_channel_settings *vcs, | |||
2785 | static int vino_v4l2_s_std(struct vino_channel_settings *vcs, | 3174 | static int vino_v4l2_s_std(struct vino_channel_settings *vcs, |
2786 | v4l2_std_id *std) | 3175 | v4l2_std_id *std) |
2787 | { | 3176 | { |
3177 | unsigned long flags; | ||
2788 | int ret = 0; | 3178 | int ret = 0; |
2789 | 3179 | ||
2790 | spin_lock(&vino_drvdata->input_lock); | 3180 | spin_lock_irqsave(&vino_drvdata->input_lock, flags); |
3181 | |||
3182 | if (!vino_is_input_owner(vcs)) { | ||
3183 | ret = -EBUSY; | ||
3184 | goto out; | ||
3185 | } | ||
2791 | 3186 | ||
2792 | /* check if the standard is valid for the current input */ | 3187 | /* check if the standard is valid for the current input */ |
2793 | if (vino_is_input_owner(vcs) | 3188 | if ((*std) & vino_inputs[vcs->input].std) { |
2794 | && (vino_inputs[vcs->input].std & (*std))) { | ||
2795 | dprintk("standard accepted\n"); | 3189 | dprintk("standard accepted\n"); |
2796 | 3190 | ||
2797 | /* change the video norm for SAA7191 | 3191 | /* change the video norm for SAA7191 |
@@ -2800,24 +3194,33 @@ static int vino_v4l2_s_std(struct vino_channel_settings *vcs, | |||
2800 | if (vcs->input == VINO_INPUT_D1) | 3194 | if (vcs->input == VINO_INPUT_D1) |
2801 | goto out; | 3195 | goto out; |
2802 | 3196 | ||
2803 | if ((*std) & V4L2_STD_PAL) { | 3197 | if (((*std) & V4L2_STD_PAL) |
2804 | vino_set_data_norm(vcs, VINO_DATA_NORM_PAL); | 3198 | && ((*std) & V4L2_STD_NTSC) |
2805 | vcs->data_norm = VINO_DATA_NORM_PAL; | 3199 | && ((*std) & V4L2_STD_SECAM)) { |
3200 | ret = vino_set_data_norm(vcs, VINO_DATA_NORM_AUTO_EXT, | ||
3201 | &flags); | ||
3202 | } else if ((*std) & V4L2_STD_PAL) { | ||
3203 | ret = vino_set_data_norm(vcs, VINO_DATA_NORM_PAL, | ||
3204 | &flags); | ||
2806 | } else if ((*std) & V4L2_STD_NTSC) { | 3205 | } else if ((*std) & V4L2_STD_NTSC) { |
2807 | vino_set_data_norm(vcs, VINO_DATA_NORM_NTSC); | 3206 | ret = vino_set_data_norm(vcs, VINO_DATA_NORM_NTSC, |
2808 | vcs->data_norm = VINO_DATA_NORM_NTSC; | 3207 | &flags); |
2809 | } else if ((*std) & V4L2_STD_SECAM) { | 3208 | } else if ((*std) & V4L2_STD_SECAM) { |
2810 | vino_set_data_norm(vcs, VINO_DATA_NORM_SECAM); | 3209 | ret = vino_set_data_norm(vcs, VINO_DATA_NORM_SECAM, |
2811 | vcs->data_norm = VINO_DATA_NORM_SECAM; | 3210 | &flags); |
2812 | } else { | 3211 | } else { |
2813 | ret = -EINVAL; | 3212 | ret = -EINVAL; |
2814 | } | 3213 | } |
3214 | |||
3215 | if (ret) { | ||
3216 | ret = -EINVAL; | ||
3217 | } | ||
2815 | } else { | 3218 | } else { |
2816 | ret = -EINVAL; | 3219 | ret = -EINVAL; |
2817 | } | 3220 | } |
2818 | 3221 | ||
2819 | out: | 3222 | out: |
2820 | spin_unlock(&vino_drvdata->input_lock); | 3223 | spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); |
2821 | 3224 | ||
2822 | return ret; | 3225 | return ret; |
2823 | } | 3226 | } |
@@ -2855,6 +3258,7 @@ static int vino_v4l2_try_fmt(struct vino_channel_settings *vcs, | |||
2855 | struct v4l2_format *f) | 3258 | struct v4l2_format *f) |
2856 | { | 3259 | { |
2857 | struct vino_channel_settings tempvcs; | 3260 | struct vino_channel_settings tempvcs; |
3261 | unsigned long flags; | ||
2858 | 3262 | ||
2859 | switch (f->type) { | 3263 | switch (f->type) { |
2860 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: { | 3264 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: { |
@@ -2863,13 +3267,13 @@ static int vino_v4l2_try_fmt(struct vino_channel_settings *vcs, | |||
2863 | dprintk("requested: w = %d, h = %d\n", | 3267 | dprintk("requested: w = %d, h = %d\n", |
2864 | pf->width, pf->height); | 3268 | pf->width, pf->height); |
2865 | 3269 | ||
2866 | spin_lock(&vino_drvdata->input_lock); | 3270 | spin_lock_irqsave(&vino_drvdata->input_lock, flags); |
2867 | memcpy(&tempvcs, vcs, sizeof(struct vino_channel_settings)); | 3271 | memcpy(&tempvcs, vcs, sizeof(struct vino_channel_settings)); |
2868 | spin_unlock(&vino_drvdata->input_lock); | 3272 | spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); |
2869 | 3273 | ||
2870 | tempvcs.data_format = vino_find_data_format(pf->pixelformat); | 3274 | tempvcs.data_format = vino_find_data_format(pf->pixelformat); |
2871 | if (tempvcs.data_format == VINO_DATA_FMT_NONE) { | 3275 | if (tempvcs.data_format == VINO_DATA_FMT_NONE) { |
2872 | tempvcs.data_format = VINO_DATA_FMT_RGB32; | 3276 | tempvcs.data_format = VINO_DATA_FMT_GREY; |
2873 | pf->pixelformat = | 3277 | pf->pixelformat = |
2874 | vino_data_formats[tempvcs.data_format]. | 3278 | vino_data_formats[tempvcs.data_format]. |
2875 | pixelformat; | 3279 | pixelformat; |
@@ -2908,10 +3312,13 @@ static int vino_v4l2_try_fmt(struct vino_channel_settings *vcs, | |||
2908 | static int vino_v4l2_g_fmt(struct vino_channel_settings *vcs, | 3312 | static int vino_v4l2_g_fmt(struct vino_channel_settings *vcs, |
2909 | struct v4l2_format *f) | 3313 | struct v4l2_format *f) |
2910 | { | 3314 | { |
3315 | unsigned long flags; | ||
3316 | |||
2911 | switch (f->type) { | 3317 | switch (f->type) { |
2912 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: { | 3318 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: { |
2913 | struct v4l2_pix_format *pf = &f->fmt.pix; | 3319 | struct v4l2_pix_format *pf = &f->fmt.pix; |
2914 | spin_lock(&vino_drvdata->input_lock); | 3320 | |
3321 | spin_lock_irqsave(&vino_drvdata->input_lock, flags); | ||
2915 | 3322 | ||
2916 | pf->width = (vcs->clipping.right - vcs->clipping.left) / | 3323 | pf->width = (vcs->clipping.right - vcs->clipping.left) / |
2917 | vcs->decimation; | 3324 | vcs->decimation; |
@@ -2930,7 +3337,7 @@ static int vino_v4l2_g_fmt(struct vino_channel_settings *vcs, | |||
2930 | 3337 | ||
2931 | pf->priv = 0; | 3338 | pf->priv = 0; |
2932 | 3339 | ||
2933 | spin_unlock(&vino_drvdata->input_lock); | 3340 | spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); |
2934 | break; | 3341 | break; |
2935 | } | 3342 | } |
2936 | case V4L2_BUF_TYPE_VIDEO_OVERLAY: | 3343 | case V4L2_BUF_TYPE_VIDEO_OVERLAY: |
@@ -2945,20 +3352,18 @@ static int vino_v4l2_s_fmt(struct vino_channel_settings *vcs, | |||
2945 | struct v4l2_format *f) | 3352 | struct v4l2_format *f) |
2946 | { | 3353 | { |
2947 | int data_format; | 3354 | int data_format; |
3355 | unsigned long flags; | ||
2948 | 3356 | ||
2949 | switch (f->type) { | 3357 | switch (f->type) { |
2950 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: { | 3358 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: { |
2951 | struct v4l2_pix_format *pf = &f->fmt.pix; | 3359 | struct v4l2_pix_format *pf = &f->fmt.pix; |
2952 | spin_lock(&vino_drvdata->input_lock); | ||
2953 | 3360 | ||
2954 | if (!vino_is_input_owner(vcs)) { | 3361 | spin_lock_irqsave(&vino_drvdata->input_lock, flags); |
2955 | spin_unlock(&vino_drvdata->input_lock); | ||
2956 | return -EINVAL; | ||
2957 | } | ||
2958 | 3362 | ||
2959 | data_format = vino_find_data_format(pf->pixelformat); | 3363 | data_format = vino_find_data_format(pf->pixelformat); |
3364 | |||
2960 | if (data_format == VINO_DATA_FMT_NONE) { | 3365 | if (data_format == VINO_DATA_FMT_NONE) { |
2961 | vcs->data_format = VINO_DATA_FMT_RGB32; | 3366 | vcs->data_format = VINO_DATA_FMT_GREY; |
2962 | pf->pixelformat = | 3367 | pf->pixelformat = |
2963 | vino_data_formats[vcs->data_format]. | 3368 | vino_data_formats[vcs->data_format]. |
2964 | pixelformat; | 3369 | pixelformat; |
@@ -2985,7 +3390,7 @@ static int vino_v4l2_s_fmt(struct vino_channel_settings *vcs, | |||
2985 | 3390 | ||
2986 | pf->priv = 0; | 3391 | pf->priv = 0; |
2987 | 3392 | ||
2988 | spin_unlock(&vino_drvdata->input_lock); | 3393 | spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); |
2989 | break; | 3394 | break; |
2990 | } | 3395 | } |
2991 | case V4L2_BUF_TYPE_VIDEO_OVERLAY: | 3396 | case V4L2_BUF_TYPE_VIDEO_OVERLAY: |
@@ -3000,12 +3405,15 @@ static int vino_v4l2_cropcap(struct vino_channel_settings *vcs, | |||
3000 | struct v4l2_cropcap *ccap) | 3405 | struct v4l2_cropcap *ccap) |
3001 | { | 3406 | { |
3002 | const struct vino_data_norm *norm; | 3407 | const struct vino_data_norm *norm; |
3408 | unsigned long flags; | ||
3003 | 3409 | ||
3004 | switch (ccap->type) { | 3410 | switch (ccap->type) { |
3005 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | 3411 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: |
3006 | spin_lock(&vino_drvdata->input_lock); | 3412 | spin_lock_irqsave(&vino_drvdata->input_lock, flags); |
3413 | |||
3007 | norm = &vino_data_norms[vcs->data_norm]; | 3414 | norm = &vino_data_norms[vcs->data_norm]; |
3008 | spin_unlock(&vino_drvdata->input_lock); | 3415 | |
3416 | spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); | ||
3009 | 3417 | ||
3010 | ccap->bounds.left = 0; | 3418 | ccap->bounds.left = 0; |
3011 | ccap->bounds.top = 0; | 3419 | ccap->bounds.top = 0; |
@@ -3028,16 +3436,18 @@ static int vino_v4l2_cropcap(struct vino_channel_settings *vcs, | |||
3028 | static int vino_v4l2_g_crop(struct vino_channel_settings *vcs, | 3436 | static int vino_v4l2_g_crop(struct vino_channel_settings *vcs, |
3029 | struct v4l2_crop *c) | 3437 | struct v4l2_crop *c) |
3030 | { | 3438 | { |
3439 | unsigned long flags; | ||
3440 | |||
3031 | switch (c->type) { | 3441 | switch (c->type) { |
3032 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | 3442 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: |
3033 | spin_lock(&vino_drvdata->input_lock); | 3443 | spin_lock_irqsave(&vino_drvdata->input_lock, flags); |
3034 | 3444 | ||
3035 | c->c.left = vcs->clipping.left; | 3445 | c->c.left = vcs->clipping.left; |
3036 | c->c.top = vcs->clipping.top; | 3446 | c->c.top = vcs->clipping.top; |
3037 | c->c.width = vcs->clipping.right - vcs->clipping.left; | 3447 | c->c.width = vcs->clipping.right - vcs->clipping.left; |
3038 | c->c.height = vcs->clipping.bottom - vcs->clipping.top; | 3448 | c->c.height = vcs->clipping.bottom - vcs->clipping.top; |
3039 | 3449 | ||
3040 | spin_unlock(&vino_drvdata->input_lock); | 3450 | spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); |
3041 | break; | 3451 | break; |
3042 | case V4L2_BUF_TYPE_VIDEO_OVERLAY: | 3452 | case V4L2_BUF_TYPE_VIDEO_OVERLAY: |
3043 | default: | 3453 | default: |
@@ -3050,18 +3460,16 @@ static int vino_v4l2_g_crop(struct vino_channel_settings *vcs, | |||
3050 | static int vino_v4l2_s_crop(struct vino_channel_settings *vcs, | 3460 | static int vino_v4l2_s_crop(struct vino_channel_settings *vcs, |
3051 | struct v4l2_crop *c) | 3461 | struct v4l2_crop *c) |
3052 | { | 3462 | { |
3463 | unsigned long flags; | ||
3464 | |||
3053 | switch (c->type) { | 3465 | switch (c->type) { |
3054 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | 3466 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: |
3055 | spin_lock(&vino_drvdata->input_lock); | 3467 | spin_lock_irqsave(&vino_drvdata->input_lock, flags); |
3056 | 3468 | ||
3057 | if (!vino_is_input_owner(vcs)) { | ||
3058 | spin_unlock(&vino_drvdata->input_lock); | ||
3059 | return -EINVAL; | ||
3060 | } | ||
3061 | vino_set_clipping(vcs, c->c.left, c->c.top, | 3469 | vino_set_clipping(vcs, c->c.left, c->c.top, |
3062 | c->c.width, c->c.height); | 3470 | c->c.width, c->c.height); |
3063 | 3471 | ||
3064 | spin_unlock(&vino_drvdata->input_lock); | 3472 | spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); |
3065 | break; | 3473 | break; |
3066 | case V4L2_BUF_TYPE_VIDEO_OVERLAY: | 3474 | case V4L2_BUF_TYPE_VIDEO_OVERLAY: |
3067 | default: | 3475 | default: |
@@ -3074,6 +3482,8 @@ static int vino_v4l2_s_crop(struct vino_channel_settings *vcs, | |||
3074 | static int vino_v4l2_g_parm(struct vino_channel_settings *vcs, | 3482 | static int vino_v4l2_g_parm(struct vino_channel_settings *vcs, |
3075 | struct v4l2_streamparm *sp) | 3483 | struct v4l2_streamparm *sp) |
3076 | { | 3484 | { |
3485 | unsigned long flags; | ||
3486 | |||
3077 | switch (sp->type) { | 3487 | switch (sp->type) { |
3078 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: { | 3488 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: { |
3079 | struct v4l2_captureparm *cp = &sp->parm.capture; | 3489 | struct v4l2_captureparm *cp = &sp->parm.capture; |
@@ -3082,9 +3492,11 @@ static int vino_v4l2_g_parm(struct vino_channel_settings *vcs, | |||
3082 | cp->capability = V4L2_CAP_TIMEPERFRAME; | 3492 | cp->capability = V4L2_CAP_TIMEPERFRAME; |
3083 | cp->timeperframe.numerator = 1; | 3493 | cp->timeperframe.numerator = 1; |
3084 | 3494 | ||
3085 | spin_lock(&vino_drvdata->input_lock); | 3495 | spin_lock_irqsave(&vino_drvdata->input_lock, flags); |
3496 | |||
3086 | cp->timeperframe.denominator = vcs->fps; | 3497 | cp->timeperframe.denominator = vcs->fps; |
3087 | spin_unlock(&vino_drvdata->input_lock); | 3498 | |
3499 | spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); | ||
3088 | 3500 | ||
3089 | // TODO: cp->readbuffers = xxx; | 3501 | // TODO: cp->readbuffers = xxx; |
3090 | break; | 3502 | break; |
@@ -3100,15 +3512,13 @@ static int vino_v4l2_g_parm(struct vino_channel_settings *vcs, | |||
3100 | static int vino_v4l2_s_parm(struct vino_channel_settings *vcs, | 3512 | static int vino_v4l2_s_parm(struct vino_channel_settings *vcs, |
3101 | struct v4l2_streamparm *sp) | 3513 | struct v4l2_streamparm *sp) |
3102 | { | 3514 | { |
3515 | unsigned long flags; | ||
3516 | |||
3103 | switch (sp->type) { | 3517 | switch (sp->type) { |
3104 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: { | 3518 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: { |
3105 | struct v4l2_captureparm *cp = &sp->parm.capture; | 3519 | struct v4l2_captureparm *cp = &sp->parm.capture; |
3106 | 3520 | ||
3107 | spin_lock(&vino_drvdata->input_lock); | 3521 | spin_lock_irqsave(&vino_drvdata->input_lock, flags); |
3108 | if (!vino_is_input_owner(vcs)) { | ||
3109 | spin_unlock(&vino_drvdata->input_lock); | ||
3110 | return -EINVAL; | ||
3111 | } | ||
3112 | 3522 | ||
3113 | if ((cp->timeperframe.numerator == 0) || | 3523 | if ((cp->timeperframe.numerator == 0) || |
3114 | (cp->timeperframe.denominator == 0)) { | 3524 | (cp->timeperframe.denominator == 0)) { |
@@ -3118,7 +3528,8 @@ static int vino_v4l2_s_parm(struct vino_channel_settings *vcs, | |||
3118 | vino_set_framerate(vcs, cp->timeperframe.denominator / | 3528 | vino_set_framerate(vcs, cp->timeperframe.denominator / |
3119 | cp->timeperframe.numerator); | 3529 | cp->timeperframe.numerator); |
3120 | } | 3530 | } |
3121 | spin_unlock(&vino_drvdata->input_lock); | 3531 | |
3532 | spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); | ||
3122 | 3533 | ||
3123 | // TODO: set buffers according to cp->readbuffers | 3534 | // TODO: set buffers according to cp->readbuffers |
3124 | break; | 3535 | break; |
@@ -3145,21 +3556,23 @@ static int vino_v4l2_reqbufs(struct vino_channel_settings *vcs, | |||
3145 | return -EINVAL; | 3556 | return -EINVAL; |
3146 | } | 3557 | } |
3147 | 3558 | ||
3148 | if (vino_is_capturing(vcs)) { | ||
3149 | dprintk("busy, capturing\n"); | ||
3150 | return -EBUSY; | ||
3151 | } | ||
3152 | |||
3153 | dprintk("count = %d\n", rb->count); | 3559 | dprintk("count = %d\n", rb->count); |
3154 | if (rb->count > 0) { | 3560 | if (rb->count > 0) { |
3561 | if (vino_is_capturing(vcs)) { | ||
3562 | dprintk("busy, capturing\n"); | ||
3563 | return -EBUSY; | ||
3564 | } | ||
3565 | |||
3155 | if (vino_queue_has_mapped_buffers(&vcs->fb_queue)) { | 3566 | if (vino_queue_has_mapped_buffers(&vcs->fb_queue)) { |
3156 | dprintk("busy, buffers still mapped\n"); | 3567 | dprintk("busy, buffers still mapped\n"); |
3157 | return -EBUSY; | 3568 | return -EBUSY; |
3158 | } else { | 3569 | } else { |
3570 | vcs->streaming = 0; | ||
3159 | vino_queue_free(&vcs->fb_queue); | 3571 | vino_queue_free(&vcs->fb_queue); |
3160 | vino_queue_init(&vcs->fb_queue, &rb->count); | 3572 | vino_queue_init(&vcs->fb_queue, &rb->count); |
3161 | } | 3573 | } |
3162 | } else { | 3574 | } else { |
3575 | vcs->streaming = 0; | ||
3163 | vino_capture_stop(vcs); | 3576 | vino_capture_stop(vcs); |
3164 | vino_queue_free(&vcs->fb_queue); | 3577 | vino_queue_free(&vcs->fb_queue); |
3165 | } | 3578 | } |
@@ -3302,12 +3715,12 @@ static int vino_v4l2_dqbuf(struct vino_channel_settings *vcs, | |||
3302 | err = vino_queue_get_incoming(&vcs->fb_queue, &incoming); | 3715 | err = vino_queue_get_incoming(&vcs->fb_queue, &incoming); |
3303 | if (err) { | 3716 | if (err) { |
3304 | dprintk("vino_queue_get_incoming() failed\n"); | 3717 | dprintk("vino_queue_get_incoming() failed\n"); |
3305 | return -EIO; | 3718 | return -EINVAL; |
3306 | } | 3719 | } |
3307 | err = vino_queue_get_outgoing(&vcs->fb_queue, &outgoing); | 3720 | err = vino_queue_get_outgoing(&vcs->fb_queue, &outgoing); |
3308 | if (err) { | 3721 | if (err) { |
3309 | dprintk("vino_queue_get_outgoing() failed\n"); | 3722 | dprintk("vino_queue_get_outgoing() failed\n"); |
3310 | return -EIO; | 3723 | return -EINVAL; |
3311 | } | 3724 | } |
3312 | 3725 | ||
3313 | dprintk("incoming = %d, outgoing = %d\n", incoming, outgoing); | 3726 | dprintk("incoming = %d, outgoing = %d\n", incoming, outgoing); |
@@ -3327,8 +3740,10 @@ static int vino_v4l2_dqbuf(struct vino_channel_settings *vcs, | |||
3327 | if (err) { | 3740 | if (err) { |
3328 | err = vino_wait_for_frame(vcs); | 3741 | err = vino_wait_for_frame(vcs); |
3329 | if (err) { | 3742 | if (err) { |
3330 | /* interrupted */ | 3743 | /* interrupted or |
3331 | vino_capture_failed(vcs); | 3744 | * no frames captured because |
3745 | * of frame skipping */ | ||
3746 | // vino_capture_failed(vcs); | ||
3332 | return -EIO; | 3747 | return -EIO; |
3333 | } | 3748 | } |
3334 | } | 3749 | } |
@@ -3341,10 +3756,12 @@ static int vino_v4l2_dqbuf(struct vino_channel_settings *vcs, | |||
3341 | } | 3756 | } |
3342 | 3757 | ||
3343 | err = vino_check_buffer(vcs, fb); | 3758 | err = vino_check_buffer(vcs, fb); |
3759 | |||
3760 | vino_v4l2_get_buffer_status(vcs, fb, b); | ||
3761 | |||
3344 | if (err) | 3762 | if (err) |
3345 | return -EIO; | 3763 | return -EIO; |
3346 | 3764 | ||
3347 | vino_v4l2_get_buffer_status(vcs, fb, b); | ||
3348 | break; | 3765 | break; |
3349 | } | 3766 | } |
3350 | case V4L2_BUF_TYPE_VIDEO_OVERLAY: | 3767 | case V4L2_BUF_TYPE_VIDEO_OVERLAY: |
@@ -3401,8 +3818,8 @@ static int vino_v4l2_streamoff(struct vino_channel_settings *vcs) | |||
3401 | if (!vcs->streaming) | 3818 | if (!vcs->streaming) |
3402 | return 0; | 3819 | return 0; |
3403 | 3820 | ||
3404 | vino_capture_stop(vcs); | ||
3405 | vcs->streaming = 0; | 3821 | vcs->streaming = 0; |
3822 | vino_capture_stop(vcs); | ||
3406 | 3823 | ||
3407 | return 0; | 3824 | return 0; |
3408 | } | 3825 | } |
@@ -3410,10 +3827,11 @@ static int vino_v4l2_streamoff(struct vino_channel_settings *vcs) | |||
3410 | static int vino_v4l2_queryctrl(struct vino_channel_settings *vcs, | 3827 | static int vino_v4l2_queryctrl(struct vino_channel_settings *vcs, |
3411 | struct v4l2_queryctrl *queryctrl) | 3828 | struct v4l2_queryctrl *queryctrl) |
3412 | { | 3829 | { |
3830 | unsigned long flags; | ||
3413 | int i; | 3831 | int i; |
3414 | int err = 0; | 3832 | int err = 0; |
3415 | 3833 | ||
3416 | spin_lock(&vino_drvdata->input_lock); | 3834 | spin_lock_irqsave(&vino_drvdata->input_lock, flags); |
3417 | 3835 | ||
3418 | switch (vcs->input) { | 3836 | switch (vcs->input) { |
3419 | case VINO_INPUT_D1: | 3837 | case VINO_INPUT_D1: |
@@ -3423,6 +3841,7 @@ static int vino_v4l2_queryctrl(struct vino_channel_settings *vcs, | |||
3423 | memcpy(queryctrl, | 3841 | memcpy(queryctrl, |
3424 | &vino_indycam_v4l2_controls[i], | 3842 | &vino_indycam_v4l2_controls[i], |
3425 | sizeof(struct v4l2_queryctrl)); | 3843 | sizeof(struct v4l2_queryctrl)); |
3844 | queryctrl->reserved[0] = 0; | ||
3426 | goto found; | 3845 | goto found; |
3427 | } | 3846 | } |
3428 | } | 3847 | } |
@@ -3437,6 +3856,7 @@ static int vino_v4l2_queryctrl(struct vino_channel_settings *vcs, | |||
3437 | memcpy(queryctrl, | 3856 | memcpy(queryctrl, |
3438 | &vino_saa7191_v4l2_controls[i], | 3857 | &vino_saa7191_v4l2_controls[i], |
3439 | sizeof(struct v4l2_queryctrl)); | 3858 | sizeof(struct v4l2_queryctrl)); |
3859 | queryctrl->reserved[0] = 0; | ||
3440 | goto found; | 3860 | goto found; |
3441 | } | 3861 | } |
3442 | } | 3862 | } |
@@ -3448,7 +3868,7 @@ static int vino_v4l2_queryctrl(struct vino_channel_settings *vcs, | |||
3448 | } | 3868 | } |
3449 | 3869 | ||
3450 | found: | 3870 | found: |
3451 | spin_unlock(&vino_drvdata->input_lock); | 3871 | spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); |
3452 | 3872 | ||
3453 | return err; | 3873 | return err; |
3454 | } | 3874 | } |
@@ -3456,70 +3876,72 @@ static int vino_v4l2_queryctrl(struct vino_channel_settings *vcs, | |||
3456 | static int vino_v4l2_g_ctrl(struct vino_channel_settings *vcs, | 3876 | static int vino_v4l2_g_ctrl(struct vino_channel_settings *vcs, |
3457 | struct v4l2_control *control) | 3877 | struct v4l2_control *control) |
3458 | { | 3878 | { |
3459 | struct indycam_control indycam_ctrl; | 3879 | unsigned long flags; |
3460 | struct saa7191_control saa7191_ctrl; | 3880 | int i; |
3461 | int err = 0; | 3881 | int err = 0; |
3462 | 3882 | ||
3463 | spin_lock(&vino_drvdata->input_lock); | 3883 | spin_lock_irqsave(&vino_drvdata->input_lock, flags); |
3464 | 3884 | ||
3465 | switch (vcs->input) { | 3885 | switch (vcs->input) { |
3466 | case VINO_INPUT_D1: | 3886 | case VINO_INPUT_D1: { |
3467 | i2c_camera_command(DECODER_INDYCAM_GET_CONTROLS, | 3887 | struct indycam_control indycam_ctrl; |
3468 | &indycam_ctrl); | ||
3469 | 3888 | ||
3470 | switch(control->id) { | 3889 | for (i = 0; i < VINO_INDYCAM_V4L2_CONTROL_COUNT; i++) { |
3471 | case V4L2_CID_AUTOGAIN: | 3890 | if (vino_indycam_v4l2_controls[i].id == |
3472 | control->value = indycam_ctrl.agc; | 3891 | control->id) { |
3473 | break; | 3892 | goto found1; |
3474 | case V4L2_CID_AUTO_WHITE_BALANCE: | 3893 | } |
3475 | control->value = indycam_ctrl.awb; | 3894 | } |
3476 | break; | 3895 | |
3477 | case V4L2_CID_GAIN: | 3896 | err = -EINVAL; |
3478 | control->value = indycam_ctrl.gain; | 3897 | goto out; |
3479 | break; | 3898 | |
3480 | case V4L2_CID_PRIVATE_BASE: | 3899 | found1: |
3481 | control->value = indycam_ctrl.red_saturation; | 3900 | indycam_ctrl.type = vino_indycam_v4l2_controls[i].reserved[0]; |
3482 | break; | 3901 | |
3483 | case V4L2_CID_PRIVATE_BASE + 1: | 3902 | err = i2c_camera_command(DECODER_INDYCAM_GET_CONTROL, |
3484 | control->value = indycam_ctrl.blue_saturation; | 3903 | &indycam_ctrl); |
3485 | break; | 3904 | if (err) { |
3486 | case V4L2_CID_RED_BALANCE: | ||
3487 | control->value = indycam_ctrl.red_balance; | ||
3488 | break; | ||
3489 | case V4L2_CID_BLUE_BALANCE: | ||
3490 | control->value = indycam_ctrl.blue_balance; | ||
3491 | break; | ||
3492 | case V4L2_CID_EXPOSURE: | ||
3493 | control->value = indycam_ctrl.shutter; | ||
3494 | break; | ||
3495 | case V4L2_CID_GAMMA: | ||
3496 | control->value = indycam_ctrl.gamma; | ||
3497 | break; | ||
3498 | default: | ||
3499 | err = -EINVAL; | 3905 | err = -EINVAL; |
3906 | goto out; | ||
3500 | } | 3907 | } |
3908 | |||
3909 | control->value = indycam_ctrl.value; | ||
3501 | break; | 3910 | break; |
3911 | } | ||
3502 | case VINO_INPUT_COMPOSITE: | 3912 | case VINO_INPUT_COMPOSITE: |
3503 | case VINO_INPUT_SVIDEO: | 3913 | case VINO_INPUT_SVIDEO: { |
3504 | i2c_decoder_command(DECODER_SAA7191_GET_CONTROLS, | 3914 | struct saa7191_control saa7191_ctrl; |
3505 | &saa7191_ctrl); | ||
3506 | 3915 | ||
3507 | switch(control->id) { | 3916 | for (i = 0; i < VINO_SAA7191_V4L2_CONTROL_COUNT; i++) { |
3508 | case V4L2_CID_HUE: | 3917 | if (vino_saa7191_v4l2_controls[i].id == |
3509 | control->value = saa7191_ctrl.hue; | 3918 | control->id) { |
3510 | break; | 3919 | goto found2; |
3511 | case V4L2_CID_PRIVATE_BASE: | 3920 | } |
3512 | control->value = saa7191_ctrl.vtrc; | 3921 | } |
3513 | break; | 3922 | |
3514 | default: | 3923 | err = -EINVAL; |
3924 | goto out; | ||
3925 | |||
3926 | found2: | ||
3927 | saa7191_ctrl.type = vino_saa7191_v4l2_controls[i].reserved[0]; | ||
3928 | |||
3929 | err = i2c_decoder_command(DECODER_SAA7191_GET_CONTROL, | ||
3930 | &saa7191_ctrl); | ||
3931 | if (err) { | ||
3515 | err = -EINVAL; | 3932 | err = -EINVAL; |
3933 | goto out; | ||
3516 | } | 3934 | } |
3935 | |||
3936 | control->value = saa7191_ctrl.value; | ||
3517 | break; | 3937 | break; |
3938 | } | ||
3518 | default: | 3939 | default: |
3519 | err = -EINVAL; | 3940 | err = -EINVAL; |
3520 | } | 3941 | } |
3521 | 3942 | ||
3522 | spin_unlock(&vino_drvdata->input_lock); | 3943 | out: |
3944 | spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); | ||
3523 | 3945 | ||
3524 | return err; | 3946 | return err; |
3525 | } | 3947 | } |
@@ -3527,15 +3949,21 @@ static int vino_v4l2_g_ctrl(struct vino_channel_settings *vcs, | |||
3527 | static int vino_v4l2_s_ctrl(struct vino_channel_settings *vcs, | 3949 | static int vino_v4l2_s_ctrl(struct vino_channel_settings *vcs, |
3528 | struct v4l2_control *control) | 3950 | struct v4l2_control *control) |
3529 | { | 3951 | { |
3530 | struct indycam_control indycam_ctrl; | 3952 | unsigned long flags; |
3531 | struct saa7191_control saa7191_ctrl; | ||
3532 | int i; | 3953 | int i; |
3533 | int err = 0; | 3954 | int err = 0; |
3534 | 3955 | ||
3535 | spin_lock(&vino_drvdata->input_lock); | 3956 | spin_lock_irqsave(&vino_drvdata->input_lock, flags); |
3957 | |||
3958 | if (!vino_is_input_owner(vcs)) { | ||
3959 | err = -EBUSY; | ||
3960 | goto out; | ||
3961 | } | ||
3536 | 3962 | ||
3537 | switch (vcs->input) { | 3963 | switch (vcs->input) { |
3538 | case VINO_INPUT_D1: | 3964 | case VINO_INPUT_D1: { |
3965 | struct indycam_control indycam_ctrl; | ||
3966 | |||
3539 | for (i = 0; i < VINO_INDYCAM_V4L2_CONTROL_COUNT; i++) { | 3967 | for (i = 0; i < VINO_INDYCAM_V4L2_CONTROL_COUNT; i++) { |
3540 | if (vino_indycam_v4l2_controls[i].id == | 3968 | if (vino_indycam_v4l2_controls[i].id == |
3541 | control->id) { | 3969 | control->id) { |
@@ -3544,65 +3972,31 @@ static int vino_v4l2_s_ctrl(struct vino_channel_settings *vcs, | |||
3544 | && (control->value <= | 3972 | && (control->value <= |
3545 | vino_indycam_v4l2_controls[i]. | 3973 | vino_indycam_v4l2_controls[i]. |
3546 | maximum)) { | 3974 | maximum)) { |
3547 | goto ok1; | 3975 | goto found1; |
3548 | } else { | 3976 | } else { |
3549 | err = -ERANGE; | 3977 | err = -ERANGE; |
3550 | goto error; | 3978 | goto out; |
3551 | } | 3979 | } |
3552 | } | 3980 | } |
3553 | } | 3981 | } |
3982 | |||
3554 | err = -EINVAL; | 3983 | err = -EINVAL; |
3555 | goto error; | 3984 | goto out; |
3556 | 3985 | ||
3557 | ok1: | 3986 | found1: |
3558 | indycam_ctrl.agc = INDYCAM_VALUE_UNCHANGED; | 3987 | indycam_ctrl.type = vino_indycam_v4l2_controls[i].reserved[0]; |
3559 | indycam_ctrl.awb = INDYCAM_VALUE_UNCHANGED; | 3988 | indycam_ctrl.value = control->value; |
3560 | indycam_ctrl.shutter = INDYCAM_VALUE_UNCHANGED; | ||
3561 | indycam_ctrl.gain = INDYCAM_VALUE_UNCHANGED; | ||
3562 | indycam_ctrl.red_balance = INDYCAM_VALUE_UNCHANGED; | ||
3563 | indycam_ctrl.blue_balance = INDYCAM_VALUE_UNCHANGED; | ||
3564 | indycam_ctrl.red_saturation = INDYCAM_VALUE_UNCHANGED; | ||
3565 | indycam_ctrl.blue_saturation = INDYCAM_VALUE_UNCHANGED; | ||
3566 | indycam_ctrl.gamma = INDYCAM_VALUE_UNCHANGED; | ||
3567 | |||
3568 | switch(control->id) { | ||
3569 | case V4L2_CID_AUTOGAIN: | ||
3570 | indycam_ctrl.agc = control->value; | ||
3571 | break; | ||
3572 | case V4L2_CID_AUTO_WHITE_BALANCE: | ||
3573 | indycam_ctrl.awb = control->value; | ||
3574 | break; | ||
3575 | case V4L2_CID_GAIN: | ||
3576 | indycam_ctrl.gain = control->value; | ||
3577 | break; | ||
3578 | case V4L2_CID_PRIVATE_BASE: | ||
3579 | indycam_ctrl.red_saturation = control->value; | ||
3580 | break; | ||
3581 | case V4L2_CID_PRIVATE_BASE + 1: | ||
3582 | indycam_ctrl.blue_saturation = control->value; | ||
3583 | break; | ||
3584 | case V4L2_CID_RED_BALANCE: | ||
3585 | indycam_ctrl.red_balance = control->value; | ||
3586 | break; | ||
3587 | case V4L2_CID_BLUE_BALANCE: | ||
3588 | indycam_ctrl.blue_balance = control->value; | ||
3589 | break; | ||
3590 | case V4L2_CID_EXPOSURE: | ||
3591 | indycam_ctrl.shutter = control->value; | ||
3592 | break; | ||
3593 | case V4L2_CID_GAMMA: | ||
3594 | indycam_ctrl.gamma = control->value; | ||
3595 | break; | ||
3596 | default: | ||
3597 | err = -EINVAL; | ||
3598 | } | ||
3599 | 3989 | ||
3600 | if (!err) | 3990 | err = i2c_camera_command(DECODER_INDYCAM_SET_CONTROL, |
3601 | i2c_camera_command(DECODER_INDYCAM_SET_CONTROLS, | 3991 | &indycam_ctrl); |
3602 | &indycam_ctrl); | 3992 | if (err) |
3993 | err = -EINVAL; | ||
3603 | break; | 3994 | break; |
3995 | } | ||
3604 | case VINO_INPUT_COMPOSITE: | 3996 | case VINO_INPUT_COMPOSITE: |
3605 | case VINO_INPUT_SVIDEO: | 3997 | case VINO_INPUT_SVIDEO: { |
3998 | struct saa7191_control saa7191_ctrl; | ||
3999 | |||
3606 | for (i = 0; i < VINO_SAA7191_V4L2_CONTROL_COUNT; i++) { | 4000 | for (i = 0; i < VINO_SAA7191_V4L2_CONTROL_COUNT; i++) { |
3607 | if (vino_saa7191_v4l2_controls[i].id == | 4001 | if (vino_saa7191_v4l2_controls[i].id == |
3608 | control->id) { | 4002 | control->id) { |
@@ -3611,41 +4005,32 @@ ok1: | |||
3611 | && (control->value <= | 4005 | && (control->value <= |
3612 | vino_saa7191_v4l2_controls[i]. | 4006 | vino_saa7191_v4l2_controls[i]. |
3613 | maximum)) { | 4007 | maximum)) { |
3614 | goto ok2; | 4008 | goto found2; |
3615 | } else { | 4009 | } else { |
3616 | err = -ERANGE; | 4010 | err = -ERANGE; |
3617 | goto error; | 4011 | goto out; |
3618 | } | 4012 | } |
3619 | } | 4013 | } |
3620 | } | 4014 | } |
3621 | err = -EINVAL; | 4015 | err = -EINVAL; |
3622 | goto error; | 4016 | goto out; |
3623 | |||
3624 | ok2: | ||
3625 | saa7191_ctrl.hue = SAA7191_VALUE_UNCHANGED; | ||
3626 | saa7191_ctrl.vtrc = SAA7191_VALUE_UNCHANGED; | ||
3627 | 4017 | ||
3628 | switch(control->id) { | 4018 | found2: |
3629 | case V4L2_CID_HUE: | 4019 | saa7191_ctrl.type = vino_saa7191_v4l2_controls[i].reserved[0]; |
3630 | saa7191_ctrl.hue = control->value; | 4020 | saa7191_ctrl.value = control->value; |
3631 | break; | ||
3632 | case V4L2_CID_PRIVATE_BASE: | ||
3633 | saa7191_ctrl.vtrc = control->value; | ||
3634 | break; | ||
3635 | default: | ||
3636 | err = -EINVAL; | ||
3637 | } | ||
3638 | 4021 | ||
3639 | if (!err) | 4022 | err = i2c_decoder_command(DECODER_SAA7191_SET_CONTROL, |
3640 | i2c_decoder_command(DECODER_SAA7191_SET_CONTROLS, | 4023 | &saa7191_ctrl); |
3641 | &saa7191_ctrl); | 4024 | if (err) |
4025 | err = -EINVAL; | ||
3642 | break; | 4026 | break; |
4027 | } | ||
3643 | default: | 4028 | default: |
3644 | err = -EINVAL; | 4029 | err = -EINVAL; |
3645 | } | 4030 | } |
3646 | 4031 | ||
3647 | error: | 4032 | out: |
3648 | spin_unlock(&vino_drvdata->input_lock); | 4033 | spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); |
3649 | 4034 | ||
3650 | return err; | 4035 | return err; |
3651 | } | 4036 | } |
@@ -3865,9 +4250,9 @@ static unsigned int vino_poll(struct file *file, poll_table *pt) | |||
3865 | over: | 4250 | over: |
3866 | dprintk("poll(): data %savailable\n", | 4251 | dprintk("poll(): data %savailable\n", |
3867 | (outgoing > 0) ? "" : "not "); | 4252 | (outgoing > 0) ? "" : "not "); |
3868 | if (outgoing > 0) { | 4253 | |
4254 | if (outgoing > 0) | ||
3869 | ret = POLLIN | POLLRDNORM; | 4255 | ret = POLLIN | POLLRDNORM; |
3870 | } | ||
3871 | 4256 | ||
3872 | error: | 4257 | error: |
3873 | 4258 | ||
@@ -3880,6 +4265,7 @@ static int vino_do_ioctl(struct inode *inode, struct file *file, | |||
3880 | struct video_device *dev = video_devdata(file); | 4265 | struct video_device *dev = video_devdata(file); |
3881 | struct vino_channel_settings *vcs = video_get_drvdata(dev); | 4266 | struct vino_channel_settings *vcs = video_get_drvdata(dev); |
3882 | 4267 | ||
4268 | #ifdef VINO_DEBUG | ||
3883 | switch (_IOC_TYPE(cmd)) { | 4269 | switch (_IOC_TYPE(cmd)) { |
3884 | case 'v': | 4270 | case 'v': |
3885 | dprintk("ioctl(): V4L1 unsupported (0x%08x)\n", cmd); | 4271 | dprintk("ioctl(): V4L1 unsupported (0x%08x)\n", cmd); |
@@ -3891,9 +4277,9 @@ static int vino_do_ioctl(struct inode *inode, struct file *file, | |||
3891 | default: | 4277 | default: |
3892 | dprintk("ioctl(): unsupported command 0x%08x\n", cmd); | 4278 | dprintk("ioctl(): unsupported command 0x%08x\n", cmd); |
3893 | } | 4279 | } |
4280 | #endif | ||
3894 | 4281 | ||
3895 | switch (cmd) { | 4282 | switch (cmd) { |
3896 | /* TODO: V4L1 interface (use compatibility layer?) */ | ||
3897 | /* V4L2 interface */ | 4283 | /* V4L2 interface */ |
3898 | case VIDIOC_QUERYCAP: { | 4284 | case VIDIOC_QUERYCAP: { |
3899 | vino_v4l2_querycap(arg); | 4285 | vino_v4l2_querycap(arg); |
@@ -3911,6 +4297,9 @@ static int vino_do_ioctl(struct inode *inode, struct file *file, | |||
3911 | case VIDIOC_ENUMSTD: { | 4297 | case VIDIOC_ENUMSTD: { |
3912 | return vino_v4l2_enumstd(vcs, arg); | 4298 | return vino_v4l2_enumstd(vcs, arg); |
3913 | } | 4299 | } |
4300 | case VIDIOC_QUERYSTD: { | ||
4301 | return vino_v4l2_querystd(vcs, arg); | ||
4302 | } | ||
3914 | case VIDIOC_G_STD: { | 4303 | case VIDIOC_G_STD: { |
3915 | return vino_v4l2_g_std(vcs, arg); | 4304 | return vino_v4l2_g_std(vcs, arg); |
3916 | } | 4305 | } |
@@ -4100,8 +4489,7 @@ static int vino_probe(void) | |||
4100 | return -ENODEV; | 4489 | return -ENODEV; |
4101 | } | 4490 | } |
4102 | 4491 | ||
4103 | printk(KERN_INFO "VINO with chip ID %ld, revision %ld found\n", | 4492 | printk(KERN_INFO "VINO revision %ld found\n", VINO_REV_NUM(rev_id)); |
4104 | VINO_ID_VALUE(rev_id), VINO_REV_NUM(rev_id)); | ||
4105 | 4493 | ||
4106 | return 0; | 4494 | return 0; |
4107 | } | 4495 | } |
diff --git a/drivers/tc/.gitignore b/drivers/tc/.gitignore new file mode 100644 index 000000000000..acc0e1e6a650 --- /dev/null +++ b/drivers/tc/.gitignore | |||
@@ -0,0 +1 @@ | |||
lk201-map.c | |||
diff --git a/include/asm-mips/.gitignore b/include/asm-mips/.gitignore new file mode 100644 index 000000000000..4ec57ad5bc3c --- /dev/null +++ b/include/asm-mips/.gitignore | |||
@@ -0,0 +1 @@ | |||
asm_offsets.h | |||
diff --git a/include/asm-mips/delay.h b/include/asm-mips/delay.h index 85435a8d4e52..48d00cccdafa 100644 --- a/include/asm-mips/delay.h +++ b/include/asm-mips/delay.h | |||
@@ -84,4 +84,13 @@ static inline void __udelay(unsigned long usecs, unsigned long lpj) | |||
84 | 84 | ||
85 | #define udelay(usecs) __udelay((usecs),__udelay_val) | 85 | #define udelay(usecs) __udelay((usecs),__udelay_val) |
86 | 86 | ||
87 | /* make sure "usecs *= ..." in udelay do not overflow. */ | ||
88 | #if HZ >= 1000 | ||
89 | #define MAX_UDELAY_MS 1 | ||
90 | #elif HZ <= 200 | ||
91 | #define MAX_UDELAY_MS 5 | ||
92 | #else | ||
93 | #define MAX_UDELAY_MS (1000 / HZ) | ||
94 | #endif | ||
95 | |||
87 | #endif /* _ASM_DELAY_H */ | 96 | #endif /* _ASM_DELAY_H */ |
diff --git a/include/asm-mips/errno.h b/include/asm-mips/errno.h index 9d3e6e7cdb92..3c0d840e4577 100644 --- a/include/asm-mips/errno.h +++ b/include/asm-mips/errno.h | |||
@@ -119,10 +119,6 @@ | |||
119 | #define EOWNERDEAD 165 /* Owner died */ | 119 | #define EOWNERDEAD 165 /* Owner died */ |
120 | #define ENOTRECOVERABLE 166 /* State not recoverable */ | 120 | #define ENOTRECOVERABLE 166 /* State not recoverable */ |
121 | 121 | ||
122 | /* for robust mutexes */ | ||
123 | #define EOWNERDEAD 165 /* Owner died */ | ||
124 | #define ENOTRECOVERABLE 166 /* State not recoverable */ | ||
125 | |||
126 | #define EDQUOT 1133 /* Quota exceeded */ | 122 | #define EDQUOT 1133 /* Quota exceeded */ |
127 | 123 | ||
128 | #ifdef __KERNEL__ | 124 | #ifdef __KERNEL__ |
diff --git a/include/asm-mips/ip32/mace.h b/include/asm-mips/ip32/mace.h index 432011b16c26..5bdc51d85b6c 100644 --- a/include/asm-mips/ip32/mace.h +++ b/include/asm-mips/ip32/mace.h | |||
@@ -147,6 +147,29 @@ struct mace_audio { | |||
147 | } chan[3]; | 147 | } chan[3]; |
148 | }; | 148 | }; |
149 | 149 | ||
150 | |||
151 | /* register definitions for parallel port DMA */ | ||
152 | struct mace_parport { | ||
153 | /* 0 - do nothing, 1 - pulse terminal count to the device after buffer is drained */ | ||
154 | #define MACEPAR_CONTEXT_LASTFLAG BIT(63) | ||
155 | /* Should not cross 4K page boundary */ | ||
156 | #define MACEPAR_CONTEXT_DATALEN_MASK 0xfff00000000 | ||
157 | /* Can be arbitrarily aligned on any byte boundary on output, 64 byte aligned on input */ | ||
158 | #define MACEPAR_CONTEXT_BASEADDR_MASK 0xffffffff | ||
159 | volatile u64 context_a; | ||
160 | volatile u64 context_b; | ||
161 | #define MACEPAR_CTLSTAT_DIRECTION BIT(0) /* 0 - mem->device, 1 - device->mem */ | ||
162 | #define MACEPAR_CTLSTAT_ENABLE BIT(1) /* 0 - channel frozen, 1 - channel enabled */ | ||
163 | #define MACEPAR_CTLSTAT_RESET BIT(2) /* 0 - channel active, 1 - complete channel reset */ | ||
164 | #define MACEPAR_CTLSTAT_CTXB_VALID BIT(3) | ||
165 | #define MACEPAR_CTLSTAT_CTXA_VALID BIT(4) | ||
166 | volatile u64 cntlstat; /* Control/Status register */ | ||
167 | #define MACEPAR_DIAG_CTXINUSE BIT(1) | ||
168 | #define MACEPAR_DIAG_DMACTIVE BIT(2) /* 1 - Dma engine is enabled and processing something */ | ||
169 | #define MACEPAR_DIAG_CTRMASK 0x3ffc /* Counter of bytes left */ | ||
170 | volatile u64 diagnostic; /* RO: diagnostic register */ | ||
171 | }; | ||
172 | |||
150 | /* ISA Control and DMA registers */ | 173 | /* ISA Control and DMA registers */ |
151 | struct mace_isactrl { | 174 | struct mace_isactrl { |
152 | volatile unsigned long ringbase; | 175 | volatile unsigned long ringbase; |
@@ -199,6 +222,7 @@ struct mace_isactrl { | |||
199 | volatile unsigned long _pad[0x2000/8 - 4]; | 222 | volatile unsigned long _pad[0x2000/8 - 4]; |
200 | 223 | ||
201 | volatile unsigned long dp_ram[0x400]; | 224 | volatile unsigned long dp_ram[0x400]; |
225 | struct mace_parport parport; | ||
202 | }; | 226 | }; |
203 | 227 | ||
204 | /* Keyboard & Mouse registers | 228 | /* Keyboard & Mouse registers |
@@ -277,7 +301,7 @@ struct mace_perif { | |||
277 | */ | 301 | */ |
278 | 302 | ||
279 | /* Parallel port */ | 303 | /* Parallel port */ |
280 | struct mace_parallel { /* later... */ | 304 | struct mace_parallel { |
281 | }; | 305 | }; |
282 | 306 | ||
283 | struct mace_ecp1284 { /* later... */ | 307 | struct mace_ecp1284 { /* later... */ |
diff --git a/include/asm-mips/mach-generic/ide.h b/include/asm-mips/mach-generic/ide.h index 961006948c7c..550979a9ea9d 100644 --- a/include/asm-mips/mach-generic/ide.h +++ b/include/asm-mips/mach-generic/ide.h | |||
@@ -168,8 +168,12 @@ static inline void __ide_mm_outsl(void __iomem * port, void *addr, u32 count) | |||
168 | /* ide_insw calls insw, not __ide_insw. Why? */ | 168 | /* ide_insw calls insw, not __ide_insw. Why? */ |
169 | #undef insw | 169 | #undef insw |
170 | #undef insl | 170 | #undef insl |
171 | #undef outsw | ||
172 | #undef outsl | ||
171 | #define insw(port, addr, count) __ide_insw(port, addr, count) | 173 | #define insw(port, addr, count) __ide_insw(port, addr, count) |
172 | #define insl(port, addr, count) __ide_insl(port, addr, count) | 174 | #define insl(port, addr, count) __ide_insl(port, addr, count) |
175 | #define outsw(port, addr, count) __ide_outsw(port, addr, count) | ||
176 | #define outsl(port, addr, count) __ide_outsl(port, addr, count) | ||
173 | 177 | ||
174 | #endif /* __KERNEL__ */ | 178 | #endif /* __KERNEL__ */ |
175 | 179 | ||
diff --git a/include/asm-mips/mc146818-time.h b/include/asm-mips/mc146818-time.h index a2c2d2c24303..47214861093b 100644 --- a/include/asm-mips/mc146818-time.h +++ b/include/asm-mips/mc146818-time.h | |||
@@ -33,7 +33,9 @@ static inline int mc146818_set_rtc_mmss(unsigned long nowtime) | |||
33 | int real_seconds, real_minutes, cmos_minutes; | 33 | int real_seconds, real_minutes, cmos_minutes; |
34 | unsigned char save_control, save_freq_select; | 34 | unsigned char save_control, save_freq_select; |
35 | int retval = 0; | 35 | int retval = 0; |
36 | unsigned long flags; | ||
36 | 37 | ||
38 | spin_lock_irqsave(&rtc_lock, flags); | ||
37 | save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */ | 39 | save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */ |
38 | CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL); | 40 | CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL); |
39 | 41 | ||
@@ -79,14 +81,30 @@ static inline int mc146818_set_rtc_mmss(unsigned long nowtime) | |||
79 | */ | 81 | */ |
80 | CMOS_WRITE(save_control, RTC_CONTROL); | 82 | CMOS_WRITE(save_control, RTC_CONTROL); |
81 | CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); | 83 | CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); |
84 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
82 | 85 | ||
83 | return retval; | 86 | return retval; |
84 | } | 87 | } |
85 | 88 | ||
89 | /* | ||
90 | * Returns true if a clock update is in progress | ||
91 | */ | ||
92 | static inline unsigned char rtc_is_updating(void) | ||
93 | { | ||
94 | unsigned char uip; | ||
95 | unsigned long flags; | ||
96 | |||
97 | spin_lock_irqsave(&rtc_lock, flags); | ||
98 | uip = (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP); | ||
99 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
100 | return uip; | ||
101 | } | ||
102 | |||
86 | static inline unsigned long mc146818_get_cmos_time(void) | 103 | static inline unsigned long mc146818_get_cmos_time(void) |
87 | { | 104 | { |
88 | unsigned int year, mon, day, hour, min, sec; | 105 | unsigned int year, mon, day, hour, min, sec; |
89 | int i; | 106 | int i; |
107 | unsigned long flags; | ||
90 | 108 | ||
91 | /* | 109 | /* |
92 | * The Linux interpretation of the CMOS clock register contents: | 110 | * The Linux interpretation of the CMOS clock register contents: |
@@ -97,12 +115,13 @@ static inline unsigned long mc146818_get_cmos_time(void) | |||
97 | 115 | ||
98 | /* read RTC exactly on falling edge of update flag */ | 116 | /* read RTC exactly on falling edge of update flag */ |
99 | for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */ | 117 | for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */ |
100 | if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP) | 118 | if (rtc_is_updating()) |
101 | break; | 119 | break; |
102 | for (i = 0 ; i < 1000000 ; i++) /* must try at least 2.228 ms */ | 120 | for (i = 0 ; i < 1000000 ; i++) /* must try at least 2.228 ms */ |
103 | if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)) | 121 | if (!rtc_is_updating()) |
104 | break; | 122 | break; |
105 | 123 | ||
124 | spin_lock_irqsave(&rtc_lock, flags); | ||
106 | do { /* Isn't this overkill ? UIP above should guarantee consistency */ | 125 | do { /* Isn't this overkill ? UIP above should guarantee consistency */ |
107 | sec = CMOS_READ(RTC_SECONDS); | 126 | sec = CMOS_READ(RTC_SECONDS); |
108 | min = CMOS_READ(RTC_MINUTES); | 127 | min = CMOS_READ(RTC_MINUTES); |
@@ -120,6 +139,7 @@ static inline unsigned long mc146818_get_cmos_time(void) | |||
120 | BCD_TO_BIN(mon); | 139 | BCD_TO_BIN(mon); |
121 | BCD_TO_BIN(year); | 140 | BCD_TO_BIN(year); |
122 | } | 141 | } |
142 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
123 | year = mc146818_decode_year(year); | 143 | year = mc146818_decode_year(year); |
124 | 144 | ||
125 | return mktime(year, mon, day, hour, min, sec); | 145 | return mktime(year, mon, day, hour, min, sec); |
diff --git a/include/asm-mips/module.h b/include/asm-mips/module.h index 2be399311eec..2af496c78c12 100644 --- a/include/asm-mips/module.h +++ b/include/asm-mips/module.h | |||
@@ -76,43 +76,43 @@ search_module_dbetables(unsigned long addr) | |||
76 | #endif | 76 | #endif |
77 | 77 | ||
78 | #ifdef CONFIG_CPU_MIPS32_R1 | 78 | #ifdef CONFIG_CPU_MIPS32_R1 |
79 | #define MODULE_PROC_FAMILY "MIPS32_R1" | 79 | #define MODULE_PROC_FAMILY "MIPS32_R1 " |
80 | #elif defined CONFIG_CPU_MIPS32_R2 | 80 | #elif defined CONFIG_CPU_MIPS32_R2 |
81 | #define MODULE_PROC_FAMILY "MIPS32_R2" | 81 | #define MODULE_PROC_FAMILY "MIPS32_R2 " |
82 | #elif defined CONFIG_CPU_MIPS64_R1 | 82 | #elif defined CONFIG_CPU_MIPS64_R1 |
83 | #define MODULE_PROC_FAMILY "MIPS64_R1" | 83 | #define MODULE_PROC_FAMILY "MIPS64_R1 " |
84 | #elif defined CONFIG_CPU_MIPS64_R2 | 84 | #elif defined CONFIG_CPU_MIPS64_R2 |
85 | #define MODULE_PROC_FAMILY "MIPS64_R2" | 85 | #define MODULE_PROC_FAMILY "MIPS64_R2 " |
86 | #elif defined CONFIG_CPU_R3000 | 86 | #elif defined CONFIG_CPU_R3000 |
87 | #define MODULE_PROC_FAMILY "R3000" | 87 | #define MODULE_PROC_FAMILY "R3000 " |
88 | #elif defined CONFIG_CPU_TX39XX | 88 | #elif defined CONFIG_CPU_TX39XX |
89 | #define MODULE_PROC_FAMILY "TX39XX" | 89 | #define MODULE_PROC_FAMILY "TX39XX " |
90 | #elif defined CONFIG_CPU_VR41XX | 90 | #elif defined CONFIG_CPU_VR41XX |
91 | #define MODULE_PROC_FAMILY "VR41XX" | 91 | #define MODULE_PROC_FAMILY "VR41XX " |
92 | #elif defined CONFIG_CPU_R4300 | 92 | #elif defined CONFIG_CPU_R4300 |
93 | #define MODULE_PROC_FAMILY "R4300" | 93 | #define MODULE_PROC_FAMILY "R4300 " |
94 | #elif defined CONFIG_CPU_R4X00 | 94 | #elif defined CONFIG_CPU_R4X00 |
95 | #define MODULE_PROC_FAMILY "R4X00" | 95 | #define MODULE_PROC_FAMILY "R4X00 " |
96 | #elif defined CONFIG_CPU_TX49XX | 96 | #elif defined CONFIG_CPU_TX49XX |
97 | #define MODULE_PROC_FAMILY "TX49XX" | 97 | #define MODULE_PROC_FAMILY "TX49XX " |
98 | #elif defined CONFIG_CPU_R5000 | 98 | #elif defined CONFIG_CPU_R5000 |
99 | #define MODULE_PROC_FAMILY "R5000" | 99 | #define MODULE_PROC_FAMILY "R5000 " |
100 | #elif defined CONFIG_CPU_R5432 | 100 | #elif defined CONFIG_CPU_R5432 |
101 | #define MODULE_PROC_FAMILY "R5432" | 101 | #define MODULE_PROC_FAMILY "R5432 " |
102 | #elif defined CONFIG_CPU_R6000 | 102 | #elif defined CONFIG_CPU_R6000 |
103 | #define MODULE_PROC_FAMILY "R6000" | 103 | #define MODULE_PROC_FAMILY "R6000 " |
104 | #elif defined CONFIG_CPU_NEVADA | 104 | #elif defined CONFIG_CPU_NEVADA |
105 | #define MODULE_PROC_FAMILY "NEVADA" | 105 | #define MODULE_PROC_FAMILY "NEVADA " |
106 | #elif defined CONFIG_CPU_R8000 | 106 | #elif defined CONFIG_CPU_R8000 |
107 | #define MODULE_PROC_FAMILY "R8000" | 107 | #define MODULE_PROC_FAMILY "R8000 " |
108 | #elif defined CONFIG_CPU_R10000 | 108 | #elif defined CONFIG_CPU_R10000 |
109 | #define MODULE_PROC_FAMILY "R10000" | 109 | #define MODULE_PROC_FAMILY "R10000 " |
110 | #elif defined CONFIG_CPU_RM7000 | 110 | #elif defined CONFIG_CPU_RM7000 |
111 | #define MODULE_PROC_FAMILY "RM7000" | 111 | #define MODULE_PROC_FAMILY "RM7000 " |
112 | #elif defined CONFIG_CPU_RM9000 | 112 | #elif defined CONFIG_CPU_RM9000 |
113 | #define MODULE_PROC_FAMILY "RM9000" | 113 | #define MODULE_PROC_FAMILY "RM9000 " |
114 | #elif defined CONFIG_CPU_SB1 | 114 | #elif defined CONFIG_CPU_SB1 |
115 | #define MODULE_PROC_FAMILY "SB1" | 115 | #define MODULE_PROC_FAMILY "SB1 " |
116 | #else | 116 | #else |
117 | #error MODULE_PROC_FAMILY undefined for your processor configuration | 117 | #error MODULE_PROC_FAMILY undefined for your processor configuration |
118 | #endif | 118 | #endif |
diff --git a/include/asm-mips/rtc.h b/include/asm-mips/rtc.h index a60e0dc7c9b9..a2abc4572b63 100644 --- a/include/asm-mips/rtc.h +++ b/include/asm-mips/rtc.h | |||
@@ -14,7 +14,6 @@ | |||
14 | 14 | ||
15 | #ifdef __KERNEL__ | 15 | #ifdef __KERNEL__ |
16 | 16 | ||
17 | #include <linux/spinlock.h> | ||
18 | #include <linux/rtc.h> | 17 | #include <linux/rtc.h> |
19 | #include <asm/time.h> | 18 | #include <asm/time.h> |
20 | 19 | ||
@@ -29,17 +28,13 @@ | |||
29 | #define RTC_24H 0x02 /* 24 hour mode - else hours bit 7 means pm */ | 28 | #define RTC_24H 0x02 /* 24 hour mode - else hours bit 7 means pm */ |
30 | #define RTC_DST_EN 0x01 /* auto switch DST - works f. USA only */ | 29 | #define RTC_DST_EN 0x01 /* auto switch DST - works f. USA only */ |
31 | 30 | ||
32 | static DEFINE_SPINLOCK(mips_rtc_lock); | ||
33 | |||
34 | static inline unsigned int get_rtc_time(struct rtc_time *time) | 31 | static inline unsigned int get_rtc_time(struct rtc_time *time) |
35 | { | 32 | { |
36 | unsigned long nowtime; | 33 | unsigned long nowtime; |
37 | 34 | ||
38 | spin_lock(&mips_rtc_lock); | ||
39 | nowtime = rtc_get_time(); | 35 | nowtime = rtc_get_time(); |
40 | to_tm(nowtime, time); | 36 | to_tm(nowtime, time); |
41 | time->tm_year -= 1900; | 37 | time->tm_year -= 1900; |
42 | spin_unlock(&mips_rtc_lock); | ||
43 | 38 | ||
44 | return RTC_24H; | 39 | return RTC_24H; |
45 | } | 40 | } |
@@ -49,12 +44,10 @@ static inline int set_rtc_time(struct rtc_time *time) | |||
49 | unsigned long nowtime; | 44 | unsigned long nowtime; |
50 | int ret; | 45 | int ret; |
51 | 46 | ||
52 | spin_lock(&mips_rtc_lock); | ||
53 | nowtime = mktime(time->tm_year+1900, time->tm_mon+1, | 47 | nowtime = mktime(time->tm_year+1900, time->tm_mon+1, |
54 | time->tm_mday, time->tm_hour, time->tm_min, | 48 | time->tm_mday, time->tm_hour, time->tm_min, |
55 | time->tm_sec); | 49 | time->tm_sec); |
56 | ret = rtc_set_time(nowtime); | 50 | ret = rtc_set_time(nowtime); |
57 | spin_unlock(&mips_rtc_lock); | ||
58 | 51 | ||
59 | return ret; | 52 | return ret; |
60 | } | 53 | } |
diff --git a/include/asm-mips/rtlx.h b/include/asm-mips/rtlx.h index 83cdf6ab0d1f..1298c3fdf6c9 100644 --- a/include/asm-mips/rtlx.h +++ b/include/asm-mips/rtlx.h | |||
@@ -16,21 +16,19 @@ | |||
16 | #define RTLX_ID (RTLX_xID | RTLX_VERSION) | 16 | #define RTLX_ID (RTLX_xID | RTLX_VERSION) |
17 | #define RTLX_CHANNELS 8 | 17 | #define RTLX_CHANNELS 8 |
18 | 18 | ||
19 | enum rtlx_state { | ||
20 | RTLX_STATE_UNUSED = 0, | ||
21 | RTLX_STATE_INITIALISED, | ||
22 | RTLX_STATE_REMOTE_READY, | ||
23 | RTLX_STATE_OPENED | ||
24 | }; | ||
25 | |||
26 | #define RTLX_BUFFER_SIZE 1024 | 19 | #define RTLX_BUFFER_SIZE 1024 |
20 | |||
21 | /* | ||
22 | * lx_state bits | ||
23 | */ | ||
24 | #define RTLX_STATE_OPENED 1UL | ||
25 | |||
27 | /* each channel supports read and write. | 26 | /* each channel supports read and write. |
28 | linux (vpe0) reads lx_buffer and writes rt_buffer | 27 | linux (vpe0) reads lx_buffer and writes rt_buffer |
29 | SP (vpe1) reads rt_buffer and writes lx_buffer | 28 | SP (vpe1) reads rt_buffer and writes lx_buffer |
30 | */ | 29 | */ |
31 | typedef struct rtlx_channel { | 30 | struct rtlx_channel { |
32 | enum rtlx_state rt_state; | 31 | unsigned long lx_state; |
33 | enum rtlx_state lx_state; | ||
34 | 32 | ||
35 | int buffer_size; | 33 | int buffer_size; |
36 | 34 | ||
@@ -43,14 +41,12 @@ typedef struct rtlx_channel { | |||
43 | 41 | ||
44 | void *queues; | 42 | void *queues; |
45 | 43 | ||
46 | } rtlx_channel_t; | 44 | }; |
47 | 45 | ||
48 | typedef struct rtlx_info { | 46 | struct rtlx_info { |
49 | unsigned long id; | 47 | unsigned long id; |
50 | enum rtlx_state state; | ||
51 | 48 | ||
52 | struct rtlx_channel channel[RTLX_CHANNELS]; | 49 | struct rtlx_channel channel[RTLX_CHANNELS]; |
50 | }; | ||
53 | 51 | ||
54 | } rtlx_info_t; | 52 | #endif /* _RTLX_H_ */ |
55 | |||
56 | #endif | ||
diff --git a/include/asm-mips/time.h b/include/asm-mips/time.h index e22a20665871..9cc3564cc2c9 100644 --- a/include/asm-mips/time.h +++ b/include/asm-mips/time.h | |||
@@ -20,6 +20,9 @@ | |||
20 | #include <linux/linkage.h> | 20 | #include <linux/linkage.h> |
21 | #include <linux/ptrace.h> | 21 | #include <linux/ptrace.h> |
22 | #include <linux/rtc.h> | 22 | #include <linux/rtc.h> |
23 | #include <linux/spinlock.h> | ||
24 | |||
25 | extern spinlock_t rtc_lock; | ||
23 | 26 | ||
24 | /* | 27 | /* |
25 | * RTC ops. By default, they point to no-RTC functions. | 28 | * RTC ops. By default, they point to no-RTC functions. |
diff --git a/sound/oss/au1000.c b/sound/oss/au1000.c index 2c2ae2ee01ac..c407de86cbb6 100644 --- a/sound/oss/au1000.c +++ b/sound/oss/au1000.c | |||
@@ -563,7 +563,7 @@ static void start_adc(struct au1000_state *s) | |||
563 | #define DMABUF_DEFAULTORDER (17-PAGE_SHIFT) | 563 | #define DMABUF_DEFAULTORDER (17-PAGE_SHIFT) |
564 | #define DMABUF_MINORDER 1 | 564 | #define DMABUF_MINORDER 1 |
565 | 565 | ||
566 | extern inline void dealloc_dmabuf(struct au1000_state *s, struct dmabuf *db) | 566 | static inline void dealloc_dmabuf(struct au1000_state *s, struct dmabuf *db) |
567 | { | 567 | { |
568 | struct page *page, *pend; | 568 | struct page *page, *pend; |
569 | 569 | ||
@@ -667,14 +667,14 @@ static int prog_dmabuf(struct au1000_state *s, struct dmabuf *db) | |||
667 | return 0; | 667 | return 0; |
668 | } | 668 | } |
669 | 669 | ||
670 | extern inline int prog_dmabuf_adc(struct au1000_state *s) | 670 | static inline int prog_dmabuf_adc(struct au1000_state *s) |
671 | { | 671 | { |
672 | stop_adc(s); | 672 | stop_adc(s); |
673 | return prog_dmabuf(s, &s->dma_adc); | 673 | return prog_dmabuf(s, &s->dma_adc); |
674 | 674 | ||
675 | } | 675 | } |
676 | 676 | ||
677 | extern inline int prog_dmabuf_dac(struct au1000_state *s) | 677 | static inline int prog_dmabuf_dac(struct au1000_state *s) |
678 | { | 678 | { |
679 | stop_dac(s); | 679 | stop_dac(s); |
680 | return prog_dmabuf(s, &s->dma_dac); | 680 | return prog_dmabuf(s, &s->dma_dac); |
diff --git a/sound/oss/nec_vrc5477.c b/sound/oss/nec_vrc5477.c index 0481e5e54ddf..9ac4bf7e1e89 100644 --- a/sound/oss/nec_vrc5477.c +++ b/sound/oss/nec_vrc5477.c | |||
@@ -435,7 +435,7 @@ static int ac97_codec_not_present(struct ac97_codec *codec) | |||
435 | 435 | ||
436 | /* --------------------------------------------------------------------- */ | 436 | /* --------------------------------------------------------------------- */ |
437 | 437 | ||
438 | extern inline void | 438 | static inline void |
439 | stop_dac(struct vrc5477_ac97_state *s) | 439 | stop_dac(struct vrc5477_ac97_state *s) |
440 | { | 440 | { |
441 | struct dmabuf* db = &s->dma_dac; | 441 | struct dmabuf* db = &s->dma_dac; |
@@ -553,7 +553,7 @@ static void start_dac(struct vrc5477_ac97_state *s) | |||
553 | spin_unlock_irqrestore(&s->lock, flags); | 553 | spin_unlock_irqrestore(&s->lock, flags); |
554 | } | 554 | } |
555 | 555 | ||
556 | extern inline void stop_adc(struct vrc5477_ac97_state *s) | 556 | static inline void stop_adc(struct vrc5477_ac97_state *s) |
557 | { | 557 | { |
558 | struct dmabuf* db = &s->dma_adc; | 558 | struct dmabuf* db = &s->dma_adc; |
559 | unsigned long flags; | 559 | unsigned long flags; |
@@ -652,7 +652,7 @@ static void start_adc(struct vrc5477_ac97_state *s) | |||
652 | #define DMABUF_DEFAULTORDER (16-PAGE_SHIFT) | 652 | #define DMABUF_DEFAULTORDER (16-PAGE_SHIFT) |
653 | #define DMABUF_MINORDER 1 | 653 | #define DMABUF_MINORDER 1 |
654 | 654 | ||
655 | extern inline void dealloc_dmabuf(struct vrc5477_ac97_state *s, | 655 | static inline void dealloc_dmabuf(struct vrc5477_ac97_state *s, |
656 | struct dmabuf *db) | 656 | struct dmabuf *db) |
657 | { | 657 | { |
658 | if (db->lbuf) { | 658 | if (db->lbuf) { |