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