aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/pms.c
diff options
context:
space:
mode:
authorAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
committerAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
commitada47b5fe13d89735805b566185f4885f5a3f750 (patch)
tree644b88f8a71896307d71438e9b3af49126ffb22b /drivers/media/video/pms.c
parent43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff)
parent3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff)
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'drivers/media/video/pms.c')
-rw-r--r--drivers/media/video/pms.c1426
1 files changed, 750 insertions, 676 deletions
diff --git a/drivers/media/video/pms.c b/drivers/media/video/pms.c
index a1ad38fc49c1..0598bbd3f368 100644
--- a/drivers/media/video/pms.c
+++ b/drivers/media/video/pms.c
@@ -14,8 +14,10 @@
14 * unless the userspace driver also doesn't work for you... 14 * unless the userspace driver also doesn't work for you...
15 * 15 *
16 * Changes: 16 * Changes:
17 * 08/07/2003 Daniele Bellucci <bellucda@tiscali.it> 17 * 25-11-2009 Hans Verkuil <hverkuil@xs4all.nl>
18 * - pms_capture: report back -EFAULT 18 * - converted to version 2 of the V4L API.
19 * 08/07/2003 Daniele Bellucci <bellucda@tiscali.it>
20 * - pms_capture: report back -EFAULT
19 */ 21 */
20 22
21#include <linux/module.h> 23#include <linux/module.h>
@@ -23,179 +25,186 @@
23#include <linux/errno.h> 25#include <linux/errno.h>
24#include <linux/fs.h> 26#include <linux/fs.h>
25#include <linux/kernel.h> 27#include <linux/kernel.h>
26#include <linux/slab.h>
27#include <linux/mm.h> 28#include <linux/mm.h>
28#include <linux/ioport.h> 29#include <linux/ioport.h>
29#include <linux/init.h> 30#include <linux/init.h>
31#include <linux/version.h>
32#include <linux/mutex.h>
33#include <linux/uaccess.h>
30#include <asm/io.h> 34#include <asm/io.h>
31#include <linux/videodev.h> 35
36#include <linux/videodev2.h>
32#include <media/v4l2-common.h> 37#include <media/v4l2-common.h>
33#include <media/v4l2-ioctl.h> 38#include <media/v4l2-ioctl.h>
34#include <linux/mutex.h> 39#include <media/v4l2-device.h>
35 40
36#include <asm/uaccess.h> 41MODULE_LICENSE("GPL");
37 42
38 43
39#define MOTOROLA 1 44#define MOTOROLA 1
40#define PHILIPS2 2 45#define PHILIPS2 2 /* SAA7191 */
41#define PHILIPS1 3 46#define PHILIPS1 3
42#define MVVMEMORYWIDTH 0x40 /* 512 bytes */ 47#define MVVMEMORYWIDTH 0x40 /* 512 bytes */
43 48
44struct pms_device 49struct i2c_info {
45{
46 struct video_device v;
47 struct video_picture picture;
48 int height;
49 int width;
50 unsigned long in_use;
51 struct mutex lock;
52};
53
54struct i2c_info
55{
56 u8 slave; 50 u8 slave;
57 u8 sub; 51 u8 sub;
58 u8 data; 52 u8 data;
59 u8 hits; 53 u8 hits;
60}; 54};
61 55
62static int i2c_count; 56struct pms {
63static struct i2c_info i2cinfo[64]; 57 struct v4l2_device v4l2_dev;
58 struct video_device vdev;
59 int height;
60 int width;
61 int depth;
62 int input;
63 s32 brightness, saturation, hue, contrast;
64 unsigned long in_use;
65 struct mutex lock;
66 int i2c_count;
67 struct i2c_info i2cinfo[64];
68
69 int decoder;
70 int standard; /* 0 - auto 1 - ntsc 2 - pal 3 - secam */
71 v4l2_std_id std;
72 int io;
73 int data;
74 void __iomem *mem;
75};
64 76
65static int decoder = PHILIPS2; 77static struct pms pms_card;
66static int standard; /* 0 - auto 1 - ntsc 2 - pal 3 - secam */
67 78
68/* 79/*
69 * I/O ports and Shared Memory 80 * I/O ports and Shared Memory
70 */ 81 */
71 82
72static int io_port = 0x250; 83static int io_port = 0x250;
73static int data_port = 0x251; 84module_param(io_port, int, 0);
74static int mem_base = 0xC8000;
75static void __iomem *mem;
76static int video_nr = -1;
77 85
86static int mem_base = 0xc8000;
87module_param(mem_base, int, 0);
78 88
89static int video_nr = -1;
90module_param(video_nr, int, 0);
79 91
80static inline void mvv_write(u8 index, u8 value) 92
93static inline void mvv_write(struct pms *dev, u8 index, u8 value)
81{ 94{
82 outw(index|(value<<8), io_port); 95 outw(index | (value << 8), dev->io);
83} 96}
84 97
85static inline u8 mvv_read(u8 index) 98static inline u8 mvv_read(struct pms *dev, u8 index)
86{ 99{
87 outb(index, io_port); 100 outb(index, dev->io);
88 return inb(data_port); 101 return inb(dev->data);
89} 102}
90 103
91static int pms_i2c_stat(u8 slave) 104static int pms_i2c_stat(struct pms *dev, u8 slave)
92{ 105{
93 int counter; 106 int counter = 0;
94 int i; 107 int i;
95 108
96 outb(0x28, io_port); 109 outb(0x28, dev->io);
97 110
98 counter=0; 111 while ((inb(dev->data) & 0x01) == 0)
99 while((inb(data_port)&0x01)==0) 112 if (counter++ == 256)
100 if(counter++==256)
101 break; 113 break;
102 114
103 while((inb(data_port)&0x01)!=0) 115 while ((inb(dev->data) & 0x01) != 0)
104 if(counter++==256) 116 if (counter++ == 256)
105 break; 117 break;
106 118
107 outb(slave, io_port); 119 outb(slave, dev->io);
108 120
109 counter=0; 121 counter = 0;
110 while((inb(data_port)&0x01)==0) 122 while ((inb(dev->data) & 0x01) == 0)
111 if(counter++==256) 123 if (counter++ == 256)
112 break; 124 break;
113 125
114 while((inb(data_port)&0x01)!=0) 126 while ((inb(dev->data) & 0x01) != 0)
115 if(counter++==256) 127 if (counter++ == 256)
116 break; 128 break;
117 129
118 for(i=0;i<12;i++) 130 for (i = 0; i < 12; i++) {
119 { 131 char st = inb(dev->data);
120 char st=inb(data_port); 132
121 if((st&2)!=0) 133 if ((st & 2) != 0)
122 return -1; 134 return -1;
123 if((st&1)==0) 135 if ((st & 1) == 0)
124 break; 136 break;
125 } 137 }
126 outb(0x29, io_port); 138 outb(0x29, dev->io);
127 return inb(data_port); 139 return inb(dev->data);
128} 140}
129 141
130static int pms_i2c_write(u16 slave, u16 sub, u16 data) 142static int pms_i2c_write(struct pms *dev, u16 slave, u16 sub, u16 data)
131{ 143{
132 int skip=0; 144 int skip = 0;
133 int count; 145 int count;
134 int i; 146 int i;
135 147
136 for(i=0;i<i2c_count;i++) 148 for (i = 0; i < dev->i2c_count; i++) {
137 { 149 if ((dev->i2cinfo[i].slave == slave) &&
138 if((i2cinfo[i].slave==slave) && 150 (dev->i2cinfo[i].sub == sub)) {
139 (i2cinfo[i].sub == sub)) 151 if (dev->i2cinfo[i].data == data)
140 { 152 skip = 1;
141 if(i2cinfo[i].data==data) 153 dev->i2cinfo[i].data = data;
142 skip=1; 154 i = dev->i2c_count + 1;
143 i2cinfo[i].data=data;
144 i=i2c_count+1;
145 } 155 }
146 } 156 }
147 157
148 if(i==i2c_count && i2c_count<64) 158 if (i == dev->i2c_count && dev->i2c_count < 64) {
149 { 159 dev->i2cinfo[dev->i2c_count].slave = slave;
150 i2cinfo[i2c_count].slave=slave; 160 dev->i2cinfo[dev->i2c_count].sub = sub;
151 i2cinfo[i2c_count].sub=sub; 161 dev->i2cinfo[dev->i2c_count].data = data;
152 i2cinfo[i2c_count].data=data; 162 dev->i2c_count++;
153 i2c_count++;
154 } 163 }
155 164
156 if(skip) 165 if (skip)
157 return 0; 166 return 0;
158 167
159 mvv_write(0x29, sub); 168 mvv_write(dev, 0x29, sub);
160 mvv_write(0x2A, data); 169 mvv_write(dev, 0x2A, data);
161 mvv_write(0x28, slave); 170 mvv_write(dev, 0x28, slave);
162 171
163 outb(0x28, io_port); 172 outb(0x28, dev->io);
164 173
165 count=0; 174 count = 0;
166 while((inb(data_port)&1)==0) 175 while ((inb(dev->data) & 1) == 0)
167 if(count>255) 176 if (count > 255)
168 break; 177 break;
169 while((inb(data_port)&1)!=0) 178 while ((inb(dev->data) & 1) != 0)
170 if(count>255) 179 if (count > 255)
171 break; 180 break;
172 181
173 count=inb(data_port); 182 count = inb(dev->data);
174 183
175 if(count&2) 184 if (count & 2)
176 return -1; 185 return -1;
177 return count; 186 return count;
178} 187}
179 188
180static int pms_i2c_read(int slave, int sub) 189static int pms_i2c_read(struct pms *dev, int slave, int sub)
181{ 190{
182 int i=0; 191 int i;
183 for(i=0;i<i2c_count;i++) 192
184 { 193 for (i = 0; i < dev->i2c_count; i++) {
185 if(i2cinfo[i].slave==slave && i2cinfo[i].sub==sub) 194 if (dev->i2cinfo[i].slave == slave && dev->i2cinfo[i].sub == sub)
186 return i2cinfo[i].data; 195 return dev->i2cinfo[i].data;
187 } 196 }
188 return 0; 197 return 0;
189} 198}
190 199
191 200
192static void pms_i2c_andor(int slave, int sub, int and, int or) 201static void pms_i2c_andor(struct pms *dev, int slave, int sub, int and, int or)
193{ 202{
194 u8 tmp; 203 u8 tmp;
195 204
196 tmp=pms_i2c_read(slave, sub); 205 tmp = pms_i2c_read(dev, slave, sub);
197 tmp = (tmp&and)|or; 206 tmp = (tmp & and) | or;
198 pms_i2c_write(slave, sub, tmp); 207 pms_i2c_write(dev, slave, sub, tmp);
199} 208}
200 209
201/* 210/*
@@ -203,100 +212,108 @@ static void pms_i2c_andor(int slave, int sub, int and, int or)
203 */ 212 */
204 213
205 214
206static void pms_videosource(short source) 215static void pms_videosource(struct pms *dev, short source)
207{ 216{
208 mvv_write(0x2E, source?0x31:0x30); 217 switch (dev->decoder) {
218 case MOTOROLA:
219 break;
220 case PHILIPS2:
221 pms_i2c_andor(dev, 0x8a, 0x06, 0x7f, source ? 0x80 : 0);
222 break;
223 case PHILIPS1:
224 break;
225 }
226 mvv_write(dev, 0x2E, 0x31);
227 /* Was: mvv_write(dev, 0x2E, source ? 0x31 : 0x30);
228 But could not make this work correctly. Only Composite input
229 worked for me. */
209} 230}
210 231
211static void pms_hue(short hue) 232static void pms_hue(struct pms *dev, short hue)
212{ 233{
213 switch(decoder) 234 switch (dev->decoder) {
214 { 235 case MOTOROLA:
215 case MOTOROLA: 236 pms_i2c_write(dev, 0x8a, 0x00, hue);
216 pms_i2c_write(0x8A, 0x00, hue); 237 break;
217 break; 238 case PHILIPS2:
218 case PHILIPS2: 239 pms_i2c_write(dev, 0x8a, 0x07, hue);
219 pms_i2c_write(0x8A, 0x07, hue); 240 break;
220 break; 241 case PHILIPS1:
221 case PHILIPS1: 242 pms_i2c_write(dev, 0x42, 0x07, hue);
222 pms_i2c_write(0x42, 0x07, hue); 243 break;
223 break;
224 } 244 }
225} 245}
226 246
227static void pms_colour(short colour) 247static void pms_saturation(struct pms *dev, short sat)
228{ 248{
229 switch(decoder) 249 switch (dev->decoder) {
230 { 250 case MOTOROLA:
231 case MOTOROLA: 251 pms_i2c_write(dev, 0x8a, 0x00, sat);
232 pms_i2c_write(0x8A, 0x00, colour); 252 break;
233 break; 253 case PHILIPS1:
234 case PHILIPS1: 254 pms_i2c_write(dev, 0x42, 0x12, sat);
235 pms_i2c_write(0x42, 0x12, colour); 255 break;
236 break;
237 } 256 }
238} 257}
239 258
240 259
241static void pms_contrast(short contrast) 260static void pms_contrast(struct pms *dev, short contrast)
242{ 261{
243 switch(decoder) 262 switch (dev->decoder) {
244 { 263 case MOTOROLA:
245 case MOTOROLA: 264 pms_i2c_write(dev, 0x8a, 0x00, contrast);
246 pms_i2c_write(0x8A, 0x00, contrast); 265 break;
247 break; 266 case PHILIPS1:
248 case PHILIPS1: 267 pms_i2c_write(dev, 0x42, 0x13, contrast);
249 pms_i2c_write(0x42, 0x13, contrast); 268 break;
250 break;
251 } 269 }
252} 270}
253 271
254static void pms_brightness(short brightness) 272static void pms_brightness(struct pms *dev, short brightness)
255{ 273{
256 switch(decoder) 274 switch (dev->decoder) {
257 { 275 case MOTOROLA:
258 case MOTOROLA: 276 pms_i2c_write(dev, 0x8a, 0x00, brightness);
259 pms_i2c_write(0x8A, 0x00, brightness); 277 pms_i2c_write(dev, 0x8a, 0x00, brightness);
260 pms_i2c_write(0x8A, 0x00, brightness); 278 pms_i2c_write(dev, 0x8a, 0x00, brightness);
261 pms_i2c_write(0x8A, 0x00, brightness); 279 break;
262 break; 280 case PHILIPS1:
263 case PHILIPS1: 281 pms_i2c_write(dev, 0x42, 0x19, brightness);
264 pms_i2c_write(0x42, 0x19, brightness); 282 break;
265 break;
266 } 283 }
267} 284}
268 285
269 286
270static void pms_format(short format) 287static void pms_format(struct pms *dev, short format)
271{ 288{
272 int target; 289 int target;
273 standard = format;
274 290
275 if(decoder==PHILIPS1) 291 dev->standard = format;
276 target=0x42; 292
277 else if(decoder==PHILIPS2) 293 if (dev->decoder == PHILIPS1)
278 target=0x8A; 294 target = 0x42;
295 else if (dev->decoder == PHILIPS2)
296 target = 0x8a;
279 else 297 else
280 return; 298 return;
281 299
282 switch(format) 300 switch (format) {
283 { 301 case 0: /* Auto */
284 case 0: /* Auto */ 302 pms_i2c_andor(dev, target, 0x0d, 0xfe, 0x00);
285 pms_i2c_andor(target, 0x0D, 0xFE,0x00); 303 pms_i2c_andor(dev, target, 0x0f, 0x3f, 0x80);
286 pms_i2c_andor(target, 0x0F, 0x3F,0x80); 304 break;
287 break; 305 case 1: /* NTSC */
288 case 1: /* NTSC */ 306 pms_i2c_andor(dev, target, 0x0d, 0xfe, 0x00);
289 pms_i2c_andor(target, 0x0D, 0xFE, 0x00); 307 pms_i2c_andor(dev, target, 0x0f, 0x3f, 0x40);
290 pms_i2c_andor(target, 0x0F, 0x3F, 0x40); 308 break;
291 break; 309 case 2: /* PAL */
292 case 2: /* PAL */ 310 pms_i2c_andor(dev, target, 0x0d, 0xfe, 0x00);
293 pms_i2c_andor(target, 0x0D, 0xFE, 0x00); 311 pms_i2c_andor(dev, target, 0x0f, 0x3f, 0x00);
294 pms_i2c_andor(target, 0x0F, 0x3F, 0x00); 312 break;
295 break; 313 case 3: /* SECAM */
296 case 3: /* SECAM */ 314 pms_i2c_andor(dev, target, 0x0d, 0xfe, 0x01);
297 pms_i2c_andor(target, 0x0D, 0xFE, 0x01); 315 pms_i2c_andor(dev, target, 0x0f, 0x3f, 0x00);
298 pms_i2c_andor(target, 0x0F, 0x3F, 0x00); 316 break;
299 break;
300 } 317 }
301} 318}
302 319
@@ -308,18 +325,17 @@ static void pms_format(short format)
308 * people need it. We also don't yet use the PMS interrupt. 325 * people need it. We also don't yet use the PMS interrupt.
309 */ 326 */
310 327
311static void pms_hstart(short start) 328static void pms_hstart(struct pms *dev, short start)
312{ 329{
313 switch(decoder) 330 switch (dev->decoder) {
314 { 331 case PHILIPS1:
315 case PHILIPS1: 332 pms_i2c_write(dev, 0x8a, 0x05, start);
316 pms_i2c_write(0x8A, 0x05, start); 333 pms_i2c_write(dev, 0x8a, 0x18, start);
317 pms_i2c_write(0x8A, 0x18, start); 334 break;
318 break; 335 case PHILIPS2:
319 case PHILIPS2: 336 pms_i2c_write(dev, 0x42, 0x05, start);
320 pms_i2c_write(0x42, 0x05, start); 337 pms_i2c_write(dev, 0x42, 0x18, start);
321 pms_i2c_write(0x42, 0x18, start); 338 break;
322 break;
323 } 339 }
324} 340}
325 341
@@ -327,293 +343,271 @@ static void pms_hstart(short start)
327 * Bandpass filters 343 * Bandpass filters
328 */ 344 */
329 345
330static void pms_bandpass(short pass) 346static void pms_bandpass(struct pms *dev, short pass)
331{ 347{
332 if(decoder==PHILIPS2) 348 if (dev->decoder == PHILIPS2)
333 pms_i2c_andor(0x8A, 0x06, 0xCF, (pass&0x03)<<4); 349 pms_i2c_andor(dev, 0x8a, 0x06, 0xcf, (pass & 0x03) << 4);
334 else if(decoder==PHILIPS1) 350 else if (dev->decoder == PHILIPS1)
335 pms_i2c_andor(0x42, 0x06, 0xCF, (pass&0x03)<<4); 351 pms_i2c_andor(dev, 0x42, 0x06, 0xcf, (pass & 0x03) << 4);
336} 352}
337 353
338static void pms_antisnow(short snow) 354static void pms_antisnow(struct pms *dev, short snow)
339{ 355{
340 if(decoder==PHILIPS2) 356 if (dev->decoder == PHILIPS2)
341 pms_i2c_andor(0x8A, 0x06, 0xF3, (snow&0x03)<<2); 357 pms_i2c_andor(dev, 0x8a, 0x06, 0xf3, (snow & 0x03) << 2);
342 else if(decoder==PHILIPS1) 358 else if (dev->decoder == PHILIPS1)
343 pms_i2c_andor(0x42, 0x06, 0xF3, (snow&0x03)<<2); 359 pms_i2c_andor(dev, 0x42, 0x06, 0xf3, (snow & 0x03) << 2);
344} 360}
345 361
346static void pms_sharpness(short sharp) 362static void pms_sharpness(struct pms *dev, short sharp)
347{ 363{
348 if(decoder==PHILIPS2) 364 if (dev->decoder == PHILIPS2)
349 pms_i2c_andor(0x8A, 0x06, 0xFC, sharp&0x03); 365 pms_i2c_andor(dev, 0x8a, 0x06, 0xfc, sharp & 0x03);
350 else if(decoder==PHILIPS1) 366 else if (dev->decoder == PHILIPS1)
351 pms_i2c_andor(0x42, 0x06, 0xFC, sharp&0x03); 367 pms_i2c_andor(dev, 0x42, 0x06, 0xfc, sharp & 0x03);
352} 368}
353 369
354static void pms_chromaagc(short agc) 370static void pms_chromaagc(struct pms *dev, short agc)
355{ 371{
356 if(decoder==PHILIPS2) 372 if (dev->decoder == PHILIPS2)
357 pms_i2c_andor(0x8A, 0x0C, 0x9F, (agc&0x03)<<5); 373 pms_i2c_andor(dev, 0x8a, 0x0c, 0x9f, (agc & 0x03) << 5);
358 else if(decoder==PHILIPS1) 374 else if (dev->decoder == PHILIPS1)
359 pms_i2c_andor(0x42, 0x0C, 0x9F, (agc&0x03)<<5); 375 pms_i2c_andor(dev, 0x42, 0x0c, 0x9f, (agc & 0x03) << 5);
360} 376}
361 377
362static void pms_vertnoise(short noise) 378static void pms_vertnoise(struct pms *dev, short noise)
363{ 379{
364 if(decoder==PHILIPS2) 380 if (dev->decoder == PHILIPS2)
365 pms_i2c_andor(0x8A, 0x10, 0xFC, noise&3); 381 pms_i2c_andor(dev, 0x8a, 0x10, 0xfc, noise & 3);
366 else if(decoder==PHILIPS1) 382 else if (dev->decoder == PHILIPS1)
367 pms_i2c_andor(0x42, 0x10, 0xFC, noise&3); 383 pms_i2c_andor(dev, 0x42, 0x10, 0xfc, noise & 3);
368} 384}
369 385
370static void pms_forcecolour(short colour) 386static void pms_forcecolour(struct pms *dev, short colour)
371{ 387{
372 if(decoder==PHILIPS2) 388 if (dev->decoder == PHILIPS2)
373 pms_i2c_andor(0x8A, 0x0C, 0x7F, (colour&1)<<7); 389 pms_i2c_andor(dev, 0x8a, 0x0c, 0x7f, (colour & 1) << 7);
374 else if(decoder==PHILIPS1) 390 else if (dev->decoder == PHILIPS1)
375 pms_i2c_andor(0x42, 0x0C, 0x7, (colour&1)<<7); 391 pms_i2c_andor(dev, 0x42, 0x0c, 0x7, (colour & 1) << 7);
376} 392}
377 393
378static void pms_antigamma(short gamma) 394static void pms_antigamma(struct pms *dev, short gamma)
379{ 395{
380 if(decoder==PHILIPS2) 396 if (dev->decoder == PHILIPS2)
381 pms_i2c_andor(0xB8, 0x00, 0x7F, (gamma&1)<<7); 397 pms_i2c_andor(dev, 0xb8, 0x00, 0x7f, (gamma & 1) << 7);
382 else if(decoder==PHILIPS1) 398 else if (dev->decoder == PHILIPS1)
383 pms_i2c_andor(0x42, 0x20, 0x7, (gamma&1)<<7); 399 pms_i2c_andor(dev, 0x42, 0x20, 0x7, (gamma & 1) << 7);
384} 400}
385 401
386static void pms_prefilter(short filter) 402static void pms_prefilter(struct pms *dev, short filter)
387{ 403{
388 if(decoder==PHILIPS2) 404 if (dev->decoder == PHILIPS2)
389 pms_i2c_andor(0x8A, 0x06, 0xBF, (filter&1)<<6); 405 pms_i2c_andor(dev, 0x8a, 0x06, 0xbf, (filter & 1) << 6);
390 else if(decoder==PHILIPS1) 406 else if (dev->decoder == PHILIPS1)
391 pms_i2c_andor(0x42, 0x06, 0xBF, (filter&1)<<6); 407 pms_i2c_andor(dev, 0x42, 0x06, 0xbf, (filter & 1) << 6);
392} 408}
393 409
394static void pms_hfilter(short filter) 410static void pms_hfilter(struct pms *dev, short filter)
395{ 411{
396 if(decoder==PHILIPS2) 412 if (dev->decoder == PHILIPS2)
397 pms_i2c_andor(0xB8, 0x04, 0x1F, (filter&7)<<5); 413 pms_i2c_andor(dev, 0xb8, 0x04, 0x1f, (filter & 7) << 5);
398 else if(decoder==PHILIPS1) 414 else if (dev->decoder == PHILIPS1)
399 pms_i2c_andor(0x42, 0x24, 0x1F, (filter&7)<<5); 415 pms_i2c_andor(dev, 0x42, 0x24, 0x1f, (filter & 7) << 5);
400} 416}
401 417
402static void pms_vfilter(short filter) 418static void pms_vfilter(struct pms *dev, short filter)
403{ 419{
404 if(decoder==PHILIPS2) 420 if (dev->decoder == PHILIPS2)
405 pms_i2c_andor(0xB8, 0x08, 0x9F, (filter&3)<<5); 421 pms_i2c_andor(dev, 0xb8, 0x08, 0x9f, (filter & 3) << 5);
406 else if(decoder==PHILIPS1) 422 else if (dev->decoder == PHILIPS1)
407 pms_i2c_andor(0x42, 0x28, 0x9F, (filter&3)<<5); 423 pms_i2c_andor(dev, 0x42, 0x28, 0x9f, (filter & 3) << 5);
408} 424}
409 425
410static void pms_killcolour(short colour) 426static void pms_killcolour(struct pms *dev, short colour)
411{ 427{
412 if(decoder==PHILIPS2) 428 if (dev->decoder == PHILIPS2) {
413 { 429 pms_i2c_andor(dev, 0x8a, 0x08, 0x07, (colour & 0x1f) << 3);
414 pms_i2c_andor(0x8A, 0x08, 0x07, (colour&0x1F)<<3); 430 pms_i2c_andor(dev, 0x8a, 0x09, 0x07, (colour & 0x1f) << 3);
415 pms_i2c_andor(0x8A, 0x09, 0x07, (colour&0x1F)<<3); 431 } else if (dev->decoder == PHILIPS1) {
416 } 432 pms_i2c_andor(dev, 0x42, 0x08, 0x07, (colour & 0x1f) << 3);
417 else if(decoder==PHILIPS1) 433 pms_i2c_andor(dev, 0x42, 0x09, 0x07, (colour & 0x1f) << 3);
418 {
419 pms_i2c_andor(0x42, 0x08, 0x07, (colour&0x1F)<<3);
420 pms_i2c_andor(0x42, 0x09, 0x07, (colour&0x1F)<<3);
421 } 434 }
422} 435}
423 436
424static void pms_chromagain(short chroma) 437static void pms_chromagain(struct pms *dev, short chroma)
425{ 438{
426 if(decoder==PHILIPS2) 439 if (dev->decoder == PHILIPS2)
427 { 440 pms_i2c_write(dev, 0x8a, 0x11, chroma);
428 pms_i2c_write(0x8A, 0x11, chroma); 441 else if (dev->decoder == PHILIPS1)
429 } 442 pms_i2c_write(dev, 0x42, 0x11, chroma);
430 else if(decoder==PHILIPS1)
431 {
432 pms_i2c_write(0x42, 0x11, chroma);
433 }
434} 443}
435 444
436 445
437static void pms_spacialcompl(short data) 446static void pms_spacialcompl(struct pms *dev, short data)
438{ 447{
439 mvv_write(0x3B, data); 448 mvv_write(dev, 0x3b, data);
440} 449}
441 450
442static void pms_spacialcomph(short data) 451static void pms_spacialcomph(struct pms *dev, short data)
443{ 452{
444 mvv_write(0x3A, data); 453 mvv_write(dev, 0x3a, data);
445} 454}
446 455
447static void pms_vstart(short start) 456static void pms_vstart(struct pms *dev, short start)
448{ 457{
449 mvv_write(0x16, start); 458 mvv_write(dev, 0x16, start);
450 mvv_write(0x17, (start>>8)&0x01); 459 mvv_write(dev, 0x17, (start >> 8) & 0x01);
451} 460}
452 461
453#endif 462#endif
454 463
455static void pms_secamcross(short cross) 464static void pms_secamcross(struct pms *dev, short cross)
456{ 465{
457 if(decoder==PHILIPS2) 466 if (dev->decoder == PHILIPS2)
458 pms_i2c_andor(0x8A, 0x0F, 0xDF, (cross&1)<<5); 467 pms_i2c_andor(dev, 0x8a, 0x0f, 0xdf, (cross & 1) << 5);
459 else if(decoder==PHILIPS1) 468 else if (dev->decoder == PHILIPS1)
460 pms_i2c_andor(0x42, 0x0F, 0xDF, (cross&1)<<5); 469 pms_i2c_andor(dev, 0x42, 0x0f, 0xdf, (cross & 1) << 5);
461} 470}
462 471
463 472
464static void pms_swsense(short sense) 473static void pms_swsense(struct pms *dev, short sense)
465{ 474{
466 if(decoder==PHILIPS2) 475 if (dev->decoder == PHILIPS2) {
467 { 476 pms_i2c_write(dev, 0x8a, 0x0a, sense);
468 pms_i2c_write(0x8A, 0x0A, sense); 477 pms_i2c_write(dev, 0x8a, 0x0b, sense);
469 pms_i2c_write(0x8A, 0x0B, sense); 478 } else if (dev->decoder == PHILIPS1) {
470 } 479 pms_i2c_write(dev, 0x42, 0x0a, sense);
471 else if(decoder==PHILIPS1) 480 pms_i2c_write(dev, 0x42, 0x0b, sense);
472 {
473 pms_i2c_write(0x42, 0x0A, sense);
474 pms_i2c_write(0x42, 0x0B, sense);
475 } 481 }
476} 482}
477 483
478 484
479static void pms_framerate(short frr) 485static void pms_framerate(struct pms *dev, short frr)
480{ 486{
481 int fps=(standard==1)?30:25; 487 int fps = (dev->std & V4L2_STD_525_60) ? 30 : 25;
482 if(frr==0) 488
489 if (frr == 0)
483 return; 490 return;
484 fps=fps/frr; 491 fps = fps/frr;
485 mvv_write(0x14,0x80|fps); 492 mvv_write(dev, 0x14, 0x80 | fps);
486 mvv_write(0x15,1); 493 mvv_write(dev, 0x15, 1);
487} 494}
488 495
489static void pms_vert(u8 deciden, u8 decinum) 496static void pms_vert(struct pms *dev, u8 deciden, u8 decinum)
490{ 497{
491 mvv_write(0x1C, deciden); /* Denominator */ 498 mvv_write(dev, 0x1c, deciden); /* Denominator */
492 mvv_write(0x1D, decinum); /* Numerator */ 499 mvv_write(dev, 0x1d, decinum); /* Numerator */
493} 500}
494 501
495/* 502/*
496 * Turn 16bit ratios into best small ratio the chipset can grok 503 * Turn 16bit ratios into best small ratio the chipset can grok
497 */ 504 */
498 505
499static void pms_vertdeci(unsigned short decinum, unsigned short deciden) 506static void pms_vertdeci(struct pms *dev, unsigned short decinum, unsigned short deciden)
500{ 507{
501 /* Knock it down by /5 once */ 508 /* Knock it down by / 5 once */
502 if(decinum%5==0) 509 if (decinum % 5 == 0) {
503 { 510 deciden /= 5;
504 deciden/=5; 511 decinum /= 5;
505 decinum/=5;
506 } 512 }
507 /* 513 /*
508 * 3's 514 * 3's
509 */ 515 */
510 while(decinum%3==0 && deciden%3==0) 516 while (decinum % 3 == 0 && deciden % 3 == 0) {
511 { 517 deciden /= 3;
512 deciden/=3; 518 decinum /= 3;
513 decinum/=3;
514 } 519 }
515 /* 520 /*
516 * 2's 521 * 2's
517 */ 522 */
518 while(decinum%2==0 && deciden%2==0) 523 while (decinum % 2 == 0 && deciden % 2 == 0) {
519 { 524 decinum /= 2;
520 decinum/=2; 525 deciden /= 2;
521 deciden/=2;
522 } 526 }
523 /* 527 /*
524 * Fudgyify 528 * Fudgyify
525 */ 529 */
526 while(deciden>32) 530 while (deciden > 32) {
527 { 531 deciden /= 2;
528 deciden/=2; 532 decinum = (decinum + 1) / 2;
529 decinum=(decinum+1)/2;
530 } 533 }
531 if(deciden==32) 534 if (deciden == 32)
532 deciden--; 535 deciden--;
533 pms_vert(deciden,decinum); 536 pms_vert(dev, deciden, decinum);
534} 537}
535 538
536static void pms_horzdeci(short decinum, short deciden) 539static void pms_horzdeci(struct pms *dev, short decinum, short deciden)
537{ 540{
538 if(decinum<=512) 541 if (decinum <= 512) {
539 { 542 if (decinum % 5 == 0) {
540 if(decinum%5==0) 543 decinum /= 5;
541 { 544 deciden /= 5;
542 decinum/=5;
543 deciden/=5;
544 } 545 }
545 } 546 } else {
546 else 547 decinum = 512;
547 { 548 deciden = 640; /* 768 would be ideal */
548 decinum=512;
549 deciden=640; /* 768 would be ideal */
550 } 549 }
551 550
552 while(((decinum|deciden)&1)==0) 551 while (((decinum | deciden) & 1) == 0) {
553 { 552 decinum >>= 1;
554 decinum>>=1; 553 deciden >>= 1;
555 deciden>>=1;
556 } 554 }
557 while(deciden>32) 555 while (deciden > 32) {
558 { 556 deciden >>= 1;
559 deciden>>=1; 557 decinum = (decinum + 1) >> 1;
560 decinum=(decinum+1)>>1;
561 } 558 }
562 if(deciden==32) 559 if (deciden == 32)
563 deciden--; 560 deciden--;
564 561
565 mvv_write(0x24, 0x80|deciden); 562 mvv_write(dev, 0x24, 0x80 | deciden);
566 mvv_write(0x25, decinum); 563 mvv_write(dev, 0x25, decinum);
567} 564}
568 565
569static void pms_resolution(short width, short height) 566static void pms_resolution(struct pms *dev, short width, short height)
570{ 567{
571 int fg_height; 568 int fg_height;
572 569
573 fg_height=height; 570 fg_height = height;
574 if(fg_height>280) 571 if (fg_height > 280)
575 fg_height=280; 572 fg_height = 280;
576 573
577 mvv_write(0x18, fg_height); 574 mvv_write(dev, 0x18, fg_height);
578 mvv_write(0x19, fg_height>>8); 575 mvv_write(dev, 0x19, fg_height >> 8);
579 576
580 if(standard==1) 577 if (dev->std & V4L2_STD_525_60) {
581 { 578 mvv_write(dev, 0x1a, 0xfc);
582 mvv_write(0x1A, 0xFC); 579 mvv_write(dev, 0x1b, 0x00);
583 mvv_write(0x1B, 0x00); 580 if (height > fg_height)
584 if(height>fg_height) 581 pms_vertdeci(dev, 240, 240);
585 pms_vertdeci(240,240);
586 else 582 else
587 pms_vertdeci(fg_height,240); 583 pms_vertdeci(dev, fg_height, 240);
588 } 584 } else {
589 else 585 mvv_write(dev, 0x1a, 0x1a);
590 { 586 mvv_write(dev, 0x1b, 0x01);
591 mvv_write(0x1A, 0x1A); 587 if (fg_height > 256)
592 mvv_write(0x1B, 0x01); 588 pms_vertdeci(dev, 270, 270);
593 if(fg_height>256)
594 pms_vertdeci(270,270);
595 else 589 else
596 pms_vertdeci(fg_height, 270); 590 pms_vertdeci(dev, fg_height, 270);
597 } 591 }
598 mvv_write(0x12,0); 592 mvv_write(dev, 0x12, 0);
599 mvv_write(0x13, MVVMEMORYWIDTH); 593 mvv_write(dev, 0x13, MVVMEMORYWIDTH);
600 mvv_write(0x42, 0x00); 594 mvv_write(dev, 0x42, 0x00);
601 mvv_write(0x43, 0x00); 595 mvv_write(dev, 0x43, 0x00);
602 mvv_write(0x44, MVVMEMORYWIDTH); 596 mvv_write(dev, 0x44, MVVMEMORYWIDTH);
603 597
604 mvv_write(0x22, width+8); 598 mvv_write(dev, 0x22, width + 8);
605 mvv_write(0x23, (width+8)>> 8); 599 mvv_write(dev, 0x23, (width + 8) >> 8);
606 600
607 if(standard==1) 601 if (dev->std & V4L2_STD_525_60)
608 pms_horzdeci(width,640); 602 pms_horzdeci(dev, width, 640);
609 else 603 else
610 pms_horzdeci(width+8, 768); 604 pms_horzdeci(dev, width + 8, 768);
611 605
612 mvv_write(0x30, mvv_read(0x30)&0xFE); 606 mvv_write(dev, 0x30, mvv_read(dev, 0x30) & 0xfe);
613 mvv_write(0x08, mvv_read(0x08)|0x01); 607 mvv_write(dev, 0x08, mvv_read(dev, 0x08) | 0x01);
614 mvv_write(0x01, mvv_read(0x01)&0xFD); 608 mvv_write(dev, 0x01, mvv_read(dev, 0x01) & 0xfd);
615 mvv_write(0x32, 0x00); 609 mvv_write(dev, 0x32, 0x00);
616 mvv_write(0x33, MVVMEMORYWIDTH); 610 mvv_write(dev, 0x33, MVVMEMORYWIDTH);
617} 611}
618 612
619 613
@@ -621,52 +615,49 @@ static void pms_resolution(short width, short height)
621 * Set Input 615 * Set Input
622 */ 616 */
623 617
624static void pms_vcrinput(short input) 618static void pms_vcrinput(struct pms *dev, short input)
625{ 619{
626 if(decoder==PHILIPS2) 620 if (dev->decoder == PHILIPS2)
627 pms_i2c_andor(0x8A,0x0D,0x7F,(input&1)<<7); 621 pms_i2c_andor(dev, 0x8a, 0x0d, 0x7f, (input & 1) << 7);
628 else if(decoder==PHILIPS1) 622 else if (dev->decoder == PHILIPS1)
629 pms_i2c_andor(0x42,0x0D,0x7F,(input&1)<<7); 623 pms_i2c_andor(dev, 0x42, 0x0d, 0x7f, (input & 1) << 7);
630} 624}
631 625
632 626
633static int pms_capture(struct pms_device *dev, char __user *buf, int rgb555, int count) 627static int pms_capture(struct pms *dev, char __user *buf, int rgb555, int count)
634{ 628{
635 int y; 629 int y;
636 int dw = 2*dev->width; 630 int dw = 2 * dev->width;
637 631 char tmp[dw + 32]; /* using a temp buffer is faster than direct */
638 char tmp[dw+32]; /* using a temp buffer is faster than direct */
639 int cnt = 0; 632 int cnt = 0;
640 int len=0; 633 int len = 0;
641 unsigned char r8 = 0x5; /* value for reg8 */ 634 unsigned char r8 = 0x5; /* value for reg8 */
642 635
643 if (rgb555) 636 if (rgb555)
644 r8 |= 0x20; /* else use untranslated rgb = 565 */ 637 r8 |= 0x20; /* else use untranslated rgb = 565 */
645 mvv_write(0x08,r8); /* capture rgb555/565, init DRAM, PC enable */ 638 mvv_write(dev, 0x08, r8); /* capture rgb555/565, init DRAM, PC enable */
646 639
647/* printf("%d %d %d %d %d %x %x\n",width,height,voff,nom,den,mvv_buf); */ 640/* printf("%d %d %d %d %d %x %x\n",width,height,voff,nom,den,mvv_buf); */
648 641
649 for (y = 0; y < dev->height; y++ ) 642 for (y = 0; y < dev->height; y++) {
650 { 643 writeb(0, dev->mem); /* synchronisiert neue Zeile */
651 writeb(0, mem); /* synchronisiert neue Zeile */
652 644
653 /* 645 /*
654 * This is in truth a fifo, be very careful as if you 646 * This is in truth a fifo, be very careful as if you
655 * forgot this odd things will occur 8) 647 * forgot this odd things will occur 8)
656 */ 648 */
657 649
658 memcpy_fromio(tmp, mem, dw+32); /* discard 16 word */ 650 memcpy_fromio(tmp, dev->mem, dw + 32); /* discard 16 word */
659 cnt -= dev->height; 651 cnt -= dev->height;
660 while (cnt <= 0) 652 while (cnt <= 0) {
661 {
662 /* 653 /*
663 * Don't copy too far 654 * Don't copy too far
664 */ 655 */
665 int dt=dw; 656 int dt = dw;
666 if(dt+len>count) 657 if (dt + len > count)
667 dt=count-len; 658 dt = count - len;
668 cnt += dev->height; 659 cnt += dev->height;
669 if (copy_to_user(buf, tmp+32, dt)) 660 if (copy_to_user(buf, tmp + 32, dt))
670 return len ? len : -EFAULT; 661 return len ? len : -EFAULT;
671 buf += dt; 662 buf += dt;
672 len += dt; 663 len += dt;
@@ -680,221 +671,278 @@ static int pms_capture(struct pms_device *dev, char __user *buf, int rgb555, int
680 * Video4linux interfacing 671 * Video4linux interfacing
681 */ 672 */
682 673
683static long pms_do_ioctl(struct file *file, unsigned int cmd, void *arg) 674static int pms_querycap(struct file *file, void *priv,
675 struct v4l2_capability *vcap)
684{ 676{
685 struct video_device *dev = video_devdata(file); 677 struct pms *dev = video_drvdata(file);
686 struct pms_device *pd=(struct pms_device *)dev;
687
688 switch(cmd)
689 {
690 case VIDIOCGCAP:
691 {
692 struct video_capability *b = arg;
693 strcpy(b->name, "Mediavision PMS");
694 b->type = VID_TYPE_CAPTURE|VID_TYPE_SCALES;
695 b->channels = 4;
696 b->audios = 0;
697 b->maxwidth = 640;
698 b->maxheight = 480;
699 b->minwidth = 16;
700 b->minheight = 16;
701 return 0;
702 }
703 case VIDIOCGCHAN:
704 {
705 struct video_channel *v = arg;
706 if(v->channel<0 || v->channel>3)
707 return -EINVAL;
708 v->flags=0;
709 v->tuners=1;
710 /* Good question.. its composite or SVHS so.. */
711 v->type = VIDEO_TYPE_CAMERA;
712 switch(v->channel)
713 {
714 case 0:
715 strcpy(v->name, "Composite");break;
716 case 1:
717 strcpy(v->name, "SVideo");break;
718 case 2:
719 strcpy(v->name, "Composite(VCR)");break;
720 case 3:
721 strcpy(v->name, "SVideo(VCR)");break;
722 }
723 return 0;
724 }
725 case VIDIOCSCHAN:
726 {
727 struct video_channel *v = arg;
728 if(v->channel<0 || v->channel>3)
729 return -EINVAL;
730 mutex_lock(&pd->lock);
731 pms_videosource(v->channel&1);
732 pms_vcrinput(v->channel>>1);
733 mutex_unlock(&pd->lock);
734 return 0;
735 }
736 case VIDIOCGTUNER:
737 {
738 struct video_tuner *v = arg;
739 if(v->tuner)
740 return -EINVAL;
741 strcpy(v->name, "Format");
742 v->rangelow=0;
743 v->rangehigh=0;
744 v->flags= VIDEO_TUNER_PAL|VIDEO_TUNER_NTSC|VIDEO_TUNER_SECAM;
745 switch(standard)
746 {
747 case 0:
748 v->mode = VIDEO_MODE_AUTO;
749 break;
750 case 1:
751 v->mode = VIDEO_MODE_NTSC;
752 break;
753 case 2:
754 v->mode = VIDEO_MODE_PAL;
755 break;
756 case 3:
757 v->mode = VIDEO_MODE_SECAM;
758 break;
759 }
760 return 0;
761 }
762 case VIDIOCSTUNER:
763 {
764 struct video_tuner *v = arg;
765 if(v->tuner)
766 return -EINVAL;
767 mutex_lock(&pd->lock);
768 switch(v->mode)
769 {
770 case VIDEO_MODE_AUTO:
771 pms_framerate(25);
772 pms_secamcross(0);
773 pms_format(0);
774 break;
775 case VIDEO_MODE_NTSC:
776 pms_framerate(30);
777 pms_secamcross(0);
778 pms_format(1);
779 break;
780 case VIDEO_MODE_PAL:
781 pms_framerate(25);
782 pms_secamcross(0);
783 pms_format(2);
784 break;
785 case VIDEO_MODE_SECAM:
786 pms_framerate(25);
787 pms_secamcross(1);
788 pms_format(2);
789 break;
790 default:
791 mutex_unlock(&pd->lock);
792 return -EINVAL;
793 }
794 mutex_unlock(&pd->lock);
795 return 0;
796 }
797 case VIDIOCGPICT:
798 {
799 struct video_picture *p = arg;
800 *p = pd->picture;
801 return 0;
802 }
803 case VIDIOCSPICT:
804 {
805 struct video_picture *p = arg;
806 if(!((p->palette==VIDEO_PALETTE_RGB565 && p->depth==16)
807 ||(p->palette==VIDEO_PALETTE_RGB555 && p->depth==15)))
808 return -EINVAL;
809 pd->picture= *p;
810 678
811 /* 679 strlcpy(vcap->driver, dev->v4l2_dev.name, sizeof(vcap->driver));
812 * Now load the card. 680 strlcpy(vcap->card, "Mediavision PMS", sizeof(vcap->card));
813 */ 681 strlcpy(vcap->bus_info, "ISA", sizeof(vcap->bus_info));
682 vcap->version = KERNEL_VERSION(0, 0, 3);
683 vcap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE;
684 return 0;
685}
814 686
815 mutex_lock(&pd->lock); 687static int pms_enum_input(struct file *file, void *fh, struct v4l2_input *vin)
816 pms_brightness(p->brightness>>8); 688{
817 pms_hue(p->hue>>8); 689 static const char *inputs[4] = {
818 pms_colour(p->colour>>8); 690 "Composite",
819 pms_contrast(p->contrast>>8); 691 "S-Video",
820 mutex_unlock(&pd->lock); 692 "Composite (VCR)",
821 return 0; 693 "S-Video (VCR)"
822 } 694 };
823 case VIDIOCSWIN: 695
824 { 696 if (vin->index > 3)
825 struct video_window *vw = arg; 697 return -EINVAL;
826 if(vw->flags) 698 strlcpy(vin->name, inputs[vin->index], sizeof(vin->name));
827 return -EINVAL; 699 vin->type = V4L2_INPUT_TYPE_CAMERA;
828 if(vw->clipcount) 700 vin->audioset = 0;
829 return -EINVAL; 701 vin->tuner = 0;
830 if(vw->height<16||vw->height>480) 702 vin->std = V4L2_STD_ALL;
831 return -EINVAL; 703 vin->status = 0;
832 if(vw->width<16||vw->width>640) 704 return 0;
833 return -EINVAL; 705}
834 pd->width=vw->width; 706
835 pd->height=vw->height; 707static int pms_g_input(struct file *file, void *fh, unsigned int *inp)
836 mutex_lock(&pd->lock); 708{
837 pms_resolution(pd->width, pd->height); 709 struct pms *dev = video_drvdata(file);
838 mutex_unlock(&pd->lock); /* Ok we figured out what to use from our wide choice */ 710
839 return 0; 711 *inp = dev->input;
840 } 712 return 0;
841 case VIDIOCGWIN: 713}
842 { 714
843 struct video_window *vw = arg; 715static int pms_s_input(struct file *file, void *fh, unsigned int inp)
844 memset(vw,0,sizeof(*vw)); 716{
845 vw->width=pd->width; 717 struct pms *dev = video_drvdata(file);
846 vw->height=pd->height; 718
847 return 0; 719 if (inp > 3)
848 } 720 return -EINVAL;
849 case VIDIOCKEY: 721
850 return 0; 722 mutex_lock(&dev->lock);
851 case VIDIOCCAPTURE: 723 dev->input = inp;
852 case VIDIOCGFBUF: 724 pms_videosource(dev, inp & 1);
853 case VIDIOCSFBUF: 725 pms_vcrinput(dev, inp >> 1);
854 case VIDIOCGFREQ: 726 mutex_unlock(&dev->lock);
855 case VIDIOCSFREQ: 727 return 0;
856 case VIDIOCGAUDIO: 728}
857 case VIDIOCSAUDIO: 729
858 return -EINVAL; 730static int pms_g_std(struct file *file, void *fh, v4l2_std_id *std)
859 default: 731{
860 return -ENOIOCTLCMD; 732 struct pms *dev = video_drvdata(file);
733
734 *std = dev->std;
735 return 0;
736}
737
738static int pms_s_std(struct file *file, void *fh, v4l2_std_id *std)
739{
740 struct pms *dev = video_drvdata(file);
741 int ret = 0;
742
743 dev->std = *std;
744 mutex_lock(&dev->lock);
745 if (dev->std & V4L2_STD_NTSC) {
746 pms_framerate(dev, 30);
747 pms_secamcross(dev, 0);
748 pms_format(dev, 1);
749 } else if (dev->std & V4L2_STD_PAL) {
750 pms_framerate(dev, 25);
751 pms_secamcross(dev, 0);
752 pms_format(dev, 2);
753 } else if (dev->std & V4L2_STD_SECAM) {
754 pms_framerate(dev, 25);
755 pms_secamcross(dev, 1);
756 pms_format(dev, 2);
757 } else {
758 ret = -EINVAL;
861 } 759 }
760 /*
761 switch (v->mode) {
762 case VIDEO_MODE_AUTO:
763 pms_framerate(dev, 25);
764 pms_secamcross(dev, 0);
765 pms_format(dev, 0);
766 break;
767 }*/
768 mutex_unlock(&dev->lock);
862 return 0; 769 return 0;
863} 770}
864 771
865static long pms_ioctl(struct file *file, 772static int pms_queryctrl(struct file *file, void *priv,
866 unsigned int cmd, unsigned long arg) 773 struct v4l2_queryctrl *qc)
867{ 774{
868 return video_usercopy(file, cmd, arg, pms_do_ioctl); 775 switch (qc->id) {
776 case V4L2_CID_BRIGHTNESS:
777 return v4l2_ctrl_query_fill(qc, 0, 255, 1, 139);
778 case V4L2_CID_CONTRAST:
779 return v4l2_ctrl_query_fill(qc, 0, 255, 1, 70);
780 case V4L2_CID_SATURATION:
781 return v4l2_ctrl_query_fill(qc, 0, 255, 1, 64);
782 case V4L2_CID_HUE:
783 return v4l2_ctrl_query_fill(qc, 0, 255, 1, 0);
784 }
785 return -EINVAL;
786}
787
788static int pms_g_ctrl(struct file *file, void *priv,
789 struct v4l2_control *ctrl)
790{
791 struct pms *dev = video_drvdata(file);
792 int ret = 0;
793
794 switch (ctrl->id) {
795 case V4L2_CID_BRIGHTNESS:
796 ctrl->value = dev->brightness;
797 break;
798 case V4L2_CID_CONTRAST:
799 ctrl->value = dev->contrast;
800 break;
801 case V4L2_CID_SATURATION:
802 ctrl->value = dev->saturation;
803 break;
804 case V4L2_CID_HUE:
805 ctrl->value = dev->hue;
806 break;
807 default:
808 ret = -EINVAL;
809 break;
810 }
811 return ret;
812}
813
814static int pms_s_ctrl(struct file *file, void *priv,
815 struct v4l2_control *ctrl)
816{
817 struct pms *dev = video_drvdata(file);
818 int ret = 0;
819
820 mutex_lock(&dev->lock);
821 switch (ctrl->id) {
822 case V4L2_CID_BRIGHTNESS:
823 dev->brightness = ctrl->value;
824 pms_brightness(dev, dev->brightness);
825 break;
826 case V4L2_CID_CONTRAST:
827 dev->contrast = ctrl->value;
828 pms_contrast(dev, dev->contrast);
829 break;
830 case V4L2_CID_SATURATION:
831 dev->saturation = ctrl->value;
832 pms_saturation(dev, dev->saturation);
833 break;
834 case V4L2_CID_HUE:
835 dev->hue = ctrl->value;
836 pms_hue(dev, dev->hue);
837 break;
838 default:
839 ret = -EINVAL;
840 break;
841 }
842 mutex_unlock(&dev->lock);
843 return ret;
844}
845
846static int pms_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
847{
848 struct pms *dev = video_drvdata(file);
849 struct v4l2_pix_format *pix = &fmt->fmt.pix;
850
851 pix->width = dev->width;
852 pix->height = dev->height;
853 pix->pixelformat = dev->width == 15 ?
854 V4L2_PIX_FMT_RGB555 : V4L2_PIX_FMT_RGB565;
855 pix->field = V4L2_FIELD_NONE;
856 pix->bytesperline = 2 * dev->width;
857 pix->sizeimage = 2 * dev->width * dev->height;
858 /* Just a guess */
859 pix->colorspace = V4L2_COLORSPACE_SRGB;
860 return 0;
861}
862
863static int pms_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
864{
865 struct v4l2_pix_format *pix = &fmt->fmt.pix;
866
867 if (pix->height < 16 || pix->height > 480)
868 return -EINVAL;
869 if (pix->width < 16 || pix->width > 640)
870 return -EINVAL;
871 if (pix->pixelformat != V4L2_PIX_FMT_RGB555 &&
872 pix->pixelformat != V4L2_PIX_FMT_RGB565)
873 return -EINVAL;
874 pix->field = V4L2_FIELD_NONE;
875 pix->bytesperline = 2 * pix->width;
876 pix->sizeimage = 2 * pix->width * pix->height;
877 /* Just a guess */
878 pix->colorspace = V4L2_COLORSPACE_SRGB;
879 return 0;
880}
881
882static int pms_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
883{
884 struct pms *dev = video_drvdata(file);
885 struct v4l2_pix_format *pix = &fmt->fmt.pix;
886 int ret = pms_try_fmt_vid_cap(file, fh, fmt);
887
888 if (ret)
889 return ret;
890 mutex_lock(&dev->lock);
891 dev->width = pix->width;
892 dev->height = pix->height;
893 dev->depth = (pix->pixelformat == V4L2_PIX_FMT_RGB555) ? 15 : 16;
894 pms_resolution(dev, dev->width, dev->height);
895 /* Ok we figured out what to use from our wide choice */
896 mutex_unlock(&dev->lock);
897 return 0;
898}
899
900static int pms_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt)
901{
902 static struct v4l2_fmtdesc formats[] = {
903 { 0, 0, 0,
904 "RGB 5:5:5", V4L2_PIX_FMT_RGB555,
905 { 0, 0, 0, 0 }
906 },
907 { 0, 0, 0,
908 "RGB 5:6:5", V4L2_PIX_FMT_RGB565,
909 { 0, 0, 0, 0 }
910 },
911 };
912 enum v4l2_buf_type type = fmt->type;
913
914 if (fmt->index > 1)
915 return -EINVAL;
916
917 *fmt = formats[fmt->index];
918 fmt->type = type;
919 return 0;
869} 920}
870 921
871static ssize_t pms_read(struct file *file, char __user *buf, 922static ssize_t pms_read(struct file *file, char __user *buf,
872 size_t count, loff_t *ppos) 923 size_t count, loff_t *ppos)
873{ 924{
874 struct video_device *v = video_devdata(file); 925 struct pms *dev = video_drvdata(file);
875 struct pms_device *pd=(struct pms_device *)v;
876 int len; 926 int len;
877 927
878 mutex_lock(&pd->lock); 928 mutex_lock(&dev->lock);
879 len=pms_capture(pd, buf, (pd->picture.depth==16)?0:1,count); 929 len = pms_capture(dev, buf, (dev->depth == 15), count);
880 mutex_unlock(&pd->lock); 930 mutex_unlock(&dev->lock);
881 return len; 931 return len;
882} 932}
883 933
884static int pms_exclusive_open(struct file *file) 934static int pms_exclusive_open(struct file *file)
885{ 935{
886 struct video_device *v = video_devdata(file); 936 struct pms *dev = video_drvdata(file);
887 struct pms_device *pd = (struct pms_device *)v;
888 937
889 return test_and_set_bit(0, &pd->in_use) ? -EBUSY : 0; 938 return test_and_set_bit(0, &dev->in_use) ? -EBUSY : 0;
890} 939}
891 940
892static int pms_exclusive_release(struct file *file) 941static int pms_exclusive_release(struct file *file)
893{ 942{
894 struct video_device *v = video_devdata(file); 943 struct pms *dev = video_drvdata(file);
895 struct pms_device *pd = (struct pms_device *)v;
896 944
897 clear_bit(0, &pd->in_use); 945 clear_bit(0, &dev->in_use);
898 return 0; 946 return 0;
899} 947}
900 948
@@ -902,78 +950,81 @@ static const struct v4l2_file_operations pms_fops = {
902 .owner = THIS_MODULE, 950 .owner = THIS_MODULE,
903 .open = pms_exclusive_open, 951 .open = pms_exclusive_open,
904 .release = pms_exclusive_release, 952 .release = pms_exclusive_release,
905 .ioctl = pms_ioctl, 953 .ioctl = video_ioctl2,
906 .read = pms_read, 954 .read = pms_read,
907}; 955};
908 956
909static struct video_device pms_template= 957static const struct v4l2_ioctl_ops pms_ioctl_ops = {
910{ 958 .vidioc_querycap = pms_querycap,
911 .name = "Mediavision PMS", 959 .vidioc_g_input = pms_g_input,
912 .fops = &pms_fops, 960 .vidioc_s_input = pms_s_input,
913 .release = video_device_release_empty, 961 .vidioc_enum_input = pms_enum_input,
962 .vidioc_g_std = pms_g_std,
963 .vidioc_s_std = pms_s_std,
964 .vidioc_queryctrl = pms_queryctrl,
965 .vidioc_g_ctrl = pms_g_ctrl,
966 .vidioc_s_ctrl = pms_s_ctrl,
967 .vidioc_enum_fmt_vid_cap = pms_enum_fmt_vid_cap,
968 .vidioc_g_fmt_vid_cap = pms_g_fmt_vid_cap,
969 .vidioc_s_fmt_vid_cap = pms_s_fmt_vid_cap,
970 .vidioc_try_fmt_vid_cap = pms_try_fmt_vid_cap,
914}; 971};
915 972
916static struct pms_device pms_device;
917
918
919/* 973/*
920 * Probe for and initialise the Mediavision PMS 974 * Probe for and initialise the Mediavision PMS
921 */ 975 */
922 976
923static int init_mediavision(void) 977static int init_mediavision(struct pms *dev)
924{ 978{
925 int id; 979 int id;
926 int idec, decst; 980 int idec, decst;
927 int i; 981 int i;
928 982 static const unsigned char i2c_defs[] = {
929 unsigned char i2c_defs[]={ 983 0x4c, 0x30, 0x00, 0xe8,
930 0x4C,0x30,0x00,0xE8, 984 0xb6, 0xe2, 0x00, 0x00,
931 0xB6,0xE2,0x00,0x00, 985 0xff, 0xff, 0x00, 0x00,
932 0xFF,0xFF,0x00,0x00, 986 0x00, 0x00, 0x78, 0x98,
933 0x00,0x00,0x78,0x98, 987 0x00, 0x00, 0x00, 0x00,
934 0x00,0x00,0x00,0x00, 988 0x34, 0x0a, 0xf4, 0xce,
935 0x34,0x0A,0xF4,0xCE, 989 0xe4
936 0xE4
937 }; 990 };
938 991
939 mem = ioremap(mem_base, 0x800); 992 dev->mem = ioremap(mem_base, 0x800);
940 if (!mem) 993 if (!dev->mem)
941 return -ENOMEM; 994 return -ENOMEM;
942 995
943 if (!request_region(0x9A01, 1, "Mediavision PMS config")) 996 if (!request_region(0x9a01, 1, "Mediavision PMS config")) {
944 { 997 printk(KERN_WARNING "mediavision: unable to detect: 0x9a01 in use.\n");
945 printk(KERN_WARNING "mediavision: unable to detect: 0x9A01 in use.\n"); 998 iounmap(dev->mem);
946 iounmap(mem);
947 return -EBUSY; 999 return -EBUSY;
948 } 1000 }
949 if (!request_region(io_port, 3, "Mediavision PMS")) 1001 if (!request_region(dev->io, 3, "Mediavision PMS")) {
950 { 1002 printk(KERN_WARNING "mediavision: I/O port %d in use.\n", dev->io);
951 printk(KERN_WARNING "mediavision: I/O port %d in use.\n", io_port); 1003 release_region(0x9a01, 1);
952 release_region(0x9A01, 1); 1004 iounmap(dev->mem);
953 iounmap(mem);
954 return -EBUSY; 1005 return -EBUSY;
955 } 1006 }
956 outb(0xB8, 0x9A01); /* Unlock */ 1007 outb(0xb8, 0x9a01); /* Unlock */
957 outb(io_port>>4, 0x9A01); /* Set IO port */ 1008 outb(dev->io >> 4, 0x9a01); /* Set IO port */
958 1009
959 1010
960 id=mvv_read(3); 1011 id = mvv_read(dev, 3);
961 decst=pms_i2c_stat(0x43); 1012 decst = pms_i2c_stat(dev, 0x43);
962 1013
963 if(decst!=-1) 1014 if (decst != -1)
964 idec=2; 1015 idec = 2;
965 else if(pms_i2c_stat(0xb9)!=-1) 1016 else if (pms_i2c_stat(dev, 0xb9) != -1)
966 idec=3; 1017 idec = 3;
967 else if(pms_i2c_stat(0x8b)!=-1) 1018 else if (pms_i2c_stat(dev, 0x8b) != -1)
968 idec=1; 1019 idec = 1;
969 else 1020 else
970 idec=0; 1021 idec = 0;
971 1022
972 printk(KERN_INFO "PMS type is %d\n", idec); 1023 printk(KERN_INFO "PMS type is %d\n", idec);
973 if(idec == 0) { 1024 if (idec == 0) {
974 release_region(io_port, 3); 1025 release_region(dev->io, 3);
975 release_region(0x9A01, 1); 1026 release_region(0x9a01, 1);
976 iounmap(mem); 1027 iounmap(dev->mem);
977 return -ENODEV; 1028 return -ENODEV;
978 } 1029 }
979 1030
@@ -981,51 +1032,50 @@ static int init_mediavision(void)
981 * Ok we have a PMS of some sort 1032 * Ok we have a PMS of some sort
982 */ 1033 */
983 1034
984 mvv_write(0x04, mem_base>>12); /* Set the memory area */ 1035 mvv_write(dev, 0x04, mem_base >> 12); /* Set the memory area */
985 1036
986 /* Ok now load the defaults */ 1037 /* Ok now load the defaults */
987 1038
988 for(i=0;i<0x19;i++) 1039 for (i = 0; i < 0x19; i++) {
989 { 1040 if (i2c_defs[i] == 0xff)
990 if(i2c_defs[i]==0xFF) 1041 pms_i2c_andor(dev, 0x8a, i, 0x07, 0x00);
991 pms_i2c_andor(0x8A, i, 0x07,0x00);
992 else 1042 else
993 pms_i2c_write(0x8A, i, i2c_defs[i]); 1043 pms_i2c_write(dev, 0x8a, i, i2c_defs[i]);
994 } 1044 }
995 1045
996 pms_i2c_write(0xB8,0x00,0x12); 1046 pms_i2c_write(dev, 0xb8, 0x00, 0x12);
997 pms_i2c_write(0xB8,0x04,0x00); 1047 pms_i2c_write(dev, 0xb8, 0x04, 0x00);
998 pms_i2c_write(0xB8,0x07,0x00); 1048 pms_i2c_write(dev, 0xb8, 0x07, 0x00);
999 pms_i2c_write(0xB8,0x08,0x00); 1049 pms_i2c_write(dev, 0xb8, 0x08, 0x00);
1000 pms_i2c_write(0xB8,0x09,0xFF); 1050 pms_i2c_write(dev, 0xb8, 0x09, 0xff);
1001 pms_i2c_write(0xB8,0x0A,0x00); 1051 pms_i2c_write(dev, 0xb8, 0x0a, 0x00);
1002 pms_i2c_write(0xB8,0x0B,0x10); 1052 pms_i2c_write(dev, 0xb8, 0x0b, 0x10);
1003 pms_i2c_write(0xB8,0x10,0x03); 1053 pms_i2c_write(dev, 0xb8, 0x10, 0x03);
1004 1054
1005 mvv_write(0x01, 0x00); 1055 mvv_write(dev, 0x01, 0x00);
1006 mvv_write(0x05, 0xA0); 1056 mvv_write(dev, 0x05, 0xa0);
1007 mvv_write(0x08, 0x25); 1057 mvv_write(dev, 0x08, 0x25);
1008 mvv_write(0x09, 0x00); 1058 mvv_write(dev, 0x09, 0x00);
1009 mvv_write(0x0A, 0x20|MVVMEMORYWIDTH); 1059 mvv_write(dev, 0x0a, 0x20 | MVVMEMORYWIDTH);
1010 1060
1011 mvv_write(0x10, 0x02); 1061 mvv_write(dev, 0x10, 0x02);
1012 mvv_write(0x1E, 0x0C); 1062 mvv_write(dev, 0x1e, 0x0c);
1013 mvv_write(0x1F, 0x03); 1063 mvv_write(dev, 0x1f, 0x03);
1014 mvv_write(0x26, 0x06); 1064 mvv_write(dev, 0x26, 0x06);
1015 1065
1016 mvv_write(0x2B, 0x00); 1066 mvv_write(dev, 0x2b, 0x00);
1017 mvv_write(0x2C, 0x20); 1067 mvv_write(dev, 0x2c, 0x20);
1018 mvv_write(0x2D, 0x00); 1068 mvv_write(dev, 0x2d, 0x00);
1019 mvv_write(0x2F, 0x70); 1069 mvv_write(dev, 0x2f, 0x70);
1020 mvv_write(0x32, 0x00); 1070 mvv_write(dev, 0x32, 0x00);
1021 mvv_write(0x33, MVVMEMORYWIDTH); 1071 mvv_write(dev, 0x33, MVVMEMORYWIDTH);
1022 mvv_write(0x34, 0x00); 1072 mvv_write(dev, 0x34, 0x00);
1023 mvv_write(0x35, 0x00); 1073 mvv_write(dev, 0x35, 0x00);
1024 mvv_write(0x3A, 0x80); 1074 mvv_write(dev, 0x3a, 0x80);
1025 mvv_write(0x3B, 0x10); 1075 mvv_write(dev, 0x3b, 0x10);
1026 mvv_write(0x20, 0x00); 1076 mvv_write(dev, 0x20, 0x00);
1027 mvv_write(0x21, 0x00); 1077 mvv_write(dev, 0x21, 0x00);
1028 mvv_write(0x30, 0x22); 1078 mvv_write(dev, 0x30, 0x22);
1029 return 0; 1079 return 0;
1030} 1080}
1031 1081
@@ -1038,53 +1088,77 @@ static int enable;
1038module_param(enable, int, 0); 1088module_param(enable, int, 0);
1039#endif 1089#endif
1040 1090
1041static int __init init_pms_cards(void) 1091static int __init pms_init(void)
1042{ 1092{
1043 printk(KERN_INFO "Mediavision Pro Movie Studio driver 0.02\n"); 1093 struct pms *dev = &pms_card;
1094 struct v4l2_device *v4l2_dev = &dev->v4l2_dev;
1095 int res;
1096
1097 strlcpy(v4l2_dev->name, "pms", sizeof(v4l2_dev->name));
1098
1099 v4l2_info(v4l2_dev, "Mediavision Pro Movie Studio driver 0.03\n");
1044 1100
1045#ifndef MODULE 1101#ifndef MODULE
1046 if (!enable) { 1102 if (!enable) {
1047 printk(KERN_INFO "PMS: not enabled, use pms.enable=1 to " 1103 v4l2_err(v4l2_dev,
1048 "probe\n"); 1104 "PMS: not enabled, use pms.enable=1 to probe\n");
1049 return -ENODEV; 1105 return -ENODEV;
1050 } 1106 }
1051#endif 1107#endif
1052 1108
1053 data_port = io_port +1; 1109 dev->decoder = PHILIPS2;
1110 dev->io = io_port;
1111 dev->data = io_port + 1;
1054 1112
1055 if(init_mediavision()) 1113 if (init_mediavision(dev)) {
1056 { 1114 v4l2_err(v4l2_dev, "Board not found.\n");
1057 printk(KERN_INFO "Board not found.\n");
1058 return -ENODEV; 1115 return -ENODEV;
1059 } 1116 }
1060 memcpy(&pms_device, &pms_template, sizeof(pms_template));
1061 mutex_init(&pms_device.lock);
1062 pms_device.height=240;
1063 pms_device.width=320;
1064 pms_swsense(75);
1065 pms_resolution(320,240);
1066 return video_register_device((struct video_device *)&pms_device, VFL_TYPE_GRABBER, video_nr);
1067}
1068
1069module_param(io_port, int, 0);
1070module_param(mem_base, int, 0);
1071module_param(video_nr, int, 0);
1072MODULE_LICENSE("GPL");
1073 1117
1118 res = v4l2_device_register(NULL, v4l2_dev);
1119 if (res < 0) {
1120 v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
1121 return res;
1122 }
1074 1123
1075static void __exit shutdown_mediavision(void) 1124 strlcpy(dev->vdev.name, v4l2_dev->name, sizeof(dev->vdev.name));
1076{ 1125 dev->vdev.v4l2_dev = v4l2_dev;
1077 release_region(io_port,3); 1126 dev->vdev.fops = &pms_fops;
1078 release_region(0x9A01, 1); 1127 dev->vdev.ioctl_ops = &pms_ioctl_ops;
1128 dev->vdev.release = video_device_release_empty;
1129 video_set_drvdata(&dev->vdev, dev);
1130 mutex_init(&dev->lock);
1131 dev->std = V4L2_STD_NTSC_M;
1132 dev->height = 240;
1133 dev->width = 320;
1134 dev->depth = 15;
1135 dev->brightness = 139;
1136 dev->contrast = 70;
1137 dev->hue = 0;
1138 dev->saturation = 64;
1139 pms_swsense(dev, 75);
1140 pms_resolution(dev, 320, 240);
1141 pms_videosource(dev, 0);
1142 pms_vcrinput(dev, 0);
1143 if (video_register_device(&dev->vdev, VFL_TYPE_GRABBER, video_nr) < 0) {
1144 v4l2_device_unregister(&dev->v4l2_dev);
1145 release_region(dev->io, 3);
1146 release_region(0x9a01, 1);
1147 iounmap(dev->mem);
1148 return -EINVAL;
1149 }
1150 return 0;
1079} 1151}
1080 1152
1081static void __exit cleanup_pms_module(void) 1153static void __exit pms_exit(void)
1082{ 1154{
1083 shutdown_mediavision(); 1155 struct pms *dev = &pms_card;
1084 video_unregister_device((struct video_device *)&pms_device);
1085 iounmap(mem);
1086}
1087 1156
1088module_init(init_pms_cards); 1157 video_unregister_device(&dev->vdev);
1089module_exit(cleanup_pms_module); 1158 release_region(dev->io, 3);
1159 release_region(0x9a01, 1);
1160 iounmap(dev->mem);
1161}
1090 1162
1163module_init(pms_init);
1164module_exit(pms_exit);