aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/saa7110.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/saa7110.c')
-rw-r--r--drivers/media/video/saa7110.c210
1 files changed, 107 insertions, 103 deletions
diff --git a/drivers/media/video/saa7110.c b/drivers/media/video/saa7110.c
index 37860698f782..9ef6b2bb1b77 100644
--- a/drivers/media/video/saa7110.c
+++ b/drivers/media/video/saa7110.c
@@ -54,7 +54,7 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)");
54struct saa7110 { 54struct saa7110 {
55 u8 reg[SAA7110_NR_REG]; 55 u8 reg[SAA7110_NR_REG];
56 56
57 int norm; 57 v4l2_std_id norm;
58 int input; 58 int input;
59 int enable; 59 int enable;
60 int bright; 60 int bright;
@@ -176,7 +176,7 @@ static const unsigned char initseq[1 + SAA7110_NR_REG] = {
176 /* 0x30 */ 0x44, 0x71, 0x02, 0x8C, 0x02 176 /* 0x30 */ 0x44, 0x71, 0x02, 0x8C, 0x02
177}; 177};
178 178
179static int determine_norm(struct i2c_client *client) 179static v4l2_std_id determine_norm(struct i2c_client *client)
180{ 180{
181 DEFINE_WAIT(wait); 181 DEFINE_WAIT(wait);
182 struct saa7110 *decoder = i2c_get_clientdata(client); 182 struct saa7110 *decoder = i2c_get_clientdata(client);
@@ -198,11 +198,11 @@ static int determine_norm(struct i2c_client *client)
198 if (status & 0x20) { 198 if (status & 0x20) {
199 v4l_dbg(1, debug, client, "status=0x%02x (NTSC/no color)\n", status); 199 v4l_dbg(1, debug, client, "status=0x%02x (NTSC/no color)\n", status);
200 //saa7110_write(client,0x2E,0x81); 200 //saa7110_write(client,0x2E,0x81);
201 return VIDEO_MODE_NTSC; 201 return V4L2_STD_NTSC;
202 } 202 }
203 v4l_dbg(1, debug, client, "status=0x%02x (PAL/no color)\n", status); 203 v4l_dbg(1, debug, client, "status=0x%02x (PAL/no color)\n", status);
204 //saa7110_write(client,0x2E,0x9A); 204 //saa7110_write(client,0x2E,0x9A);
205 return VIDEO_MODE_PAL; 205 return V4L2_STD_PAL;
206 } 206 }
207 //saa7110_write(client,0x06,0x03); 207 //saa7110_write(client,0x06,0x03);
208 if (status & 0x20) { /* 60Hz */ 208 if (status & 0x20) { /* 60Hz */
@@ -211,7 +211,7 @@ static int determine_norm(struct i2c_client *client)
211 saa7110_write(client, 0x0F, 0x50); 211 saa7110_write(client, 0x0F, 0x50);
212 saa7110_write(client, 0x11, 0x2C); 212 saa7110_write(client, 0x11, 0x2C);
213 //saa7110_write(client,0x2E,0x81); 213 //saa7110_write(client,0x2E,0x81);
214 return VIDEO_MODE_NTSC; 214 return V4L2_STD_NTSC;
215 } 215 }
216 216
217 /* 50Hz -> PAL/SECAM */ 217 /* 50Hz -> PAL/SECAM */
@@ -228,10 +228,10 @@ static int determine_norm(struct i2c_client *client)
228 if ((status & 0x03) == 0x01) { 228 if ((status & 0x03) == 0x01) {
229 v4l_dbg(1, debug, client, "status=0x%02x (SECAM)\n", status); 229 v4l_dbg(1, debug, client, "status=0x%02x (SECAM)\n", status);
230 saa7110_write(client, 0x0D, 0x87); 230 saa7110_write(client, 0x0D, 0x87);
231 return VIDEO_MODE_SECAM; 231 return V4L2_STD_SECAM;
232 } 232 }
233 v4l_dbg(1, debug, client, "status=0x%02x (PAL)\n", status); 233 v4l_dbg(1, debug, client, "status=0x%02x (PAL)\n", status);
234 return VIDEO_MODE_PAL; 234 return V4L2_STD_PAL;
235} 235}
236 236
237static int 237static int
@@ -240,112 +240,81 @@ saa7110_command (struct i2c_client *client,
240 void *arg) 240 void *arg)
241{ 241{
242 struct saa7110 *decoder = i2c_get_clientdata(client); 242 struct saa7110 *decoder = i2c_get_clientdata(client);
243 struct v4l2_routing *route = arg;
244 v4l2_std_id std;
243 int v; 245 int v;
244 246
245 switch (cmd) { 247 switch (cmd) {
246 case 0: 248 case VIDIOC_INT_INIT:
247 //saa7110_write_block(client, initseq, sizeof(initseq)); 249 //saa7110_write_block(client, initseq, sizeof(initseq));
248 break; 250 break;
249 251
250 case DECODER_GET_CAPABILITIES: 252 case VIDIOC_INT_G_INPUT_STATUS:
251 {
252 struct video_decoder_capability *dc = arg;
253
254 dc->flags =
255 VIDEO_DECODER_PAL | VIDEO_DECODER_NTSC |
256 VIDEO_DECODER_SECAM | VIDEO_DECODER_AUTO;
257 dc->inputs = SAA7110_MAX_INPUT;
258 dc->outputs = SAA7110_MAX_OUTPUT;
259 break;
260 }
261
262 case DECODER_GET_STATUS:
263 { 253 {
254 int res = V4L2_IN_ST_NO_SIGNAL;
264 int status; 255 int status;
265 int res = 0;
266 256
267 status = saa7110_read(client); 257 status = saa7110_read(client);
268 v4l_dbg(1, debug, client, "status=0x%02x norm=%d\n", 258 v4l_dbg(1, debug, client, "status=0x%02x norm=%llx\n",
269 status, decoder->norm); 259 status, decoder->norm);
270 if (!(status & 0x40)) 260 if (!(status & 0x40))
271 res |= DECODER_STATUS_GOOD; 261 res = 0;
272 if (status & 0x03) 262 if (!(status & 0x03))
273 res |= DECODER_STATUS_COLOR; 263 res |= V4L2_IN_ST_NO_COLOR;
274 264
275 switch (decoder->norm) {
276 case VIDEO_MODE_NTSC:
277 res |= DECODER_STATUS_NTSC;
278 break;
279 case VIDEO_MODE_PAL:
280 res |= DECODER_STATUS_PAL;
281 break;
282 case VIDEO_MODE_SECAM:
283 res |= DECODER_STATUS_SECAM;
284 break;
285 }
286 *(int *) arg = res; 265 *(int *) arg = res;
287 break; 266 break;
288 } 267 }
289 268
290 case DECODER_SET_NORM: 269 case VIDIOC_QUERYSTD:
291 v = *(int *) arg; 270 {
292 if (decoder->norm != v) { 271 *(v4l2_std_id *)arg = determine_norm(client);
293 decoder->norm = v; 272 break;
273 }
274
275 case VIDIOC_S_STD:
276 std = *(v4l2_std_id *) arg;
277 if (decoder->norm != std) {
278 decoder->norm = std;
294 //saa7110_write(client, 0x06, 0x03); 279 //saa7110_write(client, 0x06, 0x03);
295 switch (v) { 280 if (std & V4L2_STD_NTSC) {
296 case VIDEO_MODE_NTSC:
297 saa7110_write(client, 0x0D, 0x86); 281 saa7110_write(client, 0x0D, 0x86);
298 saa7110_write(client, 0x0F, 0x50); 282 saa7110_write(client, 0x0F, 0x50);
299 saa7110_write(client, 0x11, 0x2C); 283 saa7110_write(client, 0x11, 0x2C);
300 //saa7110_write(client, 0x2E, 0x81); 284 //saa7110_write(client, 0x2E, 0x81);
301 v4l_dbg(1, debug, client, "switched to NTSC\n"); 285 v4l_dbg(1, debug, client, "switched to NTSC\n");
302 break; 286 } else if (std & V4L2_STD_PAL) {
303 case VIDEO_MODE_PAL:
304 saa7110_write(client, 0x0D, 0x86); 287 saa7110_write(client, 0x0D, 0x86);
305 saa7110_write(client, 0x0F, 0x10); 288 saa7110_write(client, 0x0F, 0x10);
306 saa7110_write(client, 0x11, 0x59); 289 saa7110_write(client, 0x11, 0x59);
307 //saa7110_write(client, 0x2E, 0x9A); 290 //saa7110_write(client, 0x2E, 0x9A);
308 v4l_dbg(1, debug, client, "switched to PAL\n"); 291 v4l_dbg(1, debug, client, "switched to PAL\n");
309 break; 292 } else if (std & V4L2_STD_SECAM) {
310 case VIDEO_MODE_SECAM:
311 saa7110_write(client, 0x0D, 0x87); 293 saa7110_write(client, 0x0D, 0x87);
312 saa7110_write(client, 0x0F, 0x10); 294 saa7110_write(client, 0x0F, 0x10);
313 saa7110_write(client, 0x11, 0x59); 295 saa7110_write(client, 0x11, 0x59);
314 //saa7110_write(client, 0x2E, 0x9A); 296 //saa7110_write(client, 0x2E, 0x9A);
315 v4l_dbg(1, debug, client, "switched to SECAM\n"); 297 v4l_dbg(1, debug, client, "switched to SECAM\n");
316 break; 298 } else {
317 case VIDEO_MODE_AUTO: 299 return -EINVAL;
318 v4l_dbg(1, debug, client, "switched to AUTO\n");
319 decoder->norm = determine_norm(client);
320 *(int *) arg = decoder->norm;
321 break;
322 default:
323 return -EPERM;
324 } 300 }
325 } 301 }
326 break; 302 break;
327 303
328 case DECODER_SET_INPUT: 304 case VIDIOC_INT_S_VIDEO_ROUTING:
329 v = *(int *) arg; 305 if (route->input < 0 || route->input >= SAA7110_MAX_INPUT) {
330 if (v < 0 || v >= SAA7110_MAX_INPUT) { 306 v4l_dbg(1, debug, client, "input=%d not available\n", route->input);
331 v4l_dbg(1, debug, client, "input=%d not available\n", v);
332 return -EINVAL; 307 return -EINVAL;
333 } 308 }
334 if (decoder->input != v) { 309 if (decoder->input != route->input) {
335 saa7110_selmux(client, v); 310 saa7110_selmux(client, route->input);
336 v4l_dbg(1, debug, client, "switched to input=%d\n", v); 311 v4l_dbg(1, debug, client, "switched to input=%d\n", route->input);
337 } 312 }
338 break; 313 break;
339 314
340 case DECODER_SET_OUTPUT: 315 case VIDIOC_STREAMON:
341 v = *(int *) arg; 316 case VIDIOC_STREAMOFF:
342 /* not much choice of outputs */ 317 v = cmd == VIDIOC_STREAMON;
343 if (v != 0)
344 return -EINVAL;
345 break;
346
347 case DECODER_ENABLE_OUTPUT:
348 v = *(int *) arg;
349 if (decoder->enable != v) { 318 if (decoder->enable != v) {
350 decoder->enable = v; 319 decoder->enable = v;
351 saa7110_write(client, 0x0E, v ? 0x18 : 0x80); 320 saa7110_write(client, 0x0E, v ? 0x18 : 0x80);
@@ -353,46 +322,81 @@ saa7110_command (struct i2c_client *client,
353 } 322 }
354 break; 323 break;
355 324
356 case DECODER_SET_PICTURE: 325 case VIDIOC_QUERYCTRL:
357 { 326 {
358 struct video_picture *pic = arg; 327 struct v4l2_queryctrl *qc = arg;
359 328
360 if (decoder->bright != pic->brightness) { 329 switch (qc->id) {
361 /* We want 0 to 255 we get 0-65535 */ 330 case V4L2_CID_BRIGHTNESS:
362 decoder->bright = pic->brightness; 331 return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128);
363 saa7110_write(client, 0x19, decoder->bright >> 8); 332 case V4L2_CID_CONTRAST:
364 } 333 case V4L2_CID_SATURATION:
365 if (decoder->contrast != pic->contrast) { 334 return v4l2_ctrl_query_fill(qc, 0, 127, 1, 64);
366 /* We want 0 to 127 we get 0-65535 */ 335 case V4L2_CID_HUE:
367 decoder->contrast = pic->contrast; 336 return v4l2_ctrl_query_fill(qc, -128, 127, 1, 0);
368 saa7110_write(client, 0x13, 337 default:
369 decoder->contrast >> 9); 338 return -EINVAL;
370 }
371 if (decoder->sat != pic->colour) {
372 /* We want 0 to 127 we get 0-65535 */
373 decoder->sat = pic->colour;
374 saa7110_write(client, 0x12, decoder->sat >> 9);
375 } 339 }
376 if (decoder->hue != pic->hue) { 340 break;
377 /* We want -128 to 127 we get 0-65535 */ 341 }
378 decoder->hue = pic->hue; 342
379 saa7110_write(client, 0x07, 343 case VIDIOC_G_CTRL:
380 (decoder->hue >> 8) - 128); 344 {
345 struct v4l2_control *ctrl = arg;
346
347 switch (ctrl->id) {
348 case V4L2_CID_BRIGHTNESS:
349 ctrl->value = decoder->bright;
350 break;
351 case V4L2_CID_CONTRAST:
352 ctrl->value = decoder->contrast;
353 break;
354 case V4L2_CID_SATURATION:
355 ctrl->value = decoder->sat;
356 break;
357 case V4L2_CID_HUE:
358 ctrl->value = decoder->hue;
359 break;
360 default:
361 return -EINVAL;
381 } 362 }
382 break; 363 break;
383 } 364 }
384 365
385 case DECODER_DUMP: 366 case VIDIOC_S_CTRL:
386 if (!debug) 367 {
368 struct v4l2_control *ctrl = arg;
369
370 switch (ctrl->id) {
371 case V4L2_CID_BRIGHTNESS:
372 if (decoder->bright != ctrl->value) {
373 decoder->bright = ctrl->value;
374 saa7110_write(client, 0x19, decoder->bright);
375 }
387 break; 376 break;
388 for (v = 0; v < SAA7110_NR_REG; v += 16) { 377 case V4L2_CID_CONTRAST:
389 int j; 378 if (decoder->contrast != ctrl->value) {
390 v4l_dbg(1, debug, client, "%02x:", v); 379 decoder->contrast = ctrl->value;
391 for (j = 0; j < 16 && v + j < SAA7110_NR_REG; j++) 380 saa7110_write(client, 0x13, decoder->contrast);
392 printk(KERN_CONT " %02x", decoder->reg[v + j]); 381 }
393 printk(KERN_CONT "\n"); 382 break;
383 case V4L2_CID_SATURATION:
384 if (decoder->sat != ctrl->value) {
385 decoder->sat = ctrl->value;
386 saa7110_write(client, 0x12, decoder->sat);
387 }
388 break;
389 case V4L2_CID_HUE:
390 if (decoder->hue != ctrl->value) {
391 decoder->hue = ctrl->value;
392 saa7110_write(client, 0x07, decoder->hue);
393 }
394 break;
395 default:
396 return -EINVAL;
394 } 397 }
395 break; 398 break;
399 }
396 400
397 default: 401 default:
398 v4l_dbg(1, debug, client, "unknown command %08x\n", cmd); 402 v4l_dbg(1, debug, client, "unknown command %08x\n", cmd);
@@ -429,7 +433,7 @@ static int saa7110_probe(struct i2c_client *client,
429 decoder = kzalloc(sizeof(struct saa7110), GFP_KERNEL); 433 decoder = kzalloc(sizeof(struct saa7110), GFP_KERNEL);
430 if (!decoder) 434 if (!decoder)
431 return -ENOMEM; 435 return -ENOMEM;
432 decoder->norm = VIDEO_MODE_PAL; 436 decoder->norm = V4L2_STD_PAL;
433 decoder->input = 0; 437 decoder->input = 0;
434 decoder->enable = 1; 438 decoder->enable = 1;
435 decoder->bright = 32768; 439 decoder->bright = 32768;