diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-02-21 14:10:30 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-02-21 14:10:30 -0500 |
commit | e695e10bc996d6f83df7d85f1011c8d00573f68b (patch) | |
tree | 3d0ba107ea8fe7d0090e3cfd5e36cdb4abcaab99 /drivers | |
parent | 3a5f10e3708e00c406f154bae412652ec3eb2b48 (diff) | |
parent | f6982d59480953a8f5a84c237a9dabff39f788ce (diff) |
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/mchehab/v4l-dvb
* 'master' of master.kernel.org:/pub/scm/linux/kernel/git/mchehab/v4l-dvb: (196 commits)
V4L/DVB (5253): Qt1010: whitespace / 80 column cleanups
V4L/DVB (5252): Qt1010: use ARRAY_SIZE macro when appropriate
V4L/DVB (5251): Qt1010: fix compiler warning
V4L/DVB (5249): Fix compiler warning in vivi.c
V4L/DVB (5247): Stv0297: Enable BER/UNC counting
V4L/DVB (5246): Budget-ci: IR handling fixups
V4L/DVB (5245): Dvb-ttpci: use i2c gate ctrl from stv0297 frontend driver
V4L/DVB (5244): Dvbdev: fix illegal re-usage of fileoperations struct
V4L/DVB (5178): Avoid race when deregistering the IR control for dvb-usb
V4L/DVB (5240): Qt1010: use i2c_gate_ctrl where appropriate
V4L/DVB (5239): Whitespace / 80-column cleanups
V4L/DVB (5238): Kconfig: qt1010 should be selected by gl861 and au6610
V4L/DVB (5237): Dvb: add new qt1010 tuner module
V4L/DVB (5236): Initial support for Sigmatek DVB-110 DVB-T
V4L/DVB (5235): Gl861: use parallel_ts
V4L/DVB (5234): Gl861: remove unneeded declaration
V4L/DVB (5233): Gl861: correct address of the bulk endpoint
V4L/DVB (5232): Gl861: correct oops when loading module
V4L/DVB (5231): Gl861: whitespace cleanups
V4L/DVB (5230): Gl861: remove NULL entry from gl861_properties
...
Diffstat (limited to 'drivers')
149 files changed, 8744 insertions, 4188 deletions
diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig index 87410dbd3df4..91d25798ae4a 100644 --- a/drivers/media/Kconfig +++ b/drivers/media/Kconfig | |||
@@ -70,6 +70,7 @@ config VIDEO_TUNER | |||
70 | depends on I2C | 70 | depends on I2C |
71 | 71 | ||
72 | config VIDEO_BUF | 72 | config VIDEO_BUF |
73 | depends on PCI | ||
73 | tristate | 74 | tristate |
74 | 75 | ||
75 | config VIDEO_BUF_DVB | 76 | config VIDEO_BUF_DVB |
diff --git a/drivers/media/common/Kconfig b/drivers/media/common/Kconfig index f33e5d973413..c120114c241b 100644 --- a/drivers/media/common/Kconfig +++ b/drivers/media/common/Kconfig | |||
@@ -5,8 +5,4 @@ config VIDEO_SAA7146 | |||
5 | config VIDEO_SAA7146_VV | 5 | config VIDEO_SAA7146_VV |
6 | tristate | 6 | tristate |
7 | select VIDEO_BUF | 7 | select VIDEO_BUF |
8 | select VIDEO_VIDEOBUF | ||
9 | select VIDEO_SAA7146 | 8 | select VIDEO_SAA7146 |
10 | |||
11 | config VIDEO_VIDEOBUF | ||
12 | tristate | ||
diff --git a/drivers/media/common/ir-functions.c b/drivers/media/common/ir-functions.c index 9a8dd8764c99..cbf7c0564889 100644 --- a/drivers/media/common/ir-functions.c +++ b/drivers/media/common/ir-functions.c | |||
@@ -256,6 +256,112 @@ int ir_decode_biphase(u32 *samples, int count, int low, int high) | |||
256 | return value; | 256 | return value; |
257 | } | 257 | } |
258 | 258 | ||
259 | /* RC5 decoding stuff, moved from bttv-input.c to share it with | ||
260 | * saa7134 */ | ||
261 | |||
262 | /* decode raw bit pattern to RC5 code */ | ||
263 | u32 ir_rc5_decode(unsigned int code) | ||
264 | { | ||
265 | unsigned int org_code = code; | ||
266 | unsigned int pair; | ||
267 | unsigned int rc5 = 0; | ||
268 | int i; | ||
269 | |||
270 | for (i = 0; i < 14; ++i) { | ||
271 | pair = code & 0x3; | ||
272 | code >>= 2; | ||
273 | |||
274 | rc5 <<= 1; | ||
275 | switch (pair) { | ||
276 | case 0: | ||
277 | case 2: | ||
278 | break; | ||
279 | case 1: | ||
280 | rc5 |= 1; | ||
281 | break; | ||
282 | case 3: | ||
283 | dprintk(1, "ir-common: ir_rc5_decode(%x) bad code\n", org_code); | ||
284 | return 0; | ||
285 | } | ||
286 | } | ||
287 | dprintk(1, "ir-common: code=%x, rc5=%x, start=%x, toggle=%x, address=%x, " | ||
288 | "instr=%x\n", rc5, org_code, RC5_START(rc5), | ||
289 | RC5_TOGGLE(rc5), RC5_ADDR(rc5), RC5_INSTR(rc5)); | ||
290 | return rc5; | ||
291 | } | ||
292 | |||
293 | void ir_rc5_timer_end(unsigned long data) | ||
294 | { | ||
295 | struct card_ir *ir = (struct card_ir *)data; | ||
296 | struct timeval tv; | ||
297 | unsigned long current_jiffies, timeout; | ||
298 | u32 gap; | ||
299 | u32 rc5 = 0; | ||
300 | |||
301 | /* get time */ | ||
302 | current_jiffies = jiffies; | ||
303 | do_gettimeofday(&tv); | ||
304 | |||
305 | /* avoid overflow with gap >1s */ | ||
306 | if (tv.tv_sec - ir->base_time.tv_sec > 1) { | ||
307 | gap = 200000; | ||
308 | } else { | ||
309 | gap = 1000000 * (tv.tv_sec - ir->base_time.tv_sec) + | ||
310 | tv.tv_usec - ir->base_time.tv_usec; | ||
311 | } | ||
312 | |||
313 | /* Allow some timmer jitter (RC5 is ~24ms anyway so this is ok) */ | ||
314 | if (gap < 28000) { | ||
315 | dprintk(1, "ir-common: spurious timer_end\n"); | ||
316 | return; | ||
317 | } | ||
318 | |||
319 | ir->active = 0; | ||
320 | if (ir->last_bit < 20) { | ||
321 | /* ignore spurious codes (caused by light/other remotes) */ | ||
322 | dprintk(1, "ir-common: short code: %x\n", ir->code); | ||
323 | } else { | ||
324 | ir->code = (ir->code << ir->shift_by) | 1; | ||
325 | rc5 = ir_rc5_decode(ir->code); | ||
326 | |||
327 | /* two start bits? */ | ||
328 | if (RC5_START(rc5) != ir->start) { | ||
329 | dprintk(1, "ir-common: rc5 start bits invalid: %u\n", RC5_START(rc5)); | ||
330 | |||
331 | /* right address? */ | ||
332 | } else if (RC5_ADDR(rc5) == ir->addr) { | ||
333 | u32 toggle = RC5_TOGGLE(rc5); | ||
334 | u32 instr = RC5_INSTR(rc5); | ||
335 | |||
336 | /* Good code, decide if repeat/repress */ | ||
337 | if (toggle != RC5_TOGGLE(ir->last_rc5) || | ||
338 | instr != RC5_INSTR(ir->last_rc5)) { | ||
339 | dprintk(1, "ir-common: instruction %x, toggle %x\n", instr, | ||
340 | toggle); | ||
341 | ir_input_nokey(ir->dev, &ir->ir); | ||
342 | ir_input_keydown(ir->dev, &ir->ir, instr, | ||
343 | instr); | ||
344 | } | ||
345 | |||
346 | /* Set/reset key-up timer */ | ||
347 | timeout = current_jiffies + (500 + ir->rc5_key_timeout | ||
348 | * HZ) / 1000; | ||
349 | mod_timer(&ir->timer_keyup, timeout); | ||
350 | |||
351 | /* Save code for repeat test */ | ||
352 | ir->last_rc5 = rc5; | ||
353 | } | ||
354 | } | ||
355 | } | ||
356 | |||
357 | void ir_rc5_timer_keyup(unsigned long data) | ||
358 | { | ||
359 | struct card_ir *ir = (struct card_ir *)data; | ||
360 | |||
361 | dprintk(1, "ir-common: key released\n"); | ||
362 | ir_input_nokey(ir->dev, &ir->ir); | ||
363 | } | ||
364 | |||
259 | EXPORT_SYMBOL_GPL(ir_input_init); | 365 | EXPORT_SYMBOL_GPL(ir_input_init); |
260 | EXPORT_SYMBOL_GPL(ir_input_nokey); | 366 | EXPORT_SYMBOL_GPL(ir_input_nokey); |
261 | EXPORT_SYMBOL_GPL(ir_input_keydown); | 367 | EXPORT_SYMBOL_GPL(ir_input_keydown); |
@@ -265,6 +371,10 @@ EXPORT_SYMBOL_GPL(ir_dump_samples); | |||
265 | EXPORT_SYMBOL_GPL(ir_decode_biphase); | 371 | EXPORT_SYMBOL_GPL(ir_decode_biphase); |
266 | EXPORT_SYMBOL_GPL(ir_decode_pulsedistance); | 372 | EXPORT_SYMBOL_GPL(ir_decode_pulsedistance); |
267 | 373 | ||
374 | EXPORT_SYMBOL_GPL(ir_rc5_decode); | ||
375 | EXPORT_SYMBOL_GPL(ir_rc5_timer_end); | ||
376 | EXPORT_SYMBOL_GPL(ir_rc5_timer_keyup); | ||
377 | |||
268 | /* | 378 | /* |
269 | * Local variables: | 379 | * Local variables: |
270 | * c-basic-offset: 8 | 380 | * c-basic-offset: 8 |
diff --git a/drivers/media/common/ir-keymaps.c b/drivers/media/common/ir-keymaps.c index 0e948a5c5a03..03b47a262f27 100644 --- a/drivers/media/common/ir-keymaps.c +++ b/drivers/media/common/ir-keymaps.c | |||
@@ -1606,3 +1606,174 @@ IR_KEYTAB_TYPE ir_codes_budget_ci_old[IR_KEYTAB_SIZE] = { | |||
1606 | }; | 1606 | }; |
1607 | 1607 | ||
1608 | EXPORT_SYMBOL_GPL(ir_codes_budget_ci_old); | 1608 | EXPORT_SYMBOL_GPL(ir_codes_budget_ci_old); |
1609 | |||
1610 | /* | ||
1611 | * Marc Fargas <telenieko@telenieko.com> | ||
1612 | * this is the remote control that comes with the asus p7131 | ||
1613 | * which has a label saying is "Model PC-39" | ||
1614 | */ | ||
1615 | IR_KEYTAB_TYPE ir_codes_asus_pc39[IR_KEYTAB_SIZE] = { | ||
1616 | /* Keys 0 to 9 */ | ||
1617 | [ 0x15 ] = KEY_0, | ||
1618 | [ 0x29 ] = KEY_1, | ||
1619 | [ 0x2d ] = KEY_2, | ||
1620 | [ 0x2b ] = KEY_3, | ||
1621 | [ 0x09 ] = KEY_4, | ||
1622 | [ 0x0d ] = KEY_5, | ||
1623 | [ 0x0b ] = KEY_6, | ||
1624 | [ 0x31 ] = KEY_7, | ||
1625 | [ 0x35 ] = KEY_8, | ||
1626 | [ 0x33 ] = KEY_9, | ||
1627 | |||
1628 | [ 0x3e ] = KEY_RADIO, /* radio */ | ||
1629 | [ 0x03 ] = KEY_MENU, /* dvd/menu */ | ||
1630 | [ 0x2a ] = KEY_VOLUMEUP, | ||
1631 | [ 0x19 ] = KEY_VOLUMEDOWN, | ||
1632 | [ 0x37 ] = KEY_UP, | ||
1633 | [ 0x3b ] = KEY_DOWN, | ||
1634 | [ 0x27 ] = KEY_LEFT, | ||
1635 | [ 0x2f ] = KEY_RIGHT, | ||
1636 | [ 0x25 ] = KEY_VIDEO, /* video */ | ||
1637 | [ 0x39 ] = KEY_AUDIO, /* music */ | ||
1638 | |||
1639 | [ 0x21 ] = KEY_TV, /* tv */ | ||
1640 | [ 0x1d ] = KEY_EXIT, /* back */ | ||
1641 | [ 0x0a ] = KEY_CHANNELUP, /* channel / program + */ | ||
1642 | [ 0x1b ] = KEY_CHANNELDOWN, /* channel / program - */ | ||
1643 | [ 0x1a ] = KEY_ENTER, /* enter */ | ||
1644 | |||
1645 | [ 0x06 ] = KEY_PAUSE, /* play/pause */ | ||
1646 | [ 0x1e ] = KEY_PREVIOUS, /* rew */ | ||
1647 | [ 0x26 ] = KEY_NEXT, /* forward */ | ||
1648 | [ 0x0e ] = KEY_REWIND, /* backward << */ | ||
1649 | [ 0x3a ] = KEY_FASTFORWARD, /* forward >> */ | ||
1650 | [ 0x36 ] = KEY_STOP, | ||
1651 | [ 0x2e ] = KEY_RECORD, /* recording */ | ||
1652 | [ 0x16 ] = KEY_POWER, /* the button that reads "close" */ | ||
1653 | |||
1654 | [ 0x11 ] = KEY_ZOOM, /* full screen */ | ||
1655 | [ 0x13 ] = KEY_MACRO, /* recall */ | ||
1656 | [ 0x23 ] = KEY_HOME, /* home */ | ||
1657 | [ 0x05 ] = KEY_PVR, /* picture */ | ||
1658 | [ 0x3d ] = KEY_MUTE, /* mute */ | ||
1659 | [ 0x01 ] = KEY_DVD, /* dvd */ | ||
1660 | }; | ||
1661 | |||
1662 | EXPORT_SYMBOL_GPL(ir_codes_asus_pc39); | ||
1663 | |||
1664 | |||
1665 | /* Encore ENLTV-FM - black plastic, white front cover with white glowing buttons | ||
1666 | Juan Pablo Sormani <sorman@gmail.com> */ | ||
1667 | IR_KEYTAB_TYPE ir_codes_encore_enltv[IR_KEYTAB_SIZE] = { | ||
1668 | |||
1669 | /* Power button does nothing, neither in Windows app, | ||
1670 | although it sends data (used for BIOS wakeup?) */ | ||
1671 | [ 0x0d ] = KEY_MUTE, | ||
1672 | |||
1673 | [ 0x1e ] = KEY_TV, | ||
1674 | [ 0x00 ] = KEY_VIDEO, | ||
1675 | [ 0x01 ] = KEY_AUDIO, /* music */ | ||
1676 | [ 0x02 ] = KEY_MHP, /* picture */ | ||
1677 | |||
1678 | [ 0x1f ] = KEY_1, | ||
1679 | [ 0x03 ] = KEY_2, | ||
1680 | [ 0x04 ] = KEY_3, | ||
1681 | [ 0x05 ] = KEY_4, | ||
1682 | [ 0x1c ] = KEY_5, | ||
1683 | [ 0x06 ] = KEY_6, | ||
1684 | [ 0x07 ] = KEY_7, | ||
1685 | [ 0x08 ] = KEY_8, | ||
1686 | [ 0x1d ] = KEY_9, | ||
1687 | [ 0x0a ] = KEY_0, | ||
1688 | |||
1689 | [ 0x09 ] = KEY_LIST, /* -/-- */ | ||
1690 | [ 0x0b ] = KEY_LAST, /* recall */ | ||
1691 | |||
1692 | [ 0x14 ] = KEY_HOME, /* win start menu */ | ||
1693 | [ 0x15 ] = KEY_EXIT, /* exit */ | ||
1694 | [ 0x16 ] = KEY_UP, | ||
1695 | [ 0x12 ] = KEY_DOWN, | ||
1696 | [ 0x0c ] = KEY_RIGHT, | ||
1697 | [ 0x17 ] = KEY_LEFT, | ||
1698 | |||
1699 | [ 0x18 ] = KEY_ENTER, /* OK */ | ||
1700 | |||
1701 | [ 0x0e ] = KEY_ESC, | ||
1702 | [ 0x13 ] = KEY_D, /* desktop */ | ||
1703 | [ 0x11 ] = KEY_TAB, | ||
1704 | [ 0x19 ] = KEY_SWITCHVIDEOMODE, /* switch */ | ||
1705 | |||
1706 | [ 0x1a ] = KEY_MENU, | ||
1707 | [ 0x1b ] = KEY_ZOOM, /* fullscreen */ | ||
1708 | [ 0x44 ] = KEY_TIME, /* time shift */ | ||
1709 | [ 0x40 ] = KEY_MODE, /* source */ | ||
1710 | |||
1711 | [ 0x5a ] = KEY_RECORD, | ||
1712 | [ 0x42 ] = KEY_PLAY, /* play/pause */ | ||
1713 | [ 0x45 ] = KEY_STOP, | ||
1714 | [ 0x43 ] = KEY_CAMERA, /* camera icon */ | ||
1715 | |||
1716 | [ 0x48 ] = KEY_REWIND, | ||
1717 | [ 0x4a ] = KEY_FASTFORWARD, | ||
1718 | [ 0x49 ] = KEY_PREVIOUS, | ||
1719 | [ 0x4b ] = KEY_NEXT, | ||
1720 | |||
1721 | [ 0x4c ] = KEY_FAVORITES, /* tv wall */ | ||
1722 | [ 0x4d ] = KEY_SOUND, /* DVD sound */ | ||
1723 | [ 0x4e ] = KEY_LANGUAGE, /* DVD lang */ | ||
1724 | [ 0x4f ] = KEY_TEXT, /* DVD text */ | ||
1725 | |||
1726 | [ 0x50 ] = KEY_SLEEP, /* shutdown */ | ||
1727 | [ 0x51 ] = KEY_MODE, /* stereo > main */ | ||
1728 | [ 0x52 ] = KEY_SELECT, /* stereo > sap */ | ||
1729 | [ 0x53 ] = KEY_PROG1, /* teletext */ | ||
1730 | |||
1731 | |||
1732 | [ 0x59 ] = KEY_RED, /* AP1 */ | ||
1733 | [ 0x41 ] = KEY_GREEN, /* AP2 */ | ||
1734 | [ 0x47 ] = KEY_YELLOW, /* AP3 */ | ||
1735 | [ 0x57 ] = KEY_BLUE, /* AP4 */ | ||
1736 | |||
1737 | |||
1738 | }; | ||
1739 | |||
1740 | EXPORT_SYMBOL_GPL(ir_codes_encore_enltv); | ||
1741 | |||
1742 | /* for the Technotrend 1500 bundled remote: */ | ||
1743 | IR_KEYTAB_TYPE ir_codes_tt_1500[IR_KEYTAB_SIZE] = { | ||
1744 | [ 0x01 ] = KEY_POWER, | ||
1745 | [ 0x02 ] = KEY_SHUFFLE, /* ? double-arrow key */ | ||
1746 | [ 0x03 ] = KEY_1, | ||
1747 | [ 0x04 ] = KEY_2, | ||
1748 | [ 0x05 ] = KEY_3, | ||
1749 | [ 0x06 ] = KEY_4, | ||
1750 | [ 0x07 ] = KEY_5, | ||
1751 | [ 0x08 ] = KEY_6, | ||
1752 | [ 0x09 ] = KEY_7, | ||
1753 | [ 0x0a ] = KEY_8, | ||
1754 | [ 0x0b ] = KEY_9, | ||
1755 | [ 0x0c ] = KEY_0, | ||
1756 | [ 0x0d ] = KEY_UP, | ||
1757 | [ 0x0e ] = KEY_LEFT, | ||
1758 | [ 0x0f ] = KEY_OK, | ||
1759 | [ 0x10 ] = KEY_RIGHT, | ||
1760 | [ 0x11 ] = KEY_DOWN, | ||
1761 | [ 0x12 ] = KEY_INFO, | ||
1762 | [ 0x13 ] = KEY_EXIT, | ||
1763 | [ 0x14 ] = KEY_RED, | ||
1764 | [ 0x15 ] = KEY_GREEN, | ||
1765 | [ 0x16 ] = KEY_YELLOW, | ||
1766 | [ 0x17 ] = KEY_BLUE, | ||
1767 | [ 0x18 ] = KEY_MUTE, | ||
1768 | [ 0x19 ] = KEY_TEXT, | ||
1769 | [ 0x1a ] = KEY_MODE, /* ? TV/Radio */ | ||
1770 | [ 0x21 ] = KEY_OPTION, | ||
1771 | [ 0x22 ] = KEY_EPG, | ||
1772 | [ 0x23 ] = KEY_CHANNELUP, | ||
1773 | [ 0x24 ] = KEY_CHANNELDOWN, | ||
1774 | [ 0x25 ] = KEY_VOLUMEUP, | ||
1775 | [ 0x26 ] = KEY_VOLUMEDOWN, | ||
1776 | [ 0x27 ] = KEY_SETUP, | ||
1777 | }; | ||
1778 | |||
1779 | EXPORT_SYMBOL_GPL(ir_codes_tt_1500); | ||
diff --git a/drivers/media/common/saa7146_fops.c b/drivers/media/common/saa7146_fops.c index b8dcfa165266..c18a5da64934 100644 --- a/drivers/media/common/saa7146_fops.c +++ b/drivers/media/common/saa7146_fops.c | |||
@@ -508,7 +508,7 @@ int saa7146_vv_release(struct saa7146_dev* dev) | |||
508 | 508 | ||
509 | DEB_EE(("dev:%p\n",dev)); | 509 | DEB_EE(("dev:%p\n",dev)); |
510 | 510 | ||
511 | pci_free_consistent(dev->pci, SAA7146_RPS_MEM, vv->d_clipping.cpu_addr, vv->d_clipping.dma_handle); | 511 | pci_free_consistent(dev->pci, SAA7146_CLIPPING_MEM, vv->d_clipping.cpu_addr, vv->d_clipping.dma_handle); |
512 | kfree(vv); | 512 | kfree(vv); |
513 | dev->vv_data = NULL; | 513 | dev->vv_data = NULL; |
514 | dev->vv_callback = NULL; | 514 | dev->vv_callback = NULL; |
diff --git a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c index c2b35e366242..752cf79c532f 100644 --- a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c +++ b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c | |||
@@ -385,9 +385,9 @@ static int alps_tdee4_stv0297_tuner_set_params(struct dvb_frontend* fe, | |||
385 | else buf[3] = 0x88; | 385 | else buf[3] = 0x88; |
386 | 386 | ||
387 | if (fe->ops.i2c_gate_ctrl) | 387 | if (fe->ops.i2c_gate_ctrl) |
388 | fe->ops.i2c_gate_ctrl(fe, 1); | 388 | fe->ops.i2c_gate_ctrl(fe, 0); |
389 | deb_tuner("tuner buffer for %d Hz: %x %x %x %x\n",fep->frequency, buf[0],buf[1],buf[2],buf[3]); | 389 | deb_tuner("tuner buffer for %d Hz: %x %x %x %x\n",fep->frequency, buf[0],buf[1],buf[2],buf[3]); |
390 | ret = fc->i2c_request(fc,FC_WRITE,FC_I2C_PORT_TUNER,0x61,buf[0],&buf[1],3); | 390 | ret = fc->i2c_request(fc, FC_WRITE, FC_I2C_PORT_TUNER, 0x61, buf[0], &buf[1], 3); |
391 | deb_tuner("tuner write returned: %d\n",ret); | 391 | deb_tuner("tuner write returned: %d\n",ret); |
392 | 392 | ||
393 | return 0; | 393 | return 0; |
@@ -398,91 +398,71 @@ static u8 alps_tdee4_stv0297_inittab[] = { | |||
398 | 0x80, 0x00, | 398 | 0x80, 0x00, |
399 | 0x81, 0x01, | 399 | 0x81, 0x01, |
400 | 0x81, 0x00, | 400 | 0x81, 0x00, |
401 | 0x00, 0x09, | 401 | 0x00, 0x48, |
402 | 0x01, 0x69, | 402 | 0x01, 0x58, |
403 | 0x03, 0x00, | 403 | 0x03, 0x00, |
404 | 0x04, 0x00, | 404 | 0x04, 0x00, |
405 | 0x07, 0x00, | 405 | 0x07, 0x00, |
406 | 0x08, 0x00, | 406 | 0x08, 0x00, |
407 | 0x20, 0x00, | ||
408 | 0x21, 0x40, | ||
409 | 0x22, 0x00, | ||
410 | 0x23, 0x00, | ||
411 | 0x24, 0x40, | ||
412 | 0x25, 0x88, | ||
413 | 0x30, 0xff, | 407 | 0x30, 0xff, |
414 | 0x31, 0x00, | 408 | 0x31, 0x9d, |
415 | 0x32, 0xff, | 409 | 0x32, 0xff, |
416 | 0x33, 0x00, | 410 | 0x33, 0x00, |
417 | 0x34, 0x50, | 411 | 0x34, 0x29, |
418 | 0x35, 0x7f, | 412 | 0x35, 0x55, |
419 | 0x36, 0x00, | 413 | 0x36, 0x80, |
420 | 0x37, 0x20, | 414 | 0x37, 0x6e, |
421 | 0x38, 0x00, | 415 | 0x38, 0x9c, |
422 | 0x40, 0x1c, | 416 | 0x40, 0x1a, |
423 | 0x41, 0xff, | 417 | 0x41, 0xfe, |
424 | 0x42, 0x29, | 418 | 0x42, 0x33, |
425 | 0x43, 0x00, | 419 | 0x43, 0x00, |
426 | 0x44, 0xff, | 420 | 0x44, 0xff, |
427 | 0x45, 0x00, | 421 | 0x45, 0x00, |
428 | 0x46, 0x00, | 422 | 0x46, 0x00, |
429 | 0x49, 0x04, | 423 | 0x49, 0x04, |
430 | 0x4a, 0x00, | 424 | 0x4a, 0x51, |
431 | 0x4b, 0xf8, | 425 | 0x4b, 0xf8, |
432 | 0x52, 0x30, | 426 | 0x52, 0x30, |
433 | 0x55, 0xae, | 427 | 0x53, 0x06, |
434 | 0x56, 0x47, | 428 | 0x59, 0x06, |
435 | 0x57, 0xe1, | 429 | 0x5a, 0x5e, |
436 | 0x58, 0x3a, | 430 | 0x5b, 0x04, |
437 | 0x5a, 0x1e, | 431 | 0x61, 0x49, |
438 | 0x5b, 0x34, | 432 | 0x62, 0x0a, |
439 | 0x60, 0x00, | ||
440 | 0x63, 0x00, | ||
441 | 0x64, 0x00, | ||
442 | 0x65, 0x00, | ||
443 | 0x66, 0x00, | ||
444 | 0x67, 0x00, | ||
445 | 0x68, 0x00, | ||
446 | 0x69, 0x00, | ||
447 | 0x6a, 0x02, | ||
448 | 0x6b, 0x00, | ||
449 | 0x70, 0xff, | 433 | 0x70, 0xff, |
450 | 0x71, 0x00, | 434 | 0x71, 0x04, |
451 | 0x72, 0x00, | 435 | 0x72, 0x00, |
452 | 0x73, 0x00, | 436 | 0x73, 0x00, |
453 | 0x74, 0x0c, | 437 | 0x74, 0x0c, |
454 | 0x80, 0x00, | 438 | 0x80, 0x20, |
455 | 0x81, 0x00, | 439 | 0x81, 0x00, |
456 | 0x82, 0x00, | 440 | 0x82, 0x30, |
457 | 0x83, 0x00, | 441 | 0x83, 0x00, |
458 | 0x84, 0x04, | 442 | 0x84, 0x04, |
459 | 0x85, 0x80, | 443 | 0x85, 0x22, |
460 | 0x86, 0x24, | 444 | 0x86, 0x08, |
461 | 0x87, 0x78, | 445 | 0x87, 0x1b, |
462 | 0x88, 0x10, | 446 | 0x88, 0x00, |
463 | 0x89, 0x00, | 447 | 0x89, 0x00, |
464 | 0x90, 0x01, | 448 | 0x90, 0x00, |
465 | 0x91, 0x01, | 449 | 0x91, 0x04, |
466 | 0xa0, 0x04, | 450 | 0xa0, 0x86, |
467 | 0xa1, 0x00, | 451 | 0xa1, 0x00, |
468 | 0xa2, 0x00, | 452 | 0xa2, 0x00, |
469 | 0xb0, 0x91, | 453 | 0xb0, 0x91, |
470 | 0xb1, 0x0b, | 454 | 0xb1, 0x0b, |
471 | 0xc0, 0x53, | 455 | 0xc0, 0x5b, |
472 | 0xc1, 0x70, | 456 | 0xc1, 0x10, |
473 | 0xc2, 0x12, | 457 | 0xc2, 0x12, |
474 | 0xd0, 0x00, | 458 | 0xd0, 0x02, |
475 | 0xd1, 0x00, | 459 | 0xd1, 0x00, |
476 | 0xd2, 0x00, | 460 | 0xd2, 0x00, |
477 | 0xd3, 0x00, | 461 | 0xd3, 0x00, |
478 | 0xd4, 0x00, | 462 | 0xd4, 0x02, |
479 | 0xd5, 0x00, | 463 | 0xd5, 0x00, |
480 | 0xde, 0x00, | 464 | 0xde, 0x00, |
481 | 0xdf, 0x00, | 465 | 0xdf, 0x01, |
482 | 0x61, 0x49, | ||
483 | 0x62, 0x0b, | ||
484 | 0x53, 0x08, | ||
485 | 0x59, 0x08, | ||
486 | 0xff, 0xff, | 466 | 0xff, 0xff, |
487 | }; | 467 | }; |
488 | 468 | ||
diff --git a/drivers/media/dvb/bt8xx/bt878.c b/drivers/media/dvb/bt8xx/bt878.c index 329a51c18562..83b090ef2445 100644 --- a/drivers/media/dvb/bt8xx/bt878.c +++ b/drivers/media/dvb/bt8xx/bt878.c | |||
@@ -390,6 +390,7 @@ static struct cards card_list[] __devinitdata = { | |||
390 | { 0xfc00270f, BTTV_BOARD_TWINHAN_DST, "ChainTech digitop DST-1000 DVB-S" }, | 390 | { 0xfc00270f, BTTV_BOARD_TWINHAN_DST, "ChainTech digitop DST-1000 DVB-S" }, |
391 | { 0x07711461, BTTV_BOARD_AVDVBT_771, "AVermedia AverTV DVB-T 771" }, | 391 | { 0x07711461, BTTV_BOARD_AVDVBT_771, "AVermedia AverTV DVB-T 771" }, |
392 | { 0xdb1018ac, BTTV_BOARD_DVICO_DVBT_LITE, "DViCO FusionHDTV DVB-T Lite" }, | 392 | { 0xdb1018ac, BTTV_BOARD_DVICO_DVBT_LITE, "DViCO FusionHDTV DVB-T Lite" }, |
393 | { 0xdb1118ac, BTTV_BOARD_DVICO_DVBT_LITE, "Ultraview DVB-T Lite" }, | ||
393 | { 0xd50018ac, BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE, "DViCO FusionHDTV 5 Lite" }, | 394 | { 0xd50018ac, BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE, "DViCO FusionHDTV 5 Lite" }, |
394 | { 0x20007063, BTTV_BOARD_PC_HDTV, "pcHDTV HD-2000 TV" }, | 395 | { 0x20007063, BTTV_BOARD_PC_HDTV, "pcHDTV HD-2000 TV" }, |
395 | { 0x00261822, BTTV_BOARD_TWINHAN_DST, "DNTV Live! Mini" }, | 396 | { 0x00261822, BTTV_BOARD_TWINHAN_DST, "DNTV Live! Mini" }, |
diff --git a/drivers/media/dvb/bt8xx/dst.c b/drivers/media/dvb/bt8xx/dst.c index 9f72b7000c08..0393a3d19920 100644 --- a/drivers/media/dvb/bt8xx/dst.c +++ b/drivers/media/dvb/bt8xx/dst.c | |||
@@ -1161,7 +1161,7 @@ static int dst_get_device_id(struct dst_state *state) | |||
1161 | } | 1161 | } |
1162 | } | 1162 | } |
1163 | 1163 | ||
1164 | if (i >= sizeof (dst_tlist) / sizeof (dst_tlist [0])) { | 1164 | if (i >= ARRAY_SIZE(dst_tlist)) { |
1165 | dprintk(verbose, DST_ERROR, 1, "Unable to recognize %s or %s", &state->rxbuffer[0], &state->rxbuffer[1]); | 1165 | dprintk(verbose, DST_ERROR, 1, "Unable to recognize %s or %s", &state->rxbuffer[0], &state->rxbuffer[1]); |
1166 | dprintk(verbose, DST_ERROR, 1, "please email linux-dvb@linuxtv.org with this type in"); | 1166 | dprintk(verbose, DST_ERROR, 1, "please email linux-dvb@linuxtv.org with this type in"); |
1167 | use_dst_type = DST_TYPE_IS_SAT; | 1167 | use_dst_type = DST_TYPE_IS_SAT; |
diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/drivers/media/dvb/bt8xx/dvb-bt8xx.c index 3e35931af35d..58f69f6ae391 100644 --- a/drivers/media/dvb/bt8xx/dvb-bt8xx.c +++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/module.h> | 23 | #include <linux/module.h> |
24 | #include <linux/moduleparam.h> | 24 | #include <linux/moduleparam.h> |
25 | #include <linux/init.h> | 25 | #include <linux/init.h> |
26 | #include <linux/kernel.h> | ||
26 | #include <linux/device.h> | 27 | #include <linux/device.h> |
27 | #include <linux/delay.h> | 28 | #include <linux/delay.h> |
28 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
@@ -213,7 +214,7 @@ static int cx24108_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend | |||
213 | freq = 2150000; /* satellite IF is 950..2150MHz */ | 214 | freq = 2150000; /* satellite IF is 950..2150MHz */ |
214 | 215 | ||
215 | /* decide which VCO to use for the input frequency */ | 216 | /* decide which VCO to use for the input frequency */ |
216 | for(i=1;(i<sizeof(osci)/sizeof(osci[0]))&&(osci[i]<freq);i++); | 217 | for(i = 1; (i < ARRAY_SIZE(osci)) && (osci[i] < freq); i++); |
217 | printk("cx24108 debug: select vco #%d (f=%d)\n",i,freq); | 218 | printk("cx24108 debug: select vco #%d (f=%d)\n",i,freq); |
218 | band=bandsel[i]; | 219 | band=bandsel[i]; |
219 | /* the gain values must be set by SetSymbolrate */ | 220 | /* the gain values must be set by SetSymbolrate */ |
diff --git a/drivers/media/dvb/cinergyT2/cinergyT2.c b/drivers/media/dvb/cinergyT2/cinergyT2.c index d64b96cb0c46..a6cbbdd262d6 100644 --- a/drivers/media/dvb/cinergyT2/cinergyT2.c +++ b/drivers/media/dvb/cinergyT2/cinergyT2.c | |||
@@ -819,6 +819,11 @@ static int cinergyt2_register_rc(struct cinergyt2 *cinergyt2) | |||
819 | set_bit(rc_keys[i + 2], input_dev->keybit); | 819 | set_bit(rc_keys[i + 2], input_dev->keybit); |
820 | input_dev->keycodesize = 0; | 820 | input_dev->keycodesize = 0; |
821 | input_dev->keycodemax = 0; | 821 | input_dev->keycodemax = 0; |
822 | input_dev->id.bustype = BUS_USB; | ||
823 | input_dev->id.vendor = cinergyt2->udev->descriptor.idVendor; | ||
824 | input_dev->id.product = cinergyt2->udev->descriptor.idProduct; | ||
825 | input_dev->id.version = 1; | ||
826 | input_dev->cdev.dev = &cinergyt2->udev->dev; | ||
822 | 827 | ||
823 | err = input_register_device(input_dev); | 828 | err = input_register_device(input_dev); |
824 | if (err) { | 829 | if (err) { |
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index 7c42d53a1cc7..a21a894d3f98 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/list.h> | 36 | #include <linux/list.h> |
37 | #include <linux/freezer.h> | 37 | #include <linux/freezer.h> |
38 | #include <linux/jiffies.h> | 38 | #include <linux/jiffies.h> |
39 | #include <linux/kthread.h> | ||
39 | #include <asm/processor.h> | 40 | #include <asm/processor.h> |
40 | 41 | ||
41 | #include "dvb_frontend.h" | 42 | #include "dvb_frontend.h" |
@@ -100,7 +101,7 @@ struct dvb_frontend_private { | |||
100 | struct semaphore sem; | 101 | struct semaphore sem; |
101 | struct list_head list_head; | 102 | struct list_head list_head; |
102 | wait_queue_head_t wait_queue; | 103 | wait_queue_head_t wait_queue; |
103 | pid_t thread_pid; | 104 | struct task_struct *thread; |
104 | unsigned long release_jiffies; | 105 | unsigned long release_jiffies; |
105 | unsigned int exit; | 106 | unsigned int exit; |
106 | unsigned int wakeup; | 107 | unsigned int wakeup; |
@@ -508,19 +509,11 @@ static int dvb_frontend_thread(void *data) | |||
508 | struct dvb_frontend *fe = data; | 509 | struct dvb_frontend *fe = data; |
509 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | 510 | struct dvb_frontend_private *fepriv = fe->frontend_priv; |
510 | unsigned long timeout; | 511 | unsigned long timeout; |
511 | char name [15]; | ||
512 | fe_status_t s; | 512 | fe_status_t s; |
513 | struct dvb_frontend_parameters *params; | 513 | struct dvb_frontend_parameters *params; |
514 | 514 | ||
515 | dprintk("%s\n", __FUNCTION__); | 515 | dprintk("%s\n", __FUNCTION__); |
516 | 516 | ||
517 | snprintf (name, sizeof(name), "kdvb-fe-%i", fe->dvb->num); | ||
518 | |||
519 | lock_kernel(); | ||
520 | daemonize(name); | ||
521 | sigfillset(¤t->blocked); | ||
522 | unlock_kernel(); | ||
523 | |||
524 | fepriv->check_wrapped = 0; | 517 | fepriv->check_wrapped = 0; |
525 | fepriv->quality = 0; | 518 | fepriv->quality = 0; |
526 | fepriv->delay = 3*HZ; | 519 | fepriv->delay = 3*HZ; |
@@ -532,16 +525,18 @@ static int dvb_frontend_thread(void *data) | |||
532 | 525 | ||
533 | while (1) { | 526 | while (1) { |
534 | up(&fepriv->sem); /* is locked when we enter the thread... */ | 527 | up(&fepriv->sem); /* is locked when we enter the thread... */ |
535 | 528 | restart: | |
536 | timeout = wait_event_interruptible_timeout(fepriv->wait_queue, | 529 | timeout = wait_event_interruptible_timeout(fepriv->wait_queue, |
537 | dvb_frontend_should_wakeup(fe), | 530 | dvb_frontend_should_wakeup(fe) || kthread_should_stop(), |
538 | fepriv->delay); | 531 | fepriv->delay); |
539 | if (0 != dvb_frontend_is_exiting(fe)) { | 532 | |
533 | if (kthread_should_stop() || dvb_frontend_is_exiting(fe)) { | ||
540 | /* got signal or quitting */ | 534 | /* got signal or quitting */ |
541 | break; | 535 | break; |
542 | } | 536 | } |
543 | 537 | ||
544 | try_to_freeze(); | 538 | if (try_to_freeze()) |
539 | goto restart; | ||
545 | 540 | ||
546 | if (down_interruptible(&fepriv->sem)) | 541 | if (down_interruptible(&fepriv->sem)) |
547 | break; | 542 | break; |
@@ -591,7 +586,7 @@ static int dvb_frontend_thread(void *data) | |||
591 | fe->ops.sleep(fe); | 586 | fe->ops.sleep(fe); |
592 | } | 587 | } |
593 | 588 | ||
594 | fepriv->thread_pid = 0; | 589 | fepriv->thread = NULL; |
595 | mb(); | 590 | mb(); |
596 | 591 | ||
597 | dvb_frontend_wakeup(fe); | 592 | dvb_frontend_wakeup(fe); |
@@ -600,7 +595,6 @@ static int dvb_frontend_thread(void *data) | |||
600 | 595 | ||
601 | static void dvb_frontend_stop(struct dvb_frontend *fe) | 596 | static void dvb_frontend_stop(struct dvb_frontend *fe) |
602 | { | 597 | { |
603 | unsigned long ret; | ||
604 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | 598 | struct dvb_frontend_private *fepriv = fe->frontend_priv; |
605 | 599 | ||
606 | dprintk ("%s\n", __FUNCTION__); | 600 | dprintk ("%s\n", __FUNCTION__); |
@@ -608,33 +602,17 @@ static void dvb_frontend_stop(struct dvb_frontend *fe) | |||
608 | fepriv->exit = 1; | 602 | fepriv->exit = 1; |
609 | mb(); | 603 | mb(); |
610 | 604 | ||
611 | if (!fepriv->thread_pid) | 605 | if (!fepriv->thread) |
612 | return; | 606 | return; |
613 | 607 | ||
614 | /* check if the thread is really alive */ | 608 | kthread_stop(fepriv->thread); |
615 | if (kill_proc(fepriv->thread_pid, 0, 1) == -ESRCH) { | 609 | init_MUTEX (&fepriv->sem); |
616 | printk("dvb_frontend_stop: thread PID %d already died\n", | ||
617 | fepriv->thread_pid); | ||
618 | /* make sure the mutex was not held by the thread */ | ||
619 | init_MUTEX (&fepriv->sem); | ||
620 | return; | ||
621 | } | ||
622 | |||
623 | /* wake up the frontend thread, so it notices that fe->exit == 1 */ | ||
624 | dvb_frontend_wakeup(fe); | ||
625 | |||
626 | /* wait until the frontend thread has exited */ | ||
627 | ret = wait_event_interruptible(fepriv->wait_queue,0 == fepriv->thread_pid); | ||
628 | if (-ERESTARTSYS != ret) { | ||
629 | fepriv->state = FESTATE_IDLE; | ||
630 | return; | ||
631 | } | ||
632 | fepriv->state = FESTATE_IDLE; | 610 | fepriv->state = FESTATE_IDLE; |
633 | 611 | ||
634 | /* paranoia check in case a signal arrived */ | 612 | /* paranoia check in case a signal arrived */ |
635 | if (fepriv->thread_pid) | 613 | if (fepriv->thread) |
636 | printk("dvb_frontend_stop: warning: thread PID %d won't exit\n", | 614 | printk("dvb_frontend_stop: warning: thread %p won't exit\n", |
637 | fepriv->thread_pid); | 615 | fepriv->thread); |
638 | } | 616 | } |
639 | 617 | ||
640 | s32 timeval_usec_diff(struct timeval lasttime, struct timeval curtime) | 618 | s32 timeval_usec_diff(struct timeval lasttime, struct timeval curtime) |
@@ -684,10 +662,11 @@ static int dvb_frontend_start(struct dvb_frontend *fe) | |||
684 | { | 662 | { |
685 | int ret; | 663 | int ret; |
686 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | 664 | struct dvb_frontend_private *fepriv = fe->frontend_priv; |
665 | struct task_struct *fe_thread; | ||
687 | 666 | ||
688 | dprintk ("%s\n", __FUNCTION__); | 667 | dprintk ("%s\n", __FUNCTION__); |
689 | 668 | ||
690 | if (fepriv->thread_pid) { | 669 | if (fepriv->thread) { |
691 | if (!fepriv->exit) | 670 | if (!fepriv->exit) |
692 | return 0; | 671 | return 0; |
693 | else | 672 | else |
@@ -701,18 +680,18 @@ static int dvb_frontend_start(struct dvb_frontend *fe) | |||
701 | 680 | ||
702 | fepriv->state = FESTATE_IDLE; | 681 | fepriv->state = FESTATE_IDLE; |
703 | fepriv->exit = 0; | 682 | fepriv->exit = 0; |
704 | fepriv->thread_pid = 0; | 683 | fepriv->thread = NULL; |
705 | mb(); | 684 | mb(); |
706 | 685 | ||
707 | ret = kernel_thread (dvb_frontend_thread, fe, 0); | 686 | fe_thread = kthread_run(dvb_frontend_thread, fe, |
708 | 687 | "kdvb-fe-%i", fe->dvb->num); | |
709 | if (ret < 0) { | 688 | if (IS_ERR(fe_thread)) { |
710 | printk("dvb_frontend_start: failed to start kernel_thread (%d)\n", ret); | 689 | ret = PTR_ERR(fe_thread); |
690 | printk("dvb_frontend_start: failed to start kthread (%d)\n", ret); | ||
711 | up(&fepriv->sem); | 691 | up(&fepriv->sem); |
712 | return ret; | 692 | return ret; |
713 | } | 693 | } |
714 | fepriv->thread_pid = ret; | 694 | fepriv->thread = fe_thread; |
715 | |||
716 | return 0; | 695 | return 0; |
717 | } | 696 | } |
718 | 697 | ||
diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c index 826b47f155a0..490337b5ee3e 100644 --- a/drivers/media/dvb/dvb-core/dvbdev.c +++ b/drivers/media/dvb/dvb-core/dvbdev.c | |||
@@ -199,12 +199,14 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, | |||
199 | const struct dvb_device *template, void *priv, int type) | 199 | const struct dvb_device *template, void *priv, int type) |
200 | { | 200 | { |
201 | struct dvb_device *dvbdev; | 201 | struct dvb_device *dvbdev; |
202 | struct file_operations *dvbdevfops; | ||
203 | |||
202 | int id; | 204 | int id; |
203 | 205 | ||
204 | if (mutex_lock_interruptible(&dvbdev_register_lock)) | 206 | if (mutex_lock_interruptible(&dvbdev_register_lock)) |
205 | return -ERESTARTSYS; | 207 | return -ERESTARTSYS; |
206 | 208 | ||
207 | if ((id = dvbdev_get_free_id (adap, type)) < 0) { | 209 | if ((id = dvbdev_get_free_id (adap, type)) < 0){ |
208 | mutex_unlock(&dvbdev_register_lock); | 210 | mutex_unlock(&dvbdev_register_lock); |
209 | *pdvbdev = NULL; | 211 | *pdvbdev = NULL; |
210 | printk ("%s: could get find free device id...\n", __FUNCTION__); | 212 | printk ("%s: could get find free device id...\n", __FUNCTION__); |
@@ -213,7 +215,15 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, | |||
213 | 215 | ||
214 | *pdvbdev = dvbdev = kmalloc(sizeof(struct dvb_device), GFP_KERNEL); | 216 | *pdvbdev = dvbdev = kmalloc(sizeof(struct dvb_device), GFP_KERNEL); |
215 | 217 | ||
216 | if (!dvbdev) { | 218 | if (!dvbdev){ |
219 | mutex_unlock(&dvbdev_register_lock); | ||
220 | return -ENOMEM; | ||
221 | } | ||
222 | |||
223 | dvbdevfops = kzalloc(sizeof(struct file_operations), GFP_KERNEL); | ||
224 | |||
225 | if (!dvbdevfops){ | ||
226 | kfree (dvbdev); | ||
217 | mutex_unlock(&dvbdev_register_lock); | 227 | mutex_unlock(&dvbdev_register_lock); |
218 | return -ENOMEM; | 228 | return -ENOMEM; |
219 | } | 229 | } |
@@ -223,7 +233,9 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, | |||
223 | dvbdev->id = id; | 233 | dvbdev->id = id; |
224 | dvbdev->adapter = adap; | 234 | dvbdev->adapter = adap; |
225 | dvbdev->priv = priv; | 235 | dvbdev->priv = priv; |
236 | dvbdev->fops = dvbdevfops; | ||
226 | 237 | ||
238 | memcpy(dvbdev->fops, template->fops, sizeof(struct file_operations)); | ||
227 | dvbdev->fops->owner = adap->module; | 239 | dvbdev->fops->owner = adap->module; |
228 | 240 | ||
229 | list_add_tail (&dvbdev->list_head, &adap->device_list); | 241 | list_add_tail (&dvbdev->list_head, &adap->device_list); |
@@ -251,6 +263,7 @@ void dvb_unregister_device(struct dvb_device *dvbdev) | |||
251 | dvbdev->type, dvbdev->id))); | 263 | dvbdev->type, dvbdev->id))); |
252 | 264 | ||
253 | list_del (&dvbdev->list_head); | 265 | list_del (&dvbdev->list_head); |
266 | kfree (dvbdev->fops); | ||
254 | kfree (dvbdev); | 267 | kfree (dvbdev); |
255 | } | 268 | } |
256 | EXPORT_SYMBOL(dvb_unregister_device); | 269 | EXPORT_SYMBOL(dvb_unregister_device); |
diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig index ad52143602cd..80f67a51b908 100644 --- a/drivers/media/dvb/dvb-usb/Kconfig +++ b/drivers/media/dvb/dvb-usb/Kconfig | |||
@@ -109,6 +109,34 @@ config DVB_USB_CXUSB | |||
109 | Medion MD95700 hybrid USB2.0 device. | 109 | Medion MD95700 hybrid USB2.0 device. |
110 | DViCO FusionHDTV (Bluebird) USB2.0 devices | 110 | DViCO FusionHDTV (Bluebird) USB2.0 devices |
111 | 111 | ||
112 | config DVB_USB_M920X | ||
113 | tristate "Uli m920x DVB-T USB2.0 support" | ||
114 | depends on DVB_USB | ||
115 | select DVB_MT352 if !DVB_FE_CUSTOMISE | ||
116 | select DVB_TUNER_QT1010 if !DVB_FE_CUSTOMISE | ||
117 | help | ||
118 | Say Y here to support the MSI Mega Sky 580 USB2.0 DVB-T receiver. | ||
119 | Currently, only devices with a product id of | ||
120 | "DTV USB MINI" (in cold state) are supported. | ||
121 | Firmware required. | ||
122 | |||
123 | config DVB_USB_GL861 | ||
124 | tristate "Genesys Logic GL861 USB2.0 support" | ||
125 | depends on DVB_USB | ||
126 | select DVB_ZL10353 if !DVB_FE_CUSTOMISE | ||
127 | select DVB_TUNER_QT1010 if !DVB_FE_CUSTOMISE | ||
128 | help | ||
129 | Say Y here to support the MSI Megasky 580 (55801) DVB-T USB2.0 | ||
130 | receiver with USB ID 0db0:5581. | ||
131 | |||
132 | config DVB_USB_AU6610 | ||
133 | tristate "Alcor Micro AU6610 USB2.0 support" | ||
134 | depends on DVB_USB | ||
135 | select DVB_ZL10353 if !DVB_FE_CUSTOMISE | ||
136 | select DVB_TUNER_QT1010 if !DVB_FE_CUSTOMISE | ||
137 | help | ||
138 | Say Y here to support the Sigmatek DVB-110 DVB-T USB2.0 receiver. | ||
139 | |||
112 | config DVB_USB_DIGITV | 140 | config DVB_USB_DIGITV |
113 | tristate "Nebula Electronics uDigiTV DVB-T USB2.0 support" | 141 | tristate "Nebula Electronics uDigiTV DVB-T USB2.0 support" |
114 | depends on DVB_USB | 142 | depends on DVB_USB |
diff --git a/drivers/media/dvb/dvb-usb/Makefile b/drivers/media/dvb/dvb-usb/Makefile index 154d593bbb02..40f28f559b54 100644 --- a/drivers/media/dvb/dvb-usb/Makefile +++ b/drivers/media/dvb/dvb-usb/Makefile | |||
@@ -30,6 +30,15 @@ obj-$(CONFIG_DVB_USB_NOVA_T_USB2) += dvb-usb-dibusb-common.o dvb-usb-nova-t-usb2 | |||
30 | dvb-usb-umt-010-objs = umt-010.o | 30 | dvb-usb-umt-010-objs = umt-010.o |
31 | obj-$(CONFIG_DVB_USB_UMT_010) += dvb-usb-dibusb-common.o dvb-usb-umt-010.o | 31 | obj-$(CONFIG_DVB_USB_UMT_010) += dvb-usb-dibusb-common.o dvb-usb-umt-010.o |
32 | 32 | ||
33 | dvb-usb-m920x-objs = m920x.o | ||
34 | obj-$(CONFIG_DVB_USB_M920X) += dvb-usb-m920x.o | ||
35 | |||
36 | dvb-usb-gl861-objs = gl861.o | ||
37 | obj-$(CONFIG_DVB_USB_GL861) += dvb-usb-gl861.o | ||
38 | |||
39 | dvb-usb-au6610-objs = au6610.o | ||
40 | obj-$(CONFIG_DVB_USB_AU6610) += dvb-usb-au6610.o | ||
41 | |||
33 | dvb-usb-digitv-objs = digitv.o | 42 | dvb-usb-digitv-objs = digitv.o |
34 | obj-$(CONFIG_DVB_USB_DIGITV) += dvb-usb-digitv.o | 43 | obj-$(CONFIG_DVB_USB_DIGITV) += dvb-usb-digitv.o |
35 | 44 | ||
diff --git a/drivers/media/dvb/dvb-usb/au6610.c b/drivers/media/dvb/dvb-usb/au6610.c new file mode 100644 index 000000000000..0dc66a8d2baf --- /dev/null +++ b/drivers/media/dvb/dvb-usb/au6610.c | |||
@@ -0,0 +1,255 @@ | |||
1 | /* DVB USB compliant linux driver for Sigmatek DVB-110 DVB-T USB2.0 receiver | ||
2 | * | ||
3 | * Copyright (C) 2006 Antti Palosaari <crope@iki.fi> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of the GNU General Public License as published by the Free | ||
7 | * Software Foundation, version 2. | ||
8 | * | ||
9 | * see Documentation/dvb/README.dvb-usb for more information | ||
10 | */ | ||
11 | |||
12 | #include "au6610.h" | ||
13 | |||
14 | #include "zl10353.h" | ||
15 | #include "qt1010.h" | ||
16 | |||
17 | /* debug */ | ||
18 | static int dvb_usb_au6610_debug; | ||
19 | module_param_named(debug, dvb_usb_au6610_debug, int, 0644); | ||
20 | MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS); | ||
21 | |||
22 | static int au6610_usb_msg(struct dvb_usb_device *d, u8 operation, u8 addr, | ||
23 | u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen) | ||
24 | { | ||
25 | int ret; | ||
26 | u16 index; | ||
27 | u8 usb_buf[6]; /* enough for all known requests, | ||
28 | read returns 5 and write 6 bytes */ | ||
29 | switch (wlen) { | ||
30 | case 1: | ||
31 | index = wbuf[0] << 8; | ||
32 | break; | ||
33 | case 2: | ||
34 | index = wbuf[0] << 8; | ||
35 | index += wbuf[1]; | ||
36 | break; | ||
37 | default: | ||
38 | warn("wlen = %x, aborting.", wlen); | ||
39 | return -EINVAL; | ||
40 | } | ||
41 | |||
42 | ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), operation, | ||
43 | USB_TYPE_VENDOR|USB_DIR_IN, addr, index, usb_buf, | ||
44 | sizeof(usb_buf), AU6610_USB_TIMEOUT); | ||
45 | |||
46 | if (ret < 0) | ||
47 | return ret; | ||
48 | |||
49 | switch (operation) { | ||
50 | case AU6610_REQ_I2C_READ: | ||
51 | case AU6610_REQ_USB_READ: | ||
52 | /* requested value is always 5th byte in buffer */ | ||
53 | rbuf[0] = usb_buf[4]; | ||
54 | } | ||
55 | |||
56 | return ret; | ||
57 | } | ||
58 | |||
59 | static int au6610_i2c_msg(struct dvb_usb_device *d, u8 addr, | ||
60 | u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen) | ||
61 | { | ||
62 | u8 request; | ||
63 | u8 wo = (rbuf == NULL || rlen == 0); /* write-only */ | ||
64 | |||
65 | if (wo) { | ||
66 | request = AU6610_REQ_I2C_WRITE; | ||
67 | } else { /* rw */ | ||
68 | request = AU6610_REQ_I2C_READ; | ||
69 | } | ||
70 | |||
71 | return au6610_usb_msg(d, request, addr, wbuf, wlen, rbuf, rlen); | ||
72 | } | ||
73 | |||
74 | |||
75 | /* I2C */ | ||
76 | static int au6610_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], | ||
77 | int num) | ||
78 | { | ||
79 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | ||
80 | int i; | ||
81 | |||
82 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | ||
83 | return -EAGAIN; | ||
84 | |||
85 | if (num > 2) | ||
86 | return -EINVAL; | ||
87 | |||
88 | for (i = 0; i < num; i++) { | ||
89 | /* write/read request */ | ||
90 | if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) { | ||
91 | if (au6610_i2c_msg(d, msg[i].addr, msg[i].buf, | ||
92 | msg[i].len, msg[i+1].buf, | ||
93 | msg[i+1].len) < 0) | ||
94 | break; | ||
95 | i++; | ||
96 | } else if (au6610_i2c_msg(d, msg[i].addr, msg[i].buf, | ||
97 | msg[i].len, NULL, 0) < 0) | ||
98 | break; | ||
99 | } | ||
100 | |||
101 | mutex_unlock(&d->i2c_mutex); | ||
102 | return i; | ||
103 | } | ||
104 | |||
105 | |||
106 | static u32 au6610_i2c_func(struct i2c_adapter *adapter) | ||
107 | { | ||
108 | return I2C_FUNC_I2C; | ||
109 | } | ||
110 | |||
111 | static struct i2c_algorithm au6610_i2c_algo = { | ||
112 | .master_xfer = au6610_i2c_xfer, | ||
113 | .functionality = au6610_i2c_func, | ||
114 | }; | ||
115 | |||
116 | /* Callbacks for DVB USB */ | ||
117 | static int au6610_identify_state(struct usb_device *udev, | ||
118 | struct dvb_usb_device_properties *props, | ||
119 | struct dvb_usb_device_description **desc, | ||
120 | int *cold) | ||
121 | { | ||
122 | *cold = 0; | ||
123 | return 0; | ||
124 | } | ||
125 | |||
126 | static struct zl10353_config au6610_zl10353_config = { | ||
127 | .demod_address = 0x1e, | ||
128 | .no_tuner = 1, | ||
129 | .parallel_ts = 1, | ||
130 | }; | ||
131 | |||
132 | static int au6610_zl10353_frontend_attach(struct dvb_usb_adapter *adap) | ||
133 | { | ||
134 | if ((adap->fe = dvb_attach(zl10353_attach, &au6610_zl10353_config, | ||
135 | &adap->dev->i2c_adap)) != NULL) { | ||
136 | return 0; | ||
137 | } | ||
138 | |||
139 | return -EIO; | ||
140 | } | ||
141 | |||
142 | static struct qt1010_config au6610_qt1010_config = { | ||
143 | .i2c_address = 0xc4 | ||
144 | }; | ||
145 | |||
146 | static int au6610_qt1010_tuner_attach(struct dvb_usb_adapter *adap) | ||
147 | { | ||
148 | return dvb_attach(qt1010_attach, | ||
149 | adap->fe, &adap->dev->i2c_adap, | ||
150 | &au6610_qt1010_config) == NULL ? -ENODEV : 0; | ||
151 | } | ||
152 | |||
153 | /* DVB USB Driver stuff */ | ||
154 | static struct dvb_usb_device_properties au6610_properties; | ||
155 | |||
156 | static int au6610_probe(struct usb_interface *intf, | ||
157 | const struct usb_device_id *id) | ||
158 | { | ||
159 | struct dvb_usb_device *d; | ||
160 | struct usb_host_interface *alt; | ||
161 | int ret; | ||
162 | |||
163 | if (intf->num_altsetting < AU6610_ALTSETTING_COUNT) | ||
164 | return -ENODEV; | ||
165 | |||
166 | if ((ret = dvb_usb_device_init(intf, &au6610_properties, THIS_MODULE, &d)) == 0) { | ||
167 | alt = usb_altnum_to_altsetting(intf, AU6610_ALTSETTING); | ||
168 | |||
169 | if (alt == NULL) { | ||
170 | deb_rc("no alt found!\n"); | ||
171 | return -ENODEV; | ||
172 | } | ||
173 | ret = usb_set_interface(d->udev, alt->desc.bInterfaceNumber, | ||
174 | alt->desc.bAlternateSetting); | ||
175 | } | ||
176 | |||
177 | return ret; | ||
178 | } | ||
179 | |||
180 | |||
181 | static struct usb_device_id au6610_table [] = { | ||
182 | { USB_DEVICE(USB_VID_ALCOR_MICRO, USB_PID_SIGMATEK_DVB_110) }, | ||
183 | { } /* Terminating entry */ | ||
184 | }; | ||
185 | MODULE_DEVICE_TABLE (usb, au6610_table); | ||
186 | |||
187 | static struct dvb_usb_device_properties au6610_properties = { | ||
188 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
189 | .usb_ctrl = DEVICE_SPECIFIC, | ||
190 | .size_of_priv = 0, | ||
191 | .identify_state = au6610_identify_state, | ||
192 | .num_adapters = 1, | ||
193 | .adapter = { | ||
194 | { | ||
195 | .frontend_attach = au6610_zl10353_frontend_attach, | ||
196 | .tuner_attach = au6610_qt1010_tuner_attach, | ||
197 | |||
198 | .stream = { | ||
199 | .type = USB_ISOC, | ||
200 | .count = 5, | ||
201 | .endpoint = 0x82, | ||
202 | .u = { | ||
203 | .isoc = { | ||
204 | .framesperurb = 40, | ||
205 | .framesize = 942, /* maximum packet size */ | ||
206 | .interval = 1.25, /* 125 us */ | ||
207 | } | ||
208 | } | ||
209 | }, | ||
210 | } | ||
211 | }, | ||
212 | .i2c_algo = &au6610_i2c_algo, | ||
213 | .num_device_descs = 1, | ||
214 | .devices = { | ||
215 | { | ||
216 | "Sigmatek DVB-110 DVB-T USB2.0", | ||
217 | { &au6610_table[0], NULL }, | ||
218 | { NULL }, | ||
219 | }, | ||
220 | } | ||
221 | }; | ||
222 | |||
223 | static struct usb_driver au6610_driver = { | ||
224 | .name = "dvb_usb_au6610", | ||
225 | .probe = au6610_probe, | ||
226 | .disconnect = dvb_usb_device_exit, | ||
227 | .id_table = au6610_table, | ||
228 | }; | ||
229 | |||
230 | /* module stuff */ | ||
231 | static int __init au6610_module_init(void) | ||
232 | { | ||
233 | int ret; | ||
234 | |||
235 | if ((ret = usb_register(&au6610_driver))) { | ||
236 | err("usb_register failed. Error number %d", ret); | ||
237 | return ret; | ||
238 | } | ||
239 | |||
240 | return 0; | ||
241 | } | ||
242 | |||
243 | static void __exit au6610_module_exit(void) | ||
244 | { | ||
245 | /* deregister this driver from the USB subsystem */ | ||
246 | usb_deregister(&au6610_driver); | ||
247 | } | ||
248 | |||
249 | module_init (au6610_module_init); | ||
250 | module_exit (au6610_module_exit); | ||
251 | |||
252 | MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); | ||
253 | MODULE_DESCRIPTION("Driver Sigmatek DVB-110 DVB-T USB2.0 / AU6610"); | ||
254 | MODULE_VERSION("0.1"); | ||
255 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/dvb-usb/au6610.h b/drivers/media/dvb/dvb-usb/au6610.h new file mode 100644 index 000000000000..4161b054c713 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/au6610.h | |||
@@ -0,0 +1,19 @@ | |||
1 | #ifndef _DVB_USB_AU6610_H_ | ||
2 | #define _DVB_USB_AU6610_H_ | ||
3 | |||
4 | #define DVB_USB_LOG_PREFIX "au6610" | ||
5 | #include "dvb-usb.h" | ||
6 | |||
7 | #define deb_rc(args...) dprintk(dvb_usb_au6610_debug,0x01,args) | ||
8 | |||
9 | #define AU6610_REQ_I2C_WRITE 0x14 | ||
10 | #define AU6610_REQ_I2C_READ 0x13 | ||
11 | #define AU6610_REQ_USB_WRITE 0x16 | ||
12 | #define AU6610_REQ_USB_READ 0x15 | ||
13 | |||
14 | #define AU6610_USB_TIMEOUT 1000 | ||
15 | |||
16 | #define AU6610_ALTSETTING_COUNT 6 | ||
17 | #define AU6610_ALTSETTING 5 | ||
18 | |||
19 | #endif | ||
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index 299382dcb81d..148386aba275 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h | |||
@@ -11,6 +11,7 @@ | |||
11 | 11 | ||
12 | /* Vendor IDs */ | 12 | /* Vendor IDs */ |
13 | #define USB_VID_ADSTECH 0x06e1 | 13 | #define USB_VID_ADSTECH 0x06e1 |
14 | #define USB_VID_ALCOR_MICRO 0x058f | ||
14 | #define USB_VID_ANCHOR 0x0547 | 15 | #define USB_VID_ANCHOR 0x0547 |
15 | #define USB_VID_AVERMEDIA 0x07ca | 16 | #define USB_VID_AVERMEDIA 0x07ca |
16 | #define USB_VID_COMPRO 0x185b | 17 | #define USB_VID_COMPRO 0x185b |
@@ -29,6 +30,7 @@ | |||
29 | #define USB_VID_LEADTEK 0x0413 | 30 | #define USB_VID_LEADTEK 0x0413 |
30 | #define USB_VID_LITEON 0x04ca | 31 | #define USB_VID_LITEON 0x04ca |
31 | #define USB_VID_MEDION 0x1660 | 32 | #define USB_VID_MEDION 0x1660 |
33 | #define USB_VID_MSI 0x0db0 | ||
32 | #define USB_VID_PINNACLE 0x2304 | 34 | #define USB_VID_PINNACLE 0x2304 |
33 | #define USB_VID_VISIONPLUS 0x13d3 | 35 | #define USB_VID_VISIONPLUS 0x13d3 |
34 | #define USB_VID_TWINHAN 0x1822 | 36 | #define USB_VID_TWINHAN 0x1822 |
@@ -119,6 +121,8 @@ | |||
119 | #define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_COLD 0xdb54 | 121 | #define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_COLD 0xdb54 |
120 | #define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_WARM 0xdb55 | 122 | #define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_WARM 0xdb55 |
121 | #define USB_PID_MEDION_MD95700 0x0932 | 123 | #define USB_PID_MEDION_MD95700 0x0932 |
124 | #define USB_PID_MSI_MEGASKY580 0x5580 | ||
125 | #define USB_PID_MSI_MEGASKY580_55801 0x5581 | ||
122 | #define USB_PID_KYE_DVB_T_COLD 0x701e | 126 | #define USB_PID_KYE_DVB_T_COLD 0x701e |
123 | #define USB_PID_KYE_DVB_T_WARM 0x701f | 127 | #define USB_PID_KYE_DVB_T_WARM 0x701f |
124 | #define USB_PID_PCTV_200E 0x020e | 128 | #define USB_PID_PCTV_200E 0x020e |
@@ -134,6 +138,7 @@ | |||
134 | #define USB_PID_WINFAST_DTV_DONGLE_STK7700P 0x6f00 | 138 | #define USB_PID_WINFAST_DTV_DONGLE_STK7700P 0x6f00 |
135 | #define USB_PID_GENPIX_8PSK_COLD 0x0200 | 139 | #define USB_PID_GENPIX_8PSK_COLD 0x0200 |
136 | #define USB_PID_GENPIX_8PSK_WARM 0x0201 | 140 | #define USB_PID_GENPIX_8PSK_WARM 0x0201 |
141 | #define USB_PID_SIGMATEK_DVB_110 0x6610 | ||
137 | 142 | ||
138 | 143 | ||
139 | #endif | 144 | #endif |
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c index 19ff5978bc91..9511a31c8f50 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c +++ b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c | |||
@@ -151,7 +151,7 @@ int dvb_usb_remote_init(struct dvb_usb_device *d) | |||
151 | int dvb_usb_remote_exit(struct dvb_usb_device *d) | 151 | int dvb_usb_remote_exit(struct dvb_usb_device *d) |
152 | { | 152 | { |
153 | if (d->state & DVB_USB_STATE_REMOTE) { | 153 | if (d->state & DVB_USB_STATE_REMOTE) { |
154 | cancel_delayed_work(&d->rc_query_work); | 154 | cancel_rearming_delayed_work(&d->rc_query_work); |
155 | flush_scheduled_work(); | 155 | flush_scheduled_work(); |
156 | input_unregister_device(d->rc_input_dev); | 156 | input_unregister_device(d->rc_input_dev); |
157 | } | 157 | } |
diff --git a/drivers/media/dvb/dvb-usb/gl861.c b/drivers/media/dvb/dvb-usb/gl861.c new file mode 100644 index 000000000000..c9f38a5e70d3 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/gl861.c | |||
@@ -0,0 +1,231 @@ | |||
1 | /* DVB USB compliant linux driver for GL861 USB2.0 devices. | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify it | ||
4 | * under the terms of the GNU General Public License as published by the Free | ||
5 | * Software Foundation, version 2. | ||
6 | * | ||
7 | * see Documentation/dvb/README.dvb-usb for more information | ||
8 | */ | ||
9 | #include "gl861.h" | ||
10 | |||
11 | #include "zl10353.h" | ||
12 | #include "qt1010.h" | ||
13 | |||
14 | /* debug */ | ||
15 | int dvb_usb_gl861_debug; | ||
16 | module_param_named(debug,dvb_usb_gl861_debug, int, 0644); | ||
17 | MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS); | ||
18 | |||
19 | static int gl861_i2c_msg(struct dvb_usb_device *d, u8 addr, | ||
20 | u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen) | ||
21 | { | ||
22 | u16 index; | ||
23 | u16 value = addr << 8; | ||
24 | int wo = (rbuf == NULL || rlen == 0); /* write-only */ | ||
25 | u8 req, type; | ||
26 | |||
27 | if (wo) { | ||
28 | req = GL861_REQ_I2C_WRITE; | ||
29 | type = GL861_WRITE; | ||
30 | } else { /* rw */ | ||
31 | req = GL861_REQ_I2C_READ; | ||
32 | type = GL861_READ; | ||
33 | } | ||
34 | |||
35 | switch (wlen) { | ||
36 | case 1: | ||
37 | index = wbuf[0]; | ||
38 | break; | ||
39 | case 2: | ||
40 | index = wbuf[0]; | ||
41 | value = value + wbuf[1]; | ||
42 | break; | ||
43 | default: | ||
44 | warn("wlen = %x, aborting.", wlen); | ||
45 | return -EINVAL; | ||
46 | } | ||
47 | |||
48 | return usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), req, type, | ||
49 | value, index, rbuf, rlen, 2000); | ||
50 | } | ||
51 | |||
52 | /* I2C */ | ||
53 | static int gl861_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], | ||
54 | int num) | ||
55 | { | ||
56 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | ||
57 | int i; | ||
58 | |||
59 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | ||
60 | return -EAGAIN; | ||
61 | |||
62 | if (num > 2) | ||
63 | return -EINVAL; | ||
64 | |||
65 | for (i = 0; i < num; i++) { | ||
66 | /* write/read request */ | ||
67 | if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) { | ||
68 | if (gl861_i2c_msg(d, msg[i].addr, msg[i].buf, | ||
69 | msg[i].len, msg[i+1].buf, msg[i+1].len) < 0) | ||
70 | break; | ||
71 | i++; | ||
72 | } else | ||
73 | if (gl861_i2c_msg(d, msg[i].addr, msg[i].buf, | ||
74 | msg[i].len, NULL, 0) < 0) | ||
75 | break; | ||
76 | } | ||
77 | |||
78 | mutex_unlock(&d->i2c_mutex); | ||
79 | return i; | ||
80 | } | ||
81 | |||
82 | static u32 gl861_i2c_func(struct i2c_adapter *adapter) | ||
83 | { | ||
84 | return I2C_FUNC_I2C; | ||
85 | } | ||
86 | |||
87 | static struct i2c_algorithm gl861_i2c_algo = { | ||
88 | .master_xfer = gl861_i2c_xfer, | ||
89 | .functionality = gl861_i2c_func, | ||
90 | }; | ||
91 | |||
92 | /* Callbacks for DVB USB */ | ||
93 | static int gl861_identify_state(struct usb_device *udev, | ||
94 | struct dvb_usb_device_properties *props, | ||
95 | struct dvb_usb_device_description **desc, | ||
96 | int *cold) | ||
97 | { | ||
98 | *cold = 0; | ||
99 | |||
100 | return 0; | ||
101 | } | ||
102 | |||
103 | static struct zl10353_config gl861_zl10353_config = { | ||
104 | .demod_address = 0x1e, | ||
105 | .no_tuner = 1, | ||
106 | .parallel_ts = 1, | ||
107 | }; | ||
108 | |||
109 | static int gl861_frontend_attach(struct dvb_usb_adapter *adap) | ||
110 | { | ||
111 | if ((adap->fe = dvb_attach(zl10353_attach, &gl861_zl10353_config, | ||
112 | &adap->dev->i2c_adap)) != NULL) { | ||
113 | return 0; | ||
114 | } | ||
115 | |||
116 | return -EIO; | ||
117 | } | ||
118 | |||
119 | static struct qt1010_config gl861_qt1010_config = { | ||
120 | .i2c_address = 0xc4 | ||
121 | }; | ||
122 | |||
123 | static int gl861_tuner_attach(struct dvb_usb_adapter *adap) | ||
124 | { | ||
125 | return dvb_attach(qt1010_attach, | ||
126 | adap->fe, &adap->dev->i2c_adap, | ||
127 | &gl861_qt1010_config) == NULL ? -ENODEV : 0; | ||
128 | } | ||
129 | |||
130 | /* DVB USB Driver stuff */ | ||
131 | static struct dvb_usb_device_properties gl861_properties; | ||
132 | |||
133 | static int gl861_probe(struct usb_interface *intf, | ||
134 | const struct usb_device_id *id) | ||
135 | { | ||
136 | struct dvb_usb_device *d; | ||
137 | struct usb_host_interface *alt; | ||
138 | int ret; | ||
139 | |||
140 | if (intf->num_altsetting < 2) | ||
141 | return -ENODEV; | ||
142 | |||
143 | if ((ret = dvb_usb_device_init(intf, &gl861_properties, THIS_MODULE, &d)) == 0) { | ||
144 | alt = usb_altnum_to_altsetting(intf, 0); | ||
145 | |||
146 | if (alt == NULL) { | ||
147 | deb_rc("not alt found!\n"); | ||
148 | return -ENODEV; | ||
149 | } | ||
150 | |||
151 | ret = usb_set_interface(d->udev, alt->desc.bInterfaceNumber, | ||
152 | alt->desc.bAlternateSetting); | ||
153 | } | ||
154 | |||
155 | return ret; | ||
156 | } | ||
157 | |||
158 | static struct usb_device_id gl861_table [] = { | ||
159 | { USB_DEVICE(USB_VID_MSI, USB_PID_MSI_MEGASKY580_55801) }, | ||
160 | { } /* Terminating entry */ | ||
161 | }; | ||
162 | MODULE_DEVICE_TABLE (usb, gl861_table); | ||
163 | |||
164 | static struct dvb_usb_device_properties gl861_properties = { | ||
165 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
166 | .usb_ctrl = DEVICE_SPECIFIC, | ||
167 | |||
168 | .size_of_priv = 0, | ||
169 | |||
170 | .identify_state = gl861_identify_state, | ||
171 | .num_adapters = 1, | ||
172 | .adapter = {{ | ||
173 | |||
174 | .frontend_attach = gl861_frontend_attach, | ||
175 | .tuner_attach = gl861_tuner_attach, | ||
176 | |||
177 | .stream = { | ||
178 | .type = USB_BULK, | ||
179 | .count = 7, | ||
180 | .endpoint = 0x81, | ||
181 | .u = { | ||
182 | .bulk = { | ||
183 | .buffersize = 512, | ||
184 | } | ||
185 | } | ||
186 | }, | ||
187 | }}, | ||
188 | .i2c_algo = &gl861_i2c_algo, | ||
189 | |||
190 | .num_device_descs = 1, | ||
191 | .devices = { | ||
192 | { "MSI Mega Sky 55801 DVB-T USB2.0", | ||
193 | { &gl861_table[0], NULL }, | ||
194 | { NULL }, | ||
195 | }, | ||
196 | } | ||
197 | }; | ||
198 | |||
199 | static struct usb_driver gl861_driver = { | ||
200 | .name = "dvb_usb_gl861", | ||
201 | .probe = gl861_probe, | ||
202 | .disconnect = dvb_usb_device_exit, | ||
203 | .id_table = gl861_table, | ||
204 | }; | ||
205 | |||
206 | /* module stuff */ | ||
207 | static int __init gl861_module_init(void) | ||
208 | { | ||
209 | int ret; | ||
210 | |||
211 | if ((ret = usb_register(&gl861_driver))) { | ||
212 | err("usb_register failed. Error number %d", ret); | ||
213 | return ret; | ||
214 | } | ||
215 | |||
216 | return 0; | ||
217 | } | ||
218 | |||
219 | static void __exit gl861_module_exit(void) | ||
220 | { | ||
221 | /* deregister this driver from the USB subsystem */ | ||
222 | usb_deregister(&gl861_driver); | ||
223 | } | ||
224 | |||
225 | module_init (gl861_module_init); | ||
226 | module_exit (gl861_module_exit); | ||
227 | |||
228 | MODULE_AUTHOR("Carl Lundqvist <comabug@gmail.com>"); | ||
229 | MODULE_DESCRIPTION("Driver MSI Mega Sky 580 DVB-T USB2.0 / GL861"); | ||
230 | MODULE_VERSION("0.1"); | ||
231 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/dvb-usb/gl861.h b/drivers/media/dvb/dvb-usb/gl861.h new file mode 100644 index 000000000000..72a51afd5ee3 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/gl861.h | |||
@@ -0,0 +1,15 @@ | |||
1 | #ifndef _DVB_USB_GL861_H_ | ||
2 | #define _DVB_USB_GL861_H_ | ||
3 | |||
4 | #define DVB_USB_LOG_PREFIX "gl861" | ||
5 | #include "dvb-usb.h" | ||
6 | |||
7 | #define deb_rc(args...) dprintk(dvb_usb_gl861_debug,0x01,args) | ||
8 | |||
9 | #define GL861_WRITE 0x40 | ||
10 | #define GL861_READ 0xc0 | ||
11 | |||
12 | #define GL861_REQ_I2C_WRITE 0x01 | ||
13 | #define GL861_REQ_I2C_READ 0x02 | ||
14 | |||
15 | #endif | ||
diff --git a/drivers/media/dvb/dvb-usb/m920x.c b/drivers/media/dvb/dvb-usb/m920x.c new file mode 100644 index 000000000000..d48b24d9abf4 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/m920x.c | |||
@@ -0,0 +1,541 @@ | |||
1 | /* DVB USB compliant linux driver for MSI Mega Sky 580 DVB-T USB2.0 receiver | ||
2 | * | ||
3 | * Copyright (C) 2006 Aapo Tahkola (aet@rasterburn.org) | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of the GNU General Public License as published by the Free | ||
7 | * Software Foundation, version 2. | ||
8 | * | ||
9 | * see Documentation/dvb/README.dvb-usb for more information | ||
10 | */ | ||
11 | |||
12 | #include "m920x.h" | ||
13 | |||
14 | #include "mt352.h" | ||
15 | #include "mt352_priv.h" | ||
16 | #include "qt1010.h" | ||
17 | |||
18 | /* debug */ | ||
19 | static int dvb_usb_m920x_debug; | ||
20 | module_param_named(debug,dvb_usb_m920x_debug, int, 0644); | ||
21 | MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS); | ||
22 | |||
23 | static struct dvb_usb_rc_key megasky_rc_keys [] = { | ||
24 | { 0x0, 0x12, KEY_POWER }, | ||
25 | { 0x0, 0x1e, KEY_CYCLEWINDOWS }, /* min/max */ | ||
26 | { 0x0, 0x02, KEY_CHANNELUP }, | ||
27 | { 0x0, 0x05, KEY_CHANNELDOWN }, | ||
28 | { 0x0, 0x03, KEY_VOLUMEUP }, | ||
29 | { 0x0, 0x06, KEY_VOLUMEDOWN }, | ||
30 | { 0x0, 0x04, KEY_MUTE }, | ||
31 | { 0x0, 0x07, KEY_OK }, /* TS */ | ||
32 | { 0x0, 0x08, KEY_STOP }, | ||
33 | { 0x0, 0x09, KEY_MENU }, /* swap */ | ||
34 | { 0x0, 0x0a, KEY_REWIND }, | ||
35 | { 0x0, 0x1b, KEY_PAUSE }, | ||
36 | { 0x0, 0x1f, KEY_FASTFORWARD }, | ||
37 | { 0x0, 0x0c, KEY_RECORD }, | ||
38 | { 0x0, 0x0d, KEY_CAMERA }, /* screenshot */ | ||
39 | { 0x0, 0x0e, KEY_COFFEE }, /* "MTS" */ | ||
40 | }; | ||
41 | |||
42 | static inline int m9206_read(struct usb_device *udev, u8 request, u16 value,\ | ||
43 | u16 index, void *data, int size) | ||
44 | { | ||
45 | int ret; | ||
46 | |||
47 | ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), | ||
48 | request, USB_TYPE_VENDOR | USB_DIR_IN, | ||
49 | value, index, data, size, 2000); | ||
50 | if (ret < 0) | ||
51 | return ret; | ||
52 | |||
53 | if (ret != size) | ||
54 | return -EIO; | ||
55 | |||
56 | return 0; | ||
57 | } | ||
58 | |||
59 | static inline int m9206_write(struct usb_device *udev, u8 request, | ||
60 | u16 value, u16 index) | ||
61 | { | ||
62 | int ret; | ||
63 | |||
64 | ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), | ||
65 | request, USB_TYPE_VENDOR | USB_DIR_OUT, | ||
66 | value, index, NULL, 0, 2000); | ||
67 | return ret; | ||
68 | } | ||
69 | |||
70 | static int m9206_rc_init(struct usb_device *udev) | ||
71 | { | ||
72 | int ret = 0; | ||
73 | |||
74 | /* Remote controller init. */ | ||
75 | if ((ret = m9206_write(udev, M9206_CORE, 0xa8, M9206_RC_INIT2)) != 0) | ||
76 | return ret; | ||
77 | |||
78 | if ((ret = m9206_write(udev, M9206_CORE, 0x51, M9206_RC_INIT1)) != 0) | ||
79 | return ret; | ||
80 | |||
81 | return ret; | ||
82 | } | ||
83 | |||
84 | static int m9206_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | ||
85 | { | ||
86 | struct m9206_state *m = d->priv; | ||
87 | int i, ret = 0; | ||
88 | u8 rc_state[2]; | ||
89 | |||
90 | |||
91 | if ((ret = m9206_read(d->udev, M9206_CORE, 0x0, M9206_RC_STATE, rc_state, 1)) != 0) | ||
92 | goto unlock; | ||
93 | |||
94 | if ((ret = m9206_read(d->udev, M9206_CORE, 0x0, M9206_RC_KEY, rc_state + 1, 1)) != 0) | ||
95 | goto unlock; | ||
96 | |||
97 | for (i = 0; i < ARRAY_SIZE(megasky_rc_keys); i++) | ||
98 | if (megasky_rc_keys[i].data == rc_state[1]) { | ||
99 | *event = megasky_rc_keys[i].event; | ||
100 | |||
101 | switch(rc_state[0]) { | ||
102 | case 0x80: | ||
103 | *state = REMOTE_NO_KEY_PRESSED; | ||
104 | goto unlock; | ||
105 | |||
106 | case 0x93: | ||
107 | case 0x92: | ||
108 | m->rep_count = 0; | ||
109 | *state = REMOTE_KEY_PRESSED; | ||
110 | goto unlock; | ||
111 | |||
112 | case 0x91: | ||
113 | /* For comfort. */ | ||
114 | if (++m->rep_count > 2) | ||
115 | *state = REMOTE_KEY_REPEAT; | ||
116 | goto unlock; | ||
117 | |||
118 | default: | ||
119 | deb_rc("Unexpected rc response %x\n", rc_state[0]); | ||
120 | *state = REMOTE_NO_KEY_PRESSED; | ||
121 | goto unlock; | ||
122 | } | ||
123 | } | ||
124 | |||
125 | if (rc_state[1] != 0) | ||
126 | deb_rc("Unknown rc key %x\n", rc_state[1]); | ||
127 | |||
128 | *state = REMOTE_NO_KEY_PRESSED; | ||
129 | |||
130 | unlock: | ||
131 | |||
132 | return ret; | ||
133 | } | ||
134 | |||
135 | /* I2C */ | ||
136 | static int m9206_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], | ||
137 | int num) | ||
138 | { | ||
139 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | ||
140 | struct m9206_state *m = d->priv; | ||
141 | int i; | ||
142 | int ret = 0; | ||
143 | |||
144 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | ||
145 | return -EAGAIN; | ||
146 | |||
147 | if (num > 2) | ||
148 | return -EINVAL; | ||
149 | |||
150 | for (i = 0; i < num; i++) { | ||
151 | if ((ret = m9206_write(d->udev, M9206_I2C, msg[i].addr, 0x80)) != 0) | ||
152 | goto unlock; | ||
153 | |||
154 | if ((ret = m9206_write(d->udev, M9206_I2C, msg[i].buf[0], 0x0)) != 0) | ||
155 | goto unlock; | ||
156 | |||
157 | if (i + 1 < num && msg[i + 1].flags & I2C_M_RD) { | ||
158 | int i2c_i; | ||
159 | |||
160 | for (i2c_i = 0; i2c_i < M9206_I2C_MAX; i2c_i++) | ||
161 | if (msg[i].addr == m->i2c_r[i2c_i].addr) | ||
162 | break; | ||
163 | |||
164 | if (i2c_i >= M9206_I2C_MAX) { | ||
165 | deb_rc("No magic for i2c addr!\n"); | ||
166 | ret = -EINVAL; | ||
167 | goto unlock; | ||
168 | } | ||
169 | |||
170 | if ((ret = m9206_write(d->udev, M9206_I2C, m->i2c_r[i2c_i].magic, 0x80)) != 0) | ||
171 | goto unlock; | ||
172 | |||
173 | if ((ret = m9206_read(d->udev, M9206_I2C, 0x0, 0x60, msg[i + 1].buf, msg[i + 1].len)) != 0) | ||
174 | goto unlock; | ||
175 | |||
176 | i++; | ||
177 | } else { | ||
178 | if (msg[i].len != 2) | ||
179 | return -EINVAL; | ||
180 | |||
181 | if ((ret = m9206_write(d->udev, M9206_I2C, msg[i].buf[1], 0x40)) != 0) | ||
182 | goto unlock; | ||
183 | } | ||
184 | } | ||
185 | ret = i; | ||
186 | unlock: | ||
187 | mutex_unlock(&d->i2c_mutex); | ||
188 | |||
189 | return ret; | ||
190 | } | ||
191 | |||
192 | static u32 m9206_i2c_func(struct i2c_adapter *adapter) | ||
193 | { | ||
194 | return I2C_FUNC_I2C; | ||
195 | } | ||
196 | |||
197 | static struct i2c_algorithm m9206_i2c_algo = { | ||
198 | .master_xfer = m9206_i2c_xfer, | ||
199 | .functionality = m9206_i2c_func, | ||
200 | }; | ||
201 | |||
202 | |||
203 | static int m9206_set_filter(struct dvb_usb_adapter *adap, int type, int idx, | ||
204 | int pid) | ||
205 | { | ||
206 | int ret = 0; | ||
207 | |||
208 | if (pid >= 0x8000) | ||
209 | return -EINVAL; | ||
210 | |||
211 | pid |= 0x8000; | ||
212 | |||
213 | if ((ret = m9206_write(adap->dev->udev, M9206_FILTER, pid, (type << 8) | (idx * 4) )) != 0) | ||
214 | return ret; | ||
215 | |||
216 | if ((ret = m9206_write(adap->dev->udev, M9206_FILTER, 0, (type << 8) | (idx * 4) )) != 0) | ||
217 | return ret; | ||
218 | |||
219 | return ret; | ||
220 | } | ||
221 | |||
222 | static int m9206_update_filters(struct dvb_usb_adapter *adap) | ||
223 | { | ||
224 | struct m9206_state *m = adap->dev->priv; | ||
225 | int enabled = m->filtering_enabled; | ||
226 | int i, ret = 0, filter = 0; | ||
227 | |||
228 | for (i = 0; i < M9206_MAX_FILTERS; i++) | ||
229 | if (m->filters[i] == 8192) | ||
230 | enabled = 0; | ||
231 | |||
232 | /* Disable all filters */ | ||
233 | if ((ret = m9206_set_filter(adap, 0x81, 1, enabled)) != 0) | ||
234 | return ret; | ||
235 | |||
236 | for (i = 0; i < M9206_MAX_FILTERS; i++) | ||
237 | if ((ret = m9206_set_filter(adap, 0x81, i + 2, 0)) != 0) | ||
238 | return ret; | ||
239 | |||
240 | if ((ret = m9206_set_filter(adap, 0x82, 0, 0x0)) != 0) | ||
241 | return ret; | ||
242 | |||
243 | /* Set */ | ||
244 | if (enabled) { | ||
245 | for (i = 0; i < M9206_MAX_FILTERS; i++) { | ||
246 | if (m->filters[i] == 0) | ||
247 | continue; | ||
248 | |||
249 | if ((ret = m9206_set_filter(adap, 0x81, filter + 2, m->filters[i])) != 0) | ||
250 | return ret; | ||
251 | |||
252 | filter++; | ||
253 | } | ||
254 | } | ||
255 | |||
256 | if ((ret = m9206_set_filter(adap, 0x82, 0, 0x02f5)) != 0) | ||
257 | return ret; | ||
258 | |||
259 | return ret; | ||
260 | } | ||
261 | |||
262 | static int m9206_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff) | ||
263 | { | ||
264 | struct m9206_state *m = adap->dev->priv; | ||
265 | |||
266 | m->filtering_enabled = onoff ? 1 : 0; | ||
267 | |||
268 | return m9206_update_filters(adap); | ||
269 | } | ||
270 | |||
271 | static int m9206_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, | ||
272 | int onoff) | ||
273 | { | ||
274 | struct m9206_state *m = adap->dev->priv; | ||
275 | |||
276 | m->filters[index] = onoff ? pid : 0; | ||
277 | |||
278 | return m9206_update_filters(adap); | ||
279 | } | ||
280 | |||
281 | static int m9206_firmware_download(struct usb_device *udev, | ||
282 | const struct firmware *fw) | ||
283 | { | ||
284 | u16 value, index, size; | ||
285 | u8 read[4], *buff; | ||
286 | int i, pass, ret = 0; | ||
287 | |||
288 | buff = kmalloc(65536, GFP_KERNEL); | ||
289 | |||
290 | if ((ret = m9206_read(udev, M9206_FILTER, 0x0, 0x8000, read, 4)) != 0) | ||
291 | goto done; | ||
292 | deb_rc("%x %x %x %x\n", read[0], read[1], read[2], read[3]); | ||
293 | |||
294 | if ((ret = m9206_read(udev, M9206_FW, 0x0, 0x0, read, 1)) != 0) | ||
295 | goto done; | ||
296 | deb_rc("%x\n", read[0]); | ||
297 | |||
298 | for (pass = 0; pass < 2; pass++) { | ||
299 | for (i = 0; i + (sizeof(u16) * 3) < fw->size;) { | ||
300 | value = le16_to_cpu(*(u16 *)(fw->data + i)); | ||
301 | i += sizeof(u16); | ||
302 | |||
303 | index = le16_to_cpu(*(u16 *)(fw->data + i)); | ||
304 | i += sizeof(u16); | ||
305 | |||
306 | size = le16_to_cpu(*(u16 *)(fw->data + i)); | ||
307 | i += sizeof(u16); | ||
308 | |||
309 | if (pass == 1) { | ||
310 | /* Will stall if using fw->data ... */ | ||
311 | memcpy(buff, fw->data + i, size); | ||
312 | |||
313 | ret = usb_control_msg(udev, usb_sndctrlpipe(udev,0), | ||
314 | M9206_FW, | ||
315 | USB_TYPE_VENDOR | USB_DIR_OUT, | ||
316 | value, index, buff, size, 20); | ||
317 | if (ret != size) { | ||
318 | deb_rc("error while uploading fw!\n"); | ||
319 | ret = -EIO; | ||
320 | goto done; | ||
321 | } | ||
322 | msleep(3); | ||
323 | } | ||
324 | i += size; | ||
325 | } | ||
326 | if (i != fw->size) { | ||
327 | ret = -EINVAL; | ||
328 | goto done; | ||
329 | } | ||
330 | } | ||
331 | |||
332 | msleep(36); | ||
333 | |||
334 | /* m9206 will disconnect itself from the bus after this. */ | ||
335 | (void) m9206_write(udev, M9206_CORE, 0x01, M9206_FW_GO); | ||
336 | deb_rc("firmware uploaded!\n"); | ||
337 | |||
338 | done: | ||
339 | kfree(buff); | ||
340 | |||
341 | return ret; | ||
342 | } | ||
343 | |||
344 | /* Callbacks for DVB USB */ | ||
345 | static int megasky_identify_state(struct usb_device *udev, | ||
346 | struct dvb_usb_device_properties *props, | ||
347 | struct dvb_usb_device_description **desc, | ||
348 | int *cold) | ||
349 | { | ||
350 | struct usb_host_interface *alt; | ||
351 | |||
352 | alt = usb_altnum_to_altsetting(usb_ifnum_to_if(udev, 0), 1); | ||
353 | *cold = (alt == NULL) ? 1 : 0; | ||
354 | |||
355 | return 0; | ||
356 | } | ||
357 | |||
358 | static int megasky_mt352_demod_init(struct dvb_frontend *fe) | ||
359 | { | ||
360 | u8 config[] = { CONFIG, 0x3d }; | ||
361 | u8 clock[] = { CLOCK_CTL, 0x30 }; | ||
362 | u8 reset[] = { RESET, 0x80 }; | ||
363 | u8 adc_ctl[] = { ADC_CTL_1, 0x40 }; | ||
364 | u8 agc[] = { AGC_TARGET, 0x1c, 0x20 }; | ||
365 | u8 sec_agc[] = { 0x69, 0x00, 0xff, 0xff, 0x40, 0xff, 0x00, 0x40, 0x40 }; | ||
366 | u8 unk1[] = { 0x93, 0x1a }; | ||
367 | u8 unk2[] = { 0xb5, 0x7a }; | ||
368 | |||
369 | mt352_write(fe, config, ARRAY_SIZE(config)); | ||
370 | mt352_write(fe, clock, ARRAY_SIZE(clock)); | ||
371 | mt352_write(fe, reset, ARRAY_SIZE(reset)); | ||
372 | mt352_write(fe, adc_ctl, ARRAY_SIZE(adc_ctl)); | ||
373 | mt352_write(fe, agc, ARRAY_SIZE(agc)); | ||
374 | mt352_write(fe, sec_agc, ARRAY_SIZE(sec_agc)); | ||
375 | mt352_write(fe, unk1, ARRAY_SIZE(unk1)); | ||
376 | mt352_write(fe, unk2, ARRAY_SIZE(unk2)); | ||
377 | |||
378 | deb_rc("Demod init!\n"); | ||
379 | |||
380 | return 0; | ||
381 | } | ||
382 | |||
383 | static struct mt352_config megasky_mt352_config = { | ||
384 | .demod_address = 0x1e, | ||
385 | .no_tuner = 1, | ||
386 | .demod_init = megasky_mt352_demod_init, | ||
387 | }; | ||
388 | |||
389 | static int megasky_mt352_frontend_attach(struct dvb_usb_adapter *adap) | ||
390 | { | ||
391 | struct m9206_state *m = adap->dev->priv; | ||
392 | |||
393 | deb_rc("megasky_frontend_attach!\n"); | ||
394 | |||
395 | m->i2c_r[M9206_I2C_DEMOD].addr = megasky_mt352_config.demod_address; | ||
396 | m->i2c_r[M9206_I2C_DEMOD].magic = 0x1f; | ||
397 | |||
398 | if ((adap->fe = dvb_attach(mt352_attach, &megasky_mt352_config, &adap->dev->i2c_adap)) == NULL) | ||
399 | return -EIO; | ||
400 | |||
401 | return 0; | ||
402 | } | ||
403 | |||
404 | static struct qt1010_config megasky_qt1010_config = { | ||
405 | .i2c_address = 0xc4 | ||
406 | }; | ||
407 | |||
408 | static int megasky_qt1010_tuner_attach(struct dvb_usb_adapter *adap) | ||
409 | { | ||
410 | struct m9206_state *m = adap->dev->priv; | ||
411 | |||
412 | m->i2c_r[M9206_I2C_TUNER].addr = megasky_qt1010_config.i2c_address; | ||
413 | m->i2c_r[M9206_I2C_TUNER].magic = 0xc5; | ||
414 | |||
415 | if (dvb_attach(qt1010_attach, adap->fe, &adap->dev->i2c_adap, | ||
416 | &megasky_qt1010_config) == NULL) | ||
417 | return -ENODEV; | ||
418 | |||
419 | return 0; | ||
420 | } | ||
421 | |||
422 | /* DVB USB Driver stuff */ | ||
423 | static struct dvb_usb_device_properties megasky_properties; | ||
424 | |||
425 | static int m920x_probe(struct usb_interface *intf, | ||
426 | const struct usb_device_id *id) | ||
427 | { | ||
428 | struct dvb_usb_device *d; | ||
429 | struct usb_host_interface *alt; | ||
430 | int ret; | ||
431 | |||
432 | if ((ret = dvb_usb_device_init(intf, &megasky_properties, THIS_MODULE, &d)) == 0) { | ||
433 | deb_rc("probed!\n"); | ||
434 | |||
435 | alt = usb_altnum_to_altsetting(intf, 1); | ||
436 | if (alt == NULL) { | ||
437 | deb_rc("not alt found!\n"); | ||
438 | return -ENODEV; | ||
439 | } | ||
440 | |||
441 | ret = usb_set_interface(d->udev, alt->desc.bInterfaceNumber, | ||
442 | alt->desc.bAlternateSetting); | ||
443 | if (ret < 0) | ||
444 | return ret; | ||
445 | |||
446 | deb_rc("Changed to alternate setting!\n"); | ||
447 | |||
448 | if ((ret = m9206_rc_init(d->udev)) != 0) | ||
449 | return ret; | ||
450 | } | ||
451 | return ret; | ||
452 | } | ||
453 | |||
454 | static struct usb_device_id m920x_table [] = { | ||
455 | { USB_DEVICE(USB_VID_MSI, USB_PID_MSI_MEGASKY580) }, | ||
456 | { } /* Terminating entry */ | ||
457 | }; | ||
458 | MODULE_DEVICE_TABLE (usb, m920x_table); | ||
459 | |||
460 | static struct dvb_usb_device_properties megasky_properties = { | ||
461 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
462 | |||
463 | .usb_ctrl = DEVICE_SPECIFIC, | ||
464 | .firmware = "dvb-usb-megasky-02.fw", | ||
465 | .download_firmware = m9206_firmware_download, | ||
466 | |||
467 | .rc_interval = 100, | ||
468 | .rc_key_map = megasky_rc_keys, | ||
469 | .rc_key_map_size = ARRAY_SIZE(megasky_rc_keys), | ||
470 | .rc_query = m9206_rc_query, | ||
471 | |||
472 | .size_of_priv = sizeof(struct m9206_state), | ||
473 | |||
474 | .identify_state = megasky_identify_state, | ||
475 | .num_adapters = 1, | ||
476 | .adapter = {{ | ||
477 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | | ||
478 | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | ||
479 | |||
480 | .pid_filter_count = 8, | ||
481 | .pid_filter = m9206_pid_filter, | ||
482 | .pid_filter_ctrl = m9206_pid_filter_ctrl, | ||
483 | |||
484 | .frontend_attach = megasky_mt352_frontend_attach, | ||
485 | .tuner_attach = megasky_qt1010_tuner_attach, | ||
486 | |||
487 | .stream = { | ||
488 | .type = USB_BULK, | ||
489 | .count = 8, | ||
490 | .endpoint = 0x81, | ||
491 | .u = { | ||
492 | .bulk = { | ||
493 | .buffersize = 512, | ||
494 | } | ||
495 | } | ||
496 | }, | ||
497 | }}, | ||
498 | .i2c_algo = &m9206_i2c_algo, | ||
499 | |||
500 | .num_device_descs = 1, | ||
501 | .devices = { | ||
502 | { "MSI Mega Sky 580 DVB-T USB2.0", | ||
503 | { &m920x_table[0], NULL }, | ||
504 | { NULL }, | ||
505 | }, | ||
506 | } | ||
507 | }; | ||
508 | |||
509 | static struct usb_driver m920x_driver = { | ||
510 | .name = "dvb_usb_m920x", | ||
511 | .probe = m920x_probe, | ||
512 | .disconnect = dvb_usb_device_exit, | ||
513 | .id_table = m920x_table, | ||
514 | }; | ||
515 | |||
516 | /* module stuff */ | ||
517 | static int __init m920x_module_init(void) | ||
518 | { | ||
519 | int ret; | ||
520 | |||
521 | if ((ret = usb_register(&m920x_driver))) { | ||
522 | err("usb_register failed. Error number %d", ret); | ||
523 | return ret; | ||
524 | } | ||
525 | |||
526 | return 0; | ||
527 | } | ||
528 | |||
529 | static void __exit m920x_module_exit(void) | ||
530 | { | ||
531 | /* deregister this driver from the USB subsystem */ | ||
532 | usb_deregister(&m920x_driver); | ||
533 | } | ||
534 | |||
535 | module_init (m920x_module_init); | ||
536 | module_exit (m920x_module_exit); | ||
537 | |||
538 | MODULE_AUTHOR("Aapo Tahkola <aet@rasterburn.org>"); | ||
539 | MODULE_DESCRIPTION("Driver MSI Mega Sky 580 DVB-T USB2.0 / Uli m920x"); | ||
540 | MODULE_VERSION("0.1"); | ||
541 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/dvb-usb/m920x.h b/drivers/media/dvb/dvb-usb/m920x.h new file mode 100644 index 000000000000..c354196ffe5d --- /dev/null +++ b/drivers/media/dvb/dvb-usb/m920x.h | |||
@@ -0,0 +1,35 @@ | |||
1 | #ifndef _DVB_USB_M920X_H_ | ||
2 | #define _DVB_USB_M920X_H_ | ||
3 | |||
4 | #define DVB_USB_LOG_PREFIX "m920x" | ||
5 | #include "dvb-usb.h" | ||
6 | |||
7 | #define deb_rc(args...) dprintk(dvb_usb_m920x_debug,0x01,args) | ||
8 | |||
9 | #define M9206_CORE 0x22 | ||
10 | #define M9206_RC_STATE 0xff51 | ||
11 | #define M9206_RC_KEY 0xff52 | ||
12 | #define M9206_RC_INIT1 0xff54 | ||
13 | #define M9206_RC_INIT2 0xff55 | ||
14 | #define M9206_FW_GO 0xff69 | ||
15 | |||
16 | #define M9206_I2C 0x23 | ||
17 | #define M9206_FILTER 0x25 | ||
18 | #define M9206_FW 0x30 | ||
19 | |||
20 | #define M9206_MAX_FILTERS 8 | ||
21 | |||
22 | #define M9206_I2C_TUNER 0 | ||
23 | #define M9206_I2C_DEMOD 1 | ||
24 | #define M9206_I2C_MAX 2 | ||
25 | |||
26 | struct m9206_state { | ||
27 | u16 filters[M9206_MAX_FILTERS]; | ||
28 | int filtering_enabled; | ||
29 | int rep_count; | ||
30 | struct { | ||
31 | unsigned char addr; | ||
32 | unsigned char magic; | ||
33 | }i2c_r[M9206_I2C_MAX]; | ||
34 | }; | ||
35 | #endif | ||
diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index af314bb1dcac..22c2cf2cea98 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig | |||
@@ -290,6 +290,13 @@ config DVB_TDA826X | |||
290 | help | 290 | help |
291 | A DVB-S silicon tuner module. Say Y when you want to support this tuner. | 291 | A DVB-S silicon tuner module. Say Y when you want to support this tuner. |
292 | 292 | ||
293 | config DVB_TUNER_QT1010 | ||
294 | tristate "Quantek QT1010 silicon tuner" | ||
295 | depends on DVB_CORE && I2C | ||
296 | default m if DVB_FE_CUSTOMISE | ||
297 | help | ||
298 | A driver for the silicon tuner QT1010 from Quantek. | ||
299 | |||
293 | config DVB_TUNER_MT2060 | 300 | config DVB_TUNER_MT2060 |
294 | tristate "Microtune MT2060 silicon IF tuner" | 301 | tristate "Microtune MT2060 silicon IF tuner" |
295 | depends on I2C | 302 | depends on I2C |
diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index 3fa6e5d32a9c..a646d9969b71 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile | |||
@@ -38,5 +38,6 @@ obj-$(CONFIG_DVB_ISL6421) += isl6421.o | |||
38 | obj-$(CONFIG_DVB_TDA10086) += tda10086.o | 38 | obj-$(CONFIG_DVB_TDA10086) += tda10086.o |
39 | obj-$(CONFIG_DVB_TDA826X) += tda826x.o | 39 | obj-$(CONFIG_DVB_TDA826X) += tda826x.o |
40 | obj-$(CONFIG_DVB_TUNER_MT2060) += mt2060.o | 40 | obj-$(CONFIG_DVB_TUNER_MT2060) += mt2060.o |
41 | obj-$(CONFIG_DVB_TUNER_QT1010) += qt1010.o | ||
41 | obj-$(CONFIG_DVB_TUA6100) += tua6100.o | 42 | obj-$(CONFIG_DVB_TUA6100) += tua6100.o |
42 | obj-$(CONFIG_DVB_TUNER_LGH06XF) += lgh06xf.o | 43 | obj-$(CONFIG_DVB_TUNER_LGH06XF) += lgh06xf.o |
diff --git a/drivers/media/dvb/frontends/cx24110.c b/drivers/media/dvb/frontends/cx24110.c index ae96395217a2..10fc0c8316dd 100644 --- a/drivers/media/dvb/frontends/cx24110.c +++ b/drivers/media/dvb/frontends/cx24110.c | |||
@@ -254,7 +254,7 @@ static int cx24110_set_symbolrate (struct cx24110_state* state, u32 srate) | |||
254 | if (srate<500000) | 254 | if (srate<500000) |
255 | srate=500000; | 255 | srate=500000; |
256 | 256 | ||
257 | for(i=0;(i<sizeof(bands)/sizeof(bands[0]))&&(srate>bands[i]);i++) | 257 | for(i = 0; (i < ARRAY_SIZE(bands)) && (srate>bands[i]); i++) |
258 | ; | 258 | ; |
259 | /* first, check which sample rate is appropriate: 45, 60 80 or 90 MHz, | 259 | /* first, check which sample rate is appropriate: 45, 60 80 or 90 MHz, |
260 | and set the PLL accordingly (R07[1:0] Fclk, R06[7:4] PLLmult, | 260 | and set the PLL accordingly (R07[1:0] Fclk, R06[7:4] PLLmult, |
@@ -361,7 +361,7 @@ static int cx24110_initfe(struct dvb_frontend* fe) | |||
361 | 361 | ||
362 | dprintk("%s: init chip\n", __FUNCTION__); | 362 | dprintk("%s: init chip\n", __FUNCTION__); |
363 | 363 | ||
364 | for(i=0;i<sizeof(cx24110_regdata)/sizeof(cx24110_regdata[0]);i++) { | 364 | for(i = 0; i < ARRAY_SIZE(cx24110_regdata); i++) { |
365 | cx24110_writereg(state, cx24110_regdata[i].reg, cx24110_regdata[i].data); | 365 | cx24110_writereg(state, cx24110_regdata[i].reg, cx24110_regdata[i].data); |
366 | }; | 366 | }; |
367 | 367 | ||
diff --git a/drivers/media/dvb/frontends/cx24123.c b/drivers/media/dvb/frontends/cx24123.c index a356d28fc3bb..732e94aaa364 100644 --- a/drivers/media/dvb/frontends/cx24123.c +++ b/drivers/media/dvb/frontends/cx24123.c | |||
@@ -507,7 +507,7 @@ static int cx24123_pll_calculate(struct dvb_frontend* fe, struct dvb_frontend_pa | |||
507 | int i = 0; | 507 | int i = 0; |
508 | int pump = 2; | 508 | int pump = 2; |
509 | int band = 0; | 509 | int band = 0; |
510 | int num_bands = sizeof(cx24123_bandselect_vals) / sizeof(cx24123_bandselect_vals[0]); | 510 | int num_bands = ARRAY_SIZE(cx24123_bandselect_vals); |
511 | 511 | ||
512 | /* Defaults for low freq, low rate */ | 512 | /* Defaults for low freq, low rate */ |
513 | state->VCAarg = cx24123_AGC_vals[0].VCAprogdata; | 513 | state->VCAarg = cx24123_AGC_vals[0].VCAprogdata; |
@@ -516,7 +516,7 @@ static int cx24123_pll_calculate(struct dvb_frontend* fe, struct dvb_frontend_pa | |||
516 | vco_div = cx24123_bandselect_vals[0].VCOdivider; | 516 | vco_div = cx24123_bandselect_vals[0].VCOdivider; |
517 | 517 | ||
518 | /* For the given symbol rate, determine the VCA, VGA and FILTUNE programming bits */ | 518 | /* For the given symbol rate, determine the VCA, VGA and FILTUNE programming bits */ |
519 | for (i = 0; i < sizeof(cx24123_AGC_vals) / sizeof(cx24123_AGC_vals[0]); i++) | 519 | for (i = 0; i < ARRAY_SIZE(cx24123_AGC_vals); i++) |
520 | { | 520 | { |
521 | if ((cx24123_AGC_vals[i].symbolrate_low <= p->u.qpsk.symbol_rate) && | 521 | if ((cx24123_AGC_vals[i].symbolrate_low <= p->u.qpsk.symbol_rate) && |
522 | (cx24123_AGC_vals[i].symbolrate_high >= p->u.qpsk.symbol_rate) ) { | 522 | (cx24123_AGC_vals[i].symbolrate_high >= p->u.qpsk.symbol_rate) ) { |
@@ -658,7 +658,7 @@ static int cx24123_initfe(struct dvb_frontend* fe) | |||
658 | dprintk("%s: init frontend\n",__FUNCTION__); | 658 | dprintk("%s: init frontend\n",__FUNCTION__); |
659 | 659 | ||
660 | /* Configure the demod to a good set of defaults */ | 660 | /* Configure the demod to a good set of defaults */ |
661 | for (i = 0; i < sizeof(cx24123_regdata) / sizeof(cx24123_regdata[0]); i++) | 661 | for (i = 0; i < ARRAY_SIZE(cx24123_regdata); i++) |
662 | cx24123_writereg(state, cx24123_regdata[i].reg, cx24123_regdata[i].data); | 662 | cx24123_writereg(state, cx24123_regdata[i].reg, cx24123_regdata[i].data); |
663 | 663 | ||
664 | /* Set the LNB polarity */ | 664 | /* Set the LNB polarity */ |
diff --git a/drivers/media/dvb/frontends/dib3000mc.c b/drivers/media/dvb/frontends/dib3000mc.c index 23aa75a27c1f..054d7e6d9662 100644 --- a/drivers/media/dvb/frontends/dib3000mc.c +++ b/drivers/media/dvb/frontends/dib3000mc.c | |||
@@ -475,7 +475,7 @@ static void dib3000mc_set_channel_cfg(struct dib3000mc_state *state, struct dibx | |||
475 | tmp = ((chan->nfft & 0x1) << 7) | (chan->guard << 5) | (chan->nqam << 3) | chan->vit_alpha; | 475 | tmp = ((chan->nfft & 0x1) << 7) | (chan->guard << 5) | (chan->nqam << 3) | chan->vit_alpha; |
476 | dib3000mc_write_word(state, 0, tmp); | 476 | dib3000mc_write_word(state, 0, tmp); |
477 | 477 | ||
478 | dib3000mc_write_word(state, 5, seq); | 478 | dib3000mc_write_word(state, 5, (1 << 8) | ((seq & 0xf) << 4)); |
479 | 479 | ||
480 | tmp = (chan->vit_hrch << 4) | (chan->vit_select_hp); | 480 | tmp = (chan->vit_hrch << 4) | (chan->vit_select_hp); |
481 | if (!chan->vit_hrch || (chan->vit_hrch && chan->vit_select_hp)) | 481 | if (!chan->vit_hrch || (chan->vit_hrch && chan->vit_select_hp)) |
diff --git a/drivers/media/dvb/frontends/qt1010.c b/drivers/media/dvb/frontends/qt1010.c new file mode 100644 index 000000000000..825aa1412e6f --- /dev/null +++ b/drivers/media/dvb/frontends/qt1010.c | |||
@@ -0,0 +1,485 @@ | |||
1 | /* | ||
2 | * Driver for Quantek QT1010 silicon tuner | ||
3 | * | ||
4 | * Copyright (C) 2006 Antti Palosaari <crope@iki.fi> | ||
5 | * Aapo Tahkola <aet@rasterburn.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | */ | ||
21 | #include "qt1010.h" | ||
22 | #include "qt1010_priv.h" | ||
23 | |||
24 | static int debug; | ||
25 | module_param(debug, int, 0644); | ||
26 | MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)."); | ||
27 | |||
28 | #define dprintk(args...) \ | ||
29 | do { \ | ||
30 | if (debug) printk(KERN_DEBUG "QT1010: " args); \ | ||
31 | } while (0) | ||
32 | |||
33 | /* read single register */ | ||
34 | static int qt1010_readreg(struct qt1010_priv *priv, u8 reg, u8 *val) | ||
35 | { | ||
36 | struct i2c_msg msg[2] = { | ||
37 | { .addr = priv->cfg->i2c_address, | ||
38 | .flags = 0, .buf = ®, .len = 1 }, | ||
39 | { .addr = priv->cfg->i2c_address, | ||
40 | .flags = I2C_M_RD, .buf = val, .len = 1 }, | ||
41 | }; | ||
42 | |||
43 | if (i2c_transfer(priv->i2c, msg, 2) != 2) { | ||
44 | printk(KERN_WARNING "qt1010 I2C read failed\n"); | ||
45 | return -EREMOTEIO; | ||
46 | } | ||
47 | return 0; | ||
48 | } | ||
49 | |||
50 | /* write single register */ | ||
51 | static int qt1010_writereg(struct qt1010_priv *priv, u8 reg, u8 val) | ||
52 | { | ||
53 | u8 buf[2] = { reg, val }; | ||
54 | struct i2c_msg msg = { .addr = priv->cfg->i2c_address, | ||
55 | .flags = 0, .buf = buf, .len = 2 }; | ||
56 | |||
57 | if (i2c_transfer(priv->i2c, &msg, 1) != 1) { | ||
58 | printk(KERN_WARNING "qt1010 I2C write failed\n"); | ||
59 | return -EREMOTEIO; | ||
60 | } | ||
61 | return 0; | ||
62 | } | ||
63 | |||
64 | /* dump all registers */ | ||
65 | static void qt1010_dump_regs(struct qt1010_priv *priv) | ||
66 | { | ||
67 | char buf[52], buf2[4]; | ||
68 | u8 reg, val; | ||
69 | |||
70 | for (reg = 0; ; reg++) { | ||
71 | if (reg % 16 == 0) { | ||
72 | if (reg) | ||
73 | printk("%s\n", buf); | ||
74 | sprintf(buf, "%02x: ", reg); | ||
75 | } | ||
76 | if (qt1010_readreg(priv, reg, &val) == 0) | ||
77 | sprintf(buf2, "%02x ", val); | ||
78 | else | ||
79 | strcpy(buf2, "-- "); | ||
80 | strcat(buf, buf2); | ||
81 | if (reg == 0x2f) | ||
82 | break; | ||
83 | } | ||
84 | printk("%s\n", buf); | ||
85 | } | ||
86 | |||
87 | static int qt1010_set_params(struct dvb_frontend *fe, | ||
88 | struct dvb_frontend_parameters *params) | ||
89 | { | ||
90 | struct qt1010_priv *priv; | ||
91 | int err; | ||
92 | u32 freq, div, mod1, mod2; | ||
93 | u8 i, tmpval, reg05; | ||
94 | qt1010_i2c_oper_t rd[48] = { | ||
95 | { QT1010_WR, 0x01, 0x80 }, | ||
96 | { QT1010_WR, 0x02, 0x3f }, | ||
97 | { QT1010_WR, 0x05, 0xff }, /* 02 c write */ | ||
98 | { QT1010_WR, 0x06, 0x44 }, | ||
99 | { QT1010_WR, 0x07, 0xff }, /* 04 c write */ | ||
100 | { QT1010_WR, 0x08, 0x08 }, | ||
101 | { QT1010_WR, 0x09, 0xff }, /* 06 c write */ | ||
102 | { QT1010_WR, 0x0a, 0xff }, /* 07 c write */ | ||
103 | { QT1010_WR, 0x0b, 0xff }, /* 08 c write */ | ||
104 | { QT1010_WR, 0x0c, 0xe1 }, | ||
105 | { QT1010_WR, 0x1a, 0xff }, /* 10 c write */ | ||
106 | { QT1010_WR, 0x1b, 0x00 }, | ||
107 | { QT1010_WR, 0x1c, 0x89 }, | ||
108 | { QT1010_WR, 0x11, 0xff }, /* 13 c write */ | ||
109 | { QT1010_WR, 0x12, 0xff }, /* 14 c write */ | ||
110 | { QT1010_WR, 0x22, 0xff }, /* 15 c write */ | ||
111 | { QT1010_WR, 0x1e, 0x00 }, | ||
112 | { QT1010_WR, 0x1e, 0xd0 }, | ||
113 | { QT1010_RD, 0x22, 0xff }, /* 16 c read */ | ||
114 | { QT1010_WR, 0x1e, 0x00 }, | ||
115 | { QT1010_RD, 0x05, 0xff }, /* 20 c read */ | ||
116 | { QT1010_RD, 0x22, 0xff }, /* 21 c read */ | ||
117 | { QT1010_WR, 0x23, 0xd0 }, | ||
118 | { QT1010_WR, 0x1e, 0x00 }, | ||
119 | { QT1010_WR, 0x1e, 0xe0 }, | ||
120 | { QT1010_RD, 0x23, 0xff }, /* 25 c read */ | ||
121 | { QT1010_RD, 0x23, 0xff }, /* 26 c read */ | ||
122 | { QT1010_WR, 0x1e, 0x00 }, | ||
123 | { QT1010_WR, 0x24, 0xd0 }, | ||
124 | { QT1010_WR, 0x1e, 0x00 }, | ||
125 | { QT1010_WR, 0x1e, 0xf0 }, | ||
126 | { QT1010_RD, 0x24, 0xff }, /* 31 c read */ | ||
127 | { QT1010_WR, 0x1e, 0x00 }, | ||
128 | { QT1010_WR, 0x14, 0x7f }, | ||
129 | { QT1010_WR, 0x15, 0x7f }, | ||
130 | { QT1010_WR, 0x05, 0xff }, /* 35 c write */ | ||
131 | { QT1010_WR, 0x06, 0x00 }, | ||
132 | { QT1010_WR, 0x15, 0x1f }, | ||
133 | { QT1010_WR, 0x16, 0xff }, | ||
134 | { QT1010_WR, 0x18, 0xff }, | ||
135 | { QT1010_WR, 0x1f, 0xff }, /* 40 c write */ | ||
136 | { QT1010_WR, 0x20, 0xff }, /* 41 c write */ | ||
137 | { QT1010_WR, 0x21, 0x53 }, | ||
138 | { QT1010_WR, 0x25, 0xff }, /* 43 c write */ | ||
139 | { QT1010_WR, 0x26, 0x15 }, | ||
140 | { QT1010_WR, 0x00, 0xff }, /* 45 c write */ | ||
141 | { QT1010_WR, 0x02, 0x00 }, | ||
142 | { QT1010_WR, 0x01, 0x00 } | ||
143 | }; | ||
144 | |||
145 | #define FREQ1 32000000 /* 32 MHz */ | ||
146 | #define FREQ2 4000000 /* 4 MHz Quartz oscillator in the stick? */ | ||
147 | |||
148 | priv = fe->tuner_priv; | ||
149 | freq = params->frequency; | ||
150 | div = (freq + QT1010_OFFSET) / QT1010_STEP; | ||
151 | freq = (div * QT1010_STEP) - QT1010_OFFSET; | ||
152 | mod1 = (freq + QT1010_OFFSET) % FREQ1; | ||
153 | mod2 = (freq + QT1010_OFFSET) % FREQ2; | ||
154 | priv->bandwidth = | ||
155 | (fe->ops.info.type == FE_OFDM) ? params->u.ofdm.bandwidth : 0; | ||
156 | priv->frequency = freq; | ||
157 | |||
158 | if (fe->ops.i2c_gate_ctrl) | ||
159 | fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c_gate */ | ||
160 | |||
161 | /* reg 05 base value */ | ||
162 | if (freq < 290000000) reg05 = 0x14; /* 290 MHz */ | ||
163 | else if (freq < 610000000) reg05 = 0x34; /* 610 MHz */ | ||
164 | else if (freq < 802000000) reg05 = 0x54; /* 802 MHz */ | ||
165 | else reg05 = 0x74; | ||
166 | |||
167 | /* 0x5 */ | ||
168 | rd[2].val = reg05; | ||
169 | |||
170 | /* 07 - set frequency: 32 MHz scale */ | ||
171 | rd[4].val = (freq + QT1010_OFFSET) / FREQ1; | ||
172 | |||
173 | /* 09 - changes every 8/24 MHz */ | ||
174 | if (mod1 < 8000000) rd[6].val = 0x1d; | ||
175 | else rd[6].val = 0x1c; | ||
176 | |||
177 | /* 0a - set frequency: 4 MHz scale (max 28 MHz) */ | ||
178 | if (mod1 < 1*FREQ2) rd[7].val = 0x09; /* +0 MHz */ | ||
179 | else if (mod1 < 2*FREQ2) rd[7].val = 0x08; /* +4 MHz */ | ||
180 | else if (mod1 < 3*FREQ2) rd[7].val = 0x0f; /* +8 MHz */ | ||
181 | else if (mod1 < 4*FREQ2) rd[7].val = 0x0e; /* +12 MHz */ | ||
182 | else if (mod1 < 5*FREQ2) rd[7].val = 0x0d; /* +16 MHz */ | ||
183 | else if (mod1 < 6*FREQ2) rd[7].val = 0x0c; /* +20 MHz */ | ||
184 | else if (mod1 < 7*FREQ2) rd[7].val = 0x0b; /* +24 MHz */ | ||
185 | else rd[7].val = 0x0a; /* +28 MHz */ | ||
186 | |||
187 | /* 0b - changes every 2/2 MHz */ | ||
188 | if (mod2 < 2000000) rd[8].val = 0x45; | ||
189 | else rd[8].val = 0x44; | ||
190 | |||
191 | /* 1a - set frequency: 125 kHz scale (max 3875 kHz)*/ | ||
192 | tmpval = 0x78; /* byte, overflows intentionally */ | ||
193 | rd[10].val = tmpval-((mod2/QT1010_STEP)*0x08); | ||
194 | |||
195 | /* 11 */ | ||
196 | rd[13].val = 0xfd; /* TODO: correct value calculation */ | ||
197 | |||
198 | /* 12 */ | ||
199 | rd[14].val = 0x91; /* TODO: correct value calculation */ | ||
200 | |||
201 | /* 22 */ | ||
202 | if (freq < 450000000) rd[15].val = 0xd0; /* 450 MHz */ | ||
203 | else if (freq < 482000000) rd[15].val = 0xd1; /* 482 MHz */ | ||
204 | else if (freq < 514000000) rd[15].val = 0xd4; /* 514 MHz */ | ||
205 | else if (freq < 546000000) rd[15].val = 0xd7; /* 546 MHz */ | ||
206 | else if (freq < 610000000) rd[15].val = 0xda; /* 610 MHz */ | ||
207 | else rd[15].val = 0xd0; | ||
208 | |||
209 | /* 05 */ | ||
210 | rd[35].val = (reg05 & 0xf0); | ||
211 | |||
212 | /* 1f */ | ||
213 | if (mod1 < 8000000) tmpval = 0x00; | ||
214 | else if (mod1 < 12000000) tmpval = 0x01; | ||
215 | else if (mod1 < 16000000) tmpval = 0x02; | ||
216 | else if (mod1 < 24000000) tmpval = 0x03; | ||
217 | else if (mod1 < 28000000) tmpval = 0x04; | ||
218 | else tmpval = 0x05; | ||
219 | rd[40].val = (priv->reg1f_init_val + 0x0e + tmpval); | ||
220 | |||
221 | /* 20 */ | ||
222 | if (mod1 < 8000000) tmpval = 0x00; | ||
223 | else if (mod1 < 12000000) tmpval = 0x01; | ||
224 | else if (mod1 < 20000000) tmpval = 0x02; | ||
225 | else if (mod1 < 24000000) tmpval = 0x03; | ||
226 | else if (mod1 < 28000000) tmpval = 0x04; | ||
227 | else tmpval = 0x05; | ||
228 | rd[41].val = (priv->reg20_init_val + 0x0d + tmpval); | ||
229 | |||
230 | /* 25 */ | ||
231 | rd[43].val = priv->reg25_init_val; | ||
232 | |||
233 | /* 00 */ | ||
234 | rd[45].val = 0x92; /* TODO: correct value calculation */ | ||
235 | |||
236 | dprintk("freq:%u 05:%02x 07:%02x 09:%02x 0a:%02x 0b:%02x " \ | ||
237 | "1a:%02x 11:%02x 12:%02x 22:%02x 05:%02x 1f:%02x " \ | ||
238 | "20:%02x 25:%02x 00:%02x", \ | ||
239 | freq, rd[2].val, rd[4].val, rd[6].val, rd[7].val, rd[8].val, \ | ||
240 | rd[10].val, rd[13].val, rd[14].val, rd[15].val, rd[35].val, \ | ||
241 | rd[40].val, rd[41].val, rd[43].val, rd[45].val); | ||
242 | |||
243 | for (i = 0; i < ARRAY_SIZE(rd); i++) { | ||
244 | if (rd[i].oper == QT1010_WR) { | ||
245 | err = qt1010_writereg(priv, rd[i].reg, rd[i].val); | ||
246 | } else { /* read is required to proper locking */ | ||
247 | err = qt1010_readreg(priv, rd[i].reg, &tmpval); | ||
248 | } | ||
249 | if (err) return err; | ||
250 | } | ||
251 | |||
252 | if (debug) | ||
253 | qt1010_dump_regs(priv); | ||
254 | |||
255 | if (fe->ops.i2c_gate_ctrl) | ||
256 | fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c_gate */ | ||
257 | |||
258 | return 0; | ||
259 | } | ||
260 | |||
261 | static int qt1010_init_meas1(struct qt1010_priv *priv, | ||
262 | u8 oper, u8 reg, u8 reg_init_val, u8 *retval) | ||
263 | { | ||
264 | u8 i, val1, val2; | ||
265 | int err; | ||
266 | |||
267 | qt1010_i2c_oper_t i2c_data[] = { | ||
268 | { QT1010_WR, reg, reg_init_val }, | ||
269 | { QT1010_WR, 0x1e, 0x00 }, | ||
270 | { QT1010_WR, 0x1e, oper }, | ||
271 | { QT1010_RD, reg, 0xff } | ||
272 | }; | ||
273 | |||
274 | for (i = 0; i < ARRAY_SIZE(i2c_data); i++) { | ||
275 | if (i2c_data[i].oper == QT1010_WR) { | ||
276 | err = qt1010_writereg(priv, i2c_data[i].reg, | ||
277 | i2c_data[i].val); | ||
278 | } else { | ||
279 | err = qt1010_readreg(priv, i2c_data[i].reg, &val2); | ||
280 | } | ||
281 | if (err) return err; | ||
282 | } | ||
283 | |||
284 | do { | ||
285 | val1 = val2; | ||
286 | err = qt1010_readreg(priv, reg, &val2); | ||
287 | if (err) return err; | ||
288 | dprintk("compare reg:%02x %02x %02x", reg, val1, val2); | ||
289 | } while (val1 != val2); | ||
290 | *retval = val1; | ||
291 | |||
292 | return qt1010_writereg(priv, 0x1e, 0x00); | ||
293 | } | ||
294 | |||
295 | static u8 qt1010_init_meas2(struct qt1010_priv *priv, | ||
296 | u8 reg_init_val, u8 *retval) | ||
297 | { | ||
298 | u8 i, val; | ||
299 | int err; | ||
300 | qt1010_i2c_oper_t i2c_data[] = { | ||
301 | { QT1010_WR, 0x07, reg_init_val }, | ||
302 | { QT1010_WR, 0x22, 0xd0 }, | ||
303 | { QT1010_WR, 0x1e, 0x00 }, | ||
304 | { QT1010_WR, 0x1e, 0xd0 }, | ||
305 | { QT1010_RD, 0x22, 0xff }, | ||
306 | { QT1010_WR, 0x1e, 0x00 }, | ||
307 | { QT1010_WR, 0x22, 0xff } | ||
308 | }; | ||
309 | for (i = 0; i < ARRAY_SIZE(i2c_data); i++) { | ||
310 | if (i2c_data[i].oper == QT1010_WR) { | ||
311 | err = qt1010_writereg(priv, i2c_data[i].reg, | ||
312 | i2c_data[i].val); | ||
313 | } else { | ||
314 | err = qt1010_readreg(priv, i2c_data[i].reg, &val); | ||
315 | } | ||
316 | if (err) return err; | ||
317 | } | ||
318 | *retval = val; | ||
319 | return 0; | ||
320 | } | ||
321 | |||
322 | static int qt1010_init(struct dvb_frontend *fe) | ||
323 | { | ||
324 | struct qt1010_priv *priv = fe->tuner_priv; | ||
325 | struct dvb_frontend_parameters params; | ||
326 | int err = 0; | ||
327 | u8 i, tmpval, *valptr = NULL; | ||
328 | |||
329 | qt1010_i2c_oper_t i2c_data[] = { | ||
330 | { QT1010_WR, 0x01, 0x80 }, | ||
331 | { QT1010_WR, 0x0d, 0x84 }, | ||
332 | { QT1010_WR, 0x0e, 0xb7 }, | ||
333 | { QT1010_WR, 0x2a, 0x23 }, | ||
334 | { QT1010_WR, 0x2c, 0xdc }, | ||
335 | { QT1010_M1, 0x25, 0x40 }, /* get reg 25 init value */ | ||
336 | { QT1010_M1, 0x81, 0xff }, /* get reg 25 init value */ | ||
337 | { QT1010_WR, 0x2b, 0x70 }, | ||
338 | { QT1010_WR, 0x2a, 0x23 }, | ||
339 | { QT1010_M1, 0x26, 0x08 }, | ||
340 | { QT1010_M1, 0x82, 0xff }, | ||
341 | { QT1010_WR, 0x05, 0x14 }, | ||
342 | { QT1010_WR, 0x06, 0x44 }, | ||
343 | { QT1010_WR, 0x07, 0x28 }, | ||
344 | { QT1010_WR, 0x08, 0x0b }, | ||
345 | { QT1010_WR, 0x11, 0xfd }, | ||
346 | { QT1010_M1, 0x22, 0x0d }, | ||
347 | { QT1010_M1, 0xd0, 0xff }, | ||
348 | { QT1010_WR, 0x06, 0x40 }, | ||
349 | { QT1010_WR, 0x16, 0xf0 }, | ||
350 | { QT1010_WR, 0x02, 0x38 }, | ||
351 | { QT1010_WR, 0x03, 0x18 }, | ||
352 | { QT1010_WR, 0x20, 0xe0 }, | ||
353 | { QT1010_M1, 0x1f, 0x20 }, /* get reg 1f init value */ | ||
354 | { QT1010_M1, 0x84, 0xff }, /* get reg 1f init value */ | ||
355 | { QT1010_RD, 0x20, 0x20 }, /* get reg 20 init value */ | ||
356 | { QT1010_WR, 0x03, 0x19 }, | ||
357 | { QT1010_WR, 0x02, 0x3f }, | ||
358 | { QT1010_WR, 0x21, 0x53 }, | ||
359 | { QT1010_RD, 0x21, 0xff }, | ||
360 | { QT1010_WR, 0x11, 0xfd }, | ||
361 | { QT1010_WR, 0x05, 0x34 }, | ||
362 | { QT1010_WR, 0x06, 0x44 }, | ||
363 | { QT1010_WR, 0x08, 0x08 } | ||
364 | }; | ||
365 | |||
366 | if (fe->ops.i2c_gate_ctrl) | ||
367 | fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c_gate */ | ||
368 | |||
369 | for (i = 0; i < ARRAY_SIZE(i2c_data); i++) { | ||
370 | switch (i2c_data[i].oper) { | ||
371 | case QT1010_WR: | ||
372 | err = qt1010_writereg(priv, i2c_data[i].reg, | ||
373 | i2c_data[i].val); | ||
374 | break; | ||
375 | case QT1010_RD: | ||
376 | if (i2c_data[i].val == 0x20) | ||
377 | valptr = &priv->reg20_init_val; | ||
378 | else | ||
379 | valptr = &tmpval; | ||
380 | err = qt1010_readreg(priv, i2c_data[i].reg, valptr); | ||
381 | break; | ||
382 | case QT1010_M1: | ||
383 | if (i2c_data[i].val == 0x25) | ||
384 | valptr = &priv->reg25_init_val; | ||
385 | else if (i2c_data[i].val == 0x1f) | ||
386 | valptr = &priv->reg1f_init_val; | ||
387 | else | ||
388 | valptr = &tmpval; | ||
389 | err = qt1010_init_meas1(priv, i2c_data[i+1].reg, | ||
390 | i2c_data[i].reg, | ||
391 | i2c_data[i].val, valptr); | ||
392 | i++; | ||
393 | break; | ||
394 | } | ||
395 | if (err) return err; | ||
396 | } | ||
397 | |||
398 | for (i = 0x31; i < 0x3a; i++) /* 0x31 - 0x39 */ | ||
399 | if ((err = qt1010_init_meas2(priv, i, &tmpval))) | ||
400 | return err; | ||
401 | |||
402 | params.frequency = 545000000; /* Sigmatek DVB-110 545000000 */ | ||
403 | /* MSI Megasky 580 GL861 533000000 */ | ||
404 | return qt1010_set_params(fe, ¶ms); | ||
405 | } | ||
406 | |||
407 | static int qt1010_release(struct dvb_frontend *fe) | ||
408 | { | ||
409 | kfree(fe->tuner_priv); | ||
410 | fe->tuner_priv = NULL; | ||
411 | return 0; | ||
412 | } | ||
413 | |||
414 | static int qt1010_get_frequency(struct dvb_frontend *fe, u32 *frequency) | ||
415 | { | ||
416 | struct qt1010_priv *priv = fe->tuner_priv; | ||
417 | *frequency = priv->frequency; | ||
418 | return 0; | ||
419 | } | ||
420 | |||
421 | static int qt1010_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) | ||
422 | { | ||
423 | struct qt1010_priv *priv = fe->tuner_priv; | ||
424 | *bandwidth = priv->bandwidth; | ||
425 | return 0; | ||
426 | } | ||
427 | |||
428 | static const struct dvb_tuner_ops qt1010_tuner_ops = { | ||
429 | .info = { | ||
430 | .name = "Quantek QT1010", | ||
431 | .frequency_min = QT1010_MIN_FREQ, | ||
432 | .frequency_max = QT1010_MAX_FREQ, | ||
433 | .frequency_step = QT1010_STEP, | ||
434 | }, | ||
435 | |||
436 | .release = qt1010_release, | ||
437 | .init = qt1010_init, | ||
438 | /* TODO: implement sleep */ | ||
439 | |||
440 | .set_params = qt1010_set_params, | ||
441 | .get_frequency = qt1010_get_frequency, | ||
442 | .get_bandwidth = qt1010_get_bandwidth | ||
443 | }; | ||
444 | |||
445 | struct dvb_frontend * qt1010_attach(struct dvb_frontend *fe, | ||
446 | struct i2c_adapter *i2c, | ||
447 | struct qt1010_config *cfg) | ||
448 | { | ||
449 | struct qt1010_priv *priv = NULL; | ||
450 | u8 id; | ||
451 | |||
452 | priv = kzalloc(sizeof(struct qt1010_priv), GFP_KERNEL); | ||
453 | if (priv == NULL) | ||
454 | return NULL; | ||
455 | |||
456 | priv->cfg = cfg; | ||
457 | priv->i2c = i2c; | ||
458 | |||
459 | if (fe->ops.i2c_gate_ctrl) | ||
460 | fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c_gate */ | ||
461 | |||
462 | |||
463 | /* Try to detect tuner chip. Probably this is not correct register. */ | ||
464 | if (qt1010_readreg(priv, 0x29, &id) != 0 || (id != 0x39)) { | ||
465 | kfree(priv); | ||
466 | return NULL; | ||
467 | } | ||
468 | |||
469 | if (fe->ops.i2c_gate_ctrl) | ||
470 | fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c_gate */ | ||
471 | |||
472 | printk(KERN_INFO "Quantek QT1010 successfully identified.\n"); | ||
473 | memcpy(&fe->ops.tuner_ops, &qt1010_tuner_ops, | ||
474 | sizeof(struct dvb_tuner_ops)); | ||
475 | |||
476 | fe->tuner_priv = priv; | ||
477 | return fe; | ||
478 | } | ||
479 | EXPORT_SYMBOL(qt1010_attach); | ||
480 | |||
481 | MODULE_DESCRIPTION("Quantek QT1010 silicon tuner driver"); | ||
482 | MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); | ||
483 | MODULE_AUTHOR("Aapo Tahkola <aet@rasterburn.org>"); | ||
484 | MODULE_VERSION("0.1"); | ||
485 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/frontends/qt1010.h b/drivers/media/dvb/frontends/qt1010.h new file mode 100644 index 000000000000..3ab4aa045c36 --- /dev/null +++ b/drivers/media/dvb/frontends/qt1010.h | |||
@@ -0,0 +1,53 @@ | |||
1 | /* | ||
2 | * Driver for Quantek QT1010 silicon tuner | ||
3 | * | ||
4 | * Copyright (C) 2006 Antti Palosaari <crope@iki.fi> | ||
5 | * Aapo Tahkola <aet@rasterburn.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | */ | ||
21 | |||
22 | #ifndef QT1010_H | ||
23 | #define QT1010_H | ||
24 | |||
25 | #include "dvb_frontend.h" | ||
26 | |||
27 | struct qt1010_config { | ||
28 | u8 i2c_address; | ||
29 | }; | ||
30 | |||
31 | /** | ||
32 | * Attach a qt1010 tuner to the supplied frontend structure. | ||
33 | * | ||
34 | * @param fe frontend to attach to | ||
35 | * @param i2c i2c adapter to use | ||
36 | * @param cfg tuner hw based configuration | ||
37 | * @return fe pointer on success, NULL on failure | ||
38 | */ | ||
39 | #if defined(CONFIG_DVB_TUNER_QT1010) || (defined(CONFIG_DVB_TUNER_QT1010_MODULE) && defined(MODULE)) | ||
40 | extern struct dvb_frontend *qt1010_attach(struct dvb_frontend *fe, | ||
41 | struct i2c_adapter *i2c, | ||
42 | struct qt1010_config *cfg); | ||
43 | #else | ||
44 | static inline struct dvb_frontend *qt1010_attach(struct dvb_frontend *fe, | ||
45 | struct i2c_adapter *i2c, | ||
46 | struct qt1010_config *cfg) | ||
47 | { | ||
48 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); | ||
49 | return NULL; | ||
50 | } | ||
51 | #endif // CONFIG_DVB_TUNER_QT1010 | ||
52 | |||
53 | #endif | ||
diff --git a/drivers/media/dvb/frontends/qt1010_priv.h b/drivers/media/dvb/frontends/qt1010_priv.h new file mode 100644 index 000000000000..090cf475f099 --- /dev/null +++ b/drivers/media/dvb/frontends/qt1010_priv.h | |||
@@ -0,0 +1,105 @@ | |||
1 | /* | ||
2 | * Driver for Quantek QT1010 silicon tuner | ||
3 | * | ||
4 | * Copyright (C) 2006 Antti Palosaari <crope@iki.fi> | ||
5 | * Aapo Tahkola <aet@rasterburn.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | */ | ||
21 | |||
22 | #ifndef QT1010_PRIV_H | ||
23 | #define QT1010_PRIV_H | ||
24 | |||
25 | /* | ||
26 | reg def meaning | ||
27 | === === ======= | ||
28 | 00 00 ? | ||
29 | 01 a0 ? operation start/stop; start=80, stop=00 | ||
30 | 02 00 ? | ||
31 | 03 19 ? | ||
32 | 04 00 ? | ||
33 | 05 00 ? maybe band selection | ||
34 | 06 00 ? | ||
35 | 07 2b set frequency: 32 MHz scale, n*32 MHz | ||
36 | 08 0b ? | ||
37 | 09 10 ? changes every 8/24 MHz; values 1d/1c | ||
38 | 0a 08 set frequency: 4 MHz scale, n*4 MHz | ||
39 | 0b 41 ? changes every 2/2 MHz; values 45/45 | ||
40 | 0c e1 ? | ||
41 | 0d 94 ? | ||
42 | 0e b6 ? | ||
43 | 0f 2c ? | ||
44 | 10 10 ? | ||
45 | 11 f1 ? maybe device specified adjustment | ||
46 | 12 11 ? maybe device specified adjustment | ||
47 | 13 3f ? | ||
48 | 14 1f ? | ||
49 | 15 3f ? | ||
50 | 16 ff ? | ||
51 | 17 ff ? | ||
52 | 18 f7 ? | ||
53 | 19 80 ? | ||
54 | 1a d0 set frequency: 125 kHz scale, n*125 kHz | ||
55 | 1b 00 ? | ||
56 | 1c 89 ? | ||
57 | 1d 00 ? | ||
58 | 1e 00 ? looks like operation register; write cmd here, read result from 1f-26 | ||
59 | 1f 20 ? chip initialization | ||
60 | 20 e0 ? chip initialization | ||
61 | 21 20 ? | ||
62 | 22 d0 ? | ||
63 | 23 d0 ? | ||
64 | 24 d0 ? | ||
65 | 25 40 ? chip initialization | ||
66 | 26 08 ? | ||
67 | 27 29 ? | ||
68 | 28 55 ? | ||
69 | 29 39 ? | ||
70 | 2a 13 ? | ||
71 | 2b 01 ? | ||
72 | 2c ea ? | ||
73 | 2d 00 ? | ||
74 | 2e 00 ? not used? | ||
75 | 2f 00 ? not used? | ||
76 | */ | ||
77 | |||
78 | #define QT1010_STEP 125000 /* 125 kHz used by Windows drivers, | ||
79 | hw could be more precise but we don't | ||
80 | know how to use */ | ||
81 | #define QT1010_MIN_FREQ 48000000 /* 48 MHz */ | ||
82 | #define QT1010_MAX_FREQ 860000000 /* 860 MHz */ | ||
83 | #define QT1010_OFFSET 1246000000 /* 1246 MHz */ | ||
84 | |||
85 | #define QT1010_WR 0 | ||
86 | #define QT1010_RD 1 | ||
87 | #define QT1010_M1 3 | ||
88 | |||
89 | typedef struct { | ||
90 | u8 oper, reg, val; | ||
91 | } qt1010_i2c_oper_t; | ||
92 | |||
93 | struct qt1010_priv { | ||
94 | struct qt1010_config *cfg; | ||
95 | struct i2c_adapter *i2c; | ||
96 | |||
97 | u8 reg1f_init_val; | ||
98 | u8 reg20_init_val; | ||
99 | u8 reg25_init_val; | ||
100 | |||
101 | u32 frequency; | ||
102 | u32 bandwidth; | ||
103 | }; | ||
104 | |||
105 | #endif | ||
diff --git a/drivers/media/dvb/frontends/stv0297.c b/drivers/media/dvb/frontends/stv0297.c index 1ca64249010c..9a343972ff50 100644 --- a/drivers/media/dvb/frontends/stv0297.c +++ b/drivers/media/dvb/frontends/stv0297.c | |||
@@ -35,6 +35,7 @@ struct stv0297_state { | |||
35 | const struct stv0297_config *config; | 35 | const struct stv0297_config *config; |
36 | struct dvb_frontend frontend; | 36 | struct dvb_frontend frontend; |
37 | 37 | ||
38 | unsigned long last_ber; | ||
38 | unsigned long base_freq; | 39 | unsigned long base_freq; |
39 | }; | 40 | }; |
40 | 41 | ||
@@ -310,6 +311,8 @@ static int stv0297_init(struct dvb_frontend *fe) | |||
310 | stv0297_writereg(state, state->config->inittab[i], state->config->inittab[i+1]); | 311 | stv0297_writereg(state, state->config->inittab[i], state->config->inittab[i+1]); |
311 | msleep(200); | 312 | msleep(200); |
312 | 313 | ||
314 | state->last_ber = 0; | ||
315 | |||
313 | return 0; | 316 | return 0; |
314 | } | 317 | } |
315 | 318 | ||
@@ -340,11 +343,13 @@ static int stv0297_read_ber(struct dvb_frontend *fe, u32 * ber) | |||
340 | struct stv0297_state *state = fe->demodulator_priv; | 343 | struct stv0297_state *state = fe->demodulator_priv; |
341 | u8 BER[3]; | 344 | u8 BER[3]; |
342 | 345 | ||
343 | stv0297_writereg(state, 0xA0, 0x80); // Start Counting bit errors for 4096 Bytes | ||
344 | mdelay(25); // Hopefully got 4096 Bytes | ||
345 | stv0297_readregs(state, 0xA0, BER, 3); | 346 | stv0297_readregs(state, 0xA0, BER, 3); |
346 | mdelay(25); | 347 | if (!(BER[0] & 0x80)) { |
347 | *ber = (BER[2] << 8 | BER[1]) / (8 * 4096); | 348 | state->last_ber = BER[2] << 8 | BER[1]; |
349 | stv0297_writereg_mask(state, 0xA0, 0x80, 0x80); | ||
350 | } | ||
351 | |||
352 | *ber = state->last_ber; | ||
348 | 353 | ||
349 | return 0; | 354 | return 0; |
350 | } | 355 | } |
@@ -376,9 +381,14 @@ static int stv0297_read_ucblocks(struct dvb_frontend *fe, u32 * ucblocks) | |||
376 | { | 381 | { |
377 | struct stv0297_state *state = fe->demodulator_priv; | 382 | struct stv0297_state *state = fe->demodulator_priv; |
378 | 383 | ||
384 | stv0297_writereg_mask(state, 0xDF, 0x03, 0x03); /* freeze the counters */ | ||
385 | |||
379 | *ucblocks = (stv0297_readreg(state, 0xD5) << 8) | 386 | *ucblocks = (stv0297_readreg(state, 0xD5) << 8) |
380 | | stv0297_readreg(state, 0xD4); | 387 | | stv0297_readreg(state, 0xD4); |
381 | 388 | ||
389 | stv0297_writereg_mask(state, 0xDF, 0x03, 0x02); /* clear the counters */ | ||
390 | stv0297_writereg_mask(state, 0xDF, 0x03, 0x01); /* re-enable the counters */ | ||
391 | |||
382 | return 0; | 392 | return 0; |
383 | } | 393 | } |
384 | 394 | ||
@@ -648,6 +658,7 @@ struct dvb_frontend *stv0297_attach(const struct stv0297_config *config, | |||
648 | /* setup the state */ | 658 | /* setup the state */ |
649 | state->config = config; | 659 | state->config = config; |
650 | state->i2c = i2c; | 660 | state->i2c = i2c; |
661 | state->last_ber = 0; | ||
651 | state->base_freq = 0; | 662 | state->base_freq = 0; |
652 | 663 | ||
653 | /* check if the demod is there */ | 664 | /* check if the demod is there */ |
diff --git a/drivers/media/dvb/frontends/stv0299.c b/drivers/media/dvb/frontends/stv0299.c index 93483769eca8..18768d2f6d40 100644 --- a/drivers/media/dvb/frontends/stv0299.c +++ b/drivers/media/dvb/frontends/stv0299.c | |||
@@ -92,7 +92,7 @@ static int stv0299_writeregI (struct stv0299_state* state, u8 reg, u8 data) | |||
92 | return (ret != 1) ? -EREMOTEIO : 0; | 92 | return (ret != 1) ? -EREMOTEIO : 0; |
93 | } | 93 | } |
94 | 94 | ||
95 | int stv0299_write(struct dvb_frontend* fe, u8 *buf, int len) | 95 | static int stv0299_write(struct dvb_frontend* fe, u8 *buf, int len) |
96 | { | 96 | { |
97 | struct stv0299_state* state = fe->demodulator_priv; | 97 | struct stv0299_state* state = fe->demodulator_priv; |
98 | 98 | ||
diff --git a/drivers/media/dvb/frontends/tda10021.c b/drivers/media/dvb/frontends/tda10021.c index dca89171be1f..5b9c5bb29b23 100644 --- a/drivers/media/dvb/frontends/tda10021.c +++ b/drivers/media/dvb/frontends/tda10021.c | |||
@@ -201,7 +201,7 @@ static int tda10021_set_symbolrate (struct tda10021_state* state, u32 symbolrate | |||
201 | return 0; | 201 | return 0; |
202 | } | 202 | } |
203 | 203 | ||
204 | int tda10021_write(struct dvb_frontend* fe, u8 *buf, int len) | 204 | static int tda10021_write(struct dvb_frontend* fe, u8 *buf, int len) |
205 | { | 205 | { |
206 | struct tda10021_state* state = fe->demodulator_priv; | 206 | struct tda10021_state* state = fe->demodulator_priv; |
207 | 207 | ||
diff --git a/drivers/media/dvb/frontends/tda1004x.c b/drivers/media/dvb/frontends/tda1004x.c index 00e4bcd9f1a4..f4a9cf9d26d0 100644 --- a/drivers/media/dvb/frontends/tda1004x.c +++ b/drivers/media/dvb/frontends/tda1004x.c | |||
@@ -579,7 +579,7 @@ static int tda1004x_decode_fec(int tdafec) | |||
579 | return -1; | 579 | return -1; |
580 | } | 580 | } |
581 | 581 | ||
582 | int tda1004x_write(struct dvb_frontend* fe, u8 *buf, int len) | 582 | static int tda1004x_write(struct dvb_frontend* fe, u8 *buf, int len) |
583 | { | 583 | { |
584 | struct tda1004x_state* state = fe->demodulator_priv; | 584 | struct tda1004x_state* state = fe->demodulator_priv; |
585 | 585 | ||
diff --git a/drivers/media/dvb/frontends/zl10353.c b/drivers/media/dvb/frontends/zl10353.c index 0e9b59af271e..245f9b7dddfa 100644 --- a/drivers/media/dvb/frontends/zl10353.c +++ b/drivers/media/dvb/frontends/zl10353.c | |||
@@ -38,6 +38,12 @@ struct zl10353_state { | |||
38 | struct zl10353_config config; | 38 | struct zl10353_config config; |
39 | }; | 39 | }; |
40 | 40 | ||
41 | static int debug; | ||
42 | #define dprintk(args...) \ | ||
43 | do { \ | ||
44 | if (debug) printk(KERN_DEBUG "zl10353: " args); \ | ||
45 | } while (0) | ||
46 | |||
41 | static int debug_regs = 0; | 47 | static int debug_regs = 0; |
42 | 48 | ||
43 | static int zl10353_single_write(struct dvb_frontend *fe, u8 reg, u8 val) | 49 | static int zl10353_single_write(struct dvb_frontend *fe, u8 reg, u8 val) |
@@ -54,7 +60,7 @@ static int zl10353_single_write(struct dvb_frontend *fe, u8 reg, u8 val) | |||
54 | return 0; | 60 | return 0; |
55 | } | 61 | } |
56 | 62 | ||
57 | int zl10353_write(struct dvb_frontend *fe, u8 *ibuf, int ilen) | 63 | static int zl10353_write(struct dvb_frontend *fe, u8 *ibuf, int ilen) |
58 | { | 64 | { |
59 | int err, i; | 65 | int err, i; |
60 | for (i = 0; i < ilen - 1; i++) | 66 | for (i = 0; i < ilen - 1; i++) |
@@ -113,6 +119,36 @@ static void zl10353_dump_regs(struct dvb_frontend *fe) | |||
113 | printk(KERN_DEBUG "%s\n", buf); | 119 | printk(KERN_DEBUG "%s\n", buf); |
114 | } | 120 | } |
115 | 121 | ||
122 | static void zl10353_calc_nominal_rate(struct dvb_frontend *fe, | ||
123 | enum fe_bandwidth bandwidth, | ||
124 | u16 *nominal_rate) | ||
125 | { | ||
126 | u32 adc_clock = 22528; /* 20.480 MHz on the board(!?) */ | ||
127 | u8 bw; | ||
128 | struct zl10353_state *state = fe->demodulator_priv; | ||
129 | |||
130 | if (state->config.adc_clock) | ||
131 | adc_clock = state->config.adc_clock; | ||
132 | |||
133 | switch (bandwidth) { | ||
134 | case BANDWIDTH_6_MHZ: | ||
135 | bw = 6; | ||
136 | break; | ||
137 | case BANDWIDTH_7_MHZ: | ||
138 | bw = 7; | ||
139 | break; | ||
140 | case BANDWIDTH_8_MHZ: | ||
141 | default: | ||
142 | bw = 8; | ||
143 | break; | ||
144 | } | ||
145 | |||
146 | *nominal_rate = (64 * bw * (1<<16) / (7 * 8) * 4000 / adc_clock + 2) / 4; | ||
147 | |||
148 | dprintk("%s: bw %d, adc_clock %d => 0x%x\n", | ||
149 | __FUNCTION__, bw, adc_clock, *nominal_rate); | ||
150 | } | ||
151 | |||
116 | static int zl10353_sleep(struct dvb_frontend *fe) | 152 | static int zl10353_sleep(struct dvb_frontend *fe) |
117 | { | 153 | { |
118 | static u8 zl10353_softdown[] = { 0x50, 0x0C, 0x44 }; | 154 | static u8 zl10353_softdown[] = { 0x50, 0x0C, 0x44 }; |
@@ -125,7 +161,7 @@ static int zl10353_set_parameters(struct dvb_frontend *fe, | |||
125 | struct dvb_frontend_parameters *param) | 161 | struct dvb_frontend_parameters *param) |
126 | { | 162 | { |
127 | struct zl10353_state *state = fe->demodulator_priv; | 163 | struct zl10353_state *state = fe->demodulator_priv; |
128 | 164 | u16 nominal_rate; | |
129 | u8 pllbuf[6] = { 0x67 }; | 165 | u8 pllbuf[6] = { 0x67 }; |
130 | 166 | ||
131 | /* These settings set "auto-everything" and start the FSM. */ | 167 | /* These settings set "auto-everything" and start the FSM. */ |
@@ -138,18 +174,23 @@ static int zl10353_set_parameters(struct dvb_frontend *fe, | |||
138 | zl10353_single_write(fe, 0x56, 0x28); | 174 | zl10353_single_write(fe, 0x56, 0x28); |
139 | zl10353_single_write(fe, 0x89, 0x20); | 175 | zl10353_single_write(fe, 0x89, 0x20); |
140 | zl10353_single_write(fe, 0x5E, 0x00); | 176 | zl10353_single_write(fe, 0x5E, 0x00); |
141 | zl10353_single_write(fe, 0x65, 0x5A); | 177 | |
142 | zl10353_single_write(fe, 0x66, 0xE9); | 178 | zl10353_calc_nominal_rate(fe, param->u.ofdm.bandwidth, &nominal_rate); |
179 | zl10353_single_write(fe, TRL_NOMINAL_RATE_1, msb(nominal_rate)); | ||
180 | zl10353_single_write(fe, TRL_NOMINAL_RATE_0, lsb(nominal_rate)); | ||
181 | |||
143 | zl10353_single_write(fe, 0x6C, 0xCD); | 182 | zl10353_single_write(fe, 0x6C, 0xCD); |
144 | zl10353_single_write(fe, 0x6D, 0x7E); | 183 | zl10353_single_write(fe, 0x6D, 0x7E); |
145 | zl10353_single_write(fe, 0x62, 0x0A); | 184 | if (fe->ops.i2c_gate_ctrl) |
185 | fe->ops.i2c_gate_ctrl(fe, 0); | ||
146 | 186 | ||
147 | // if there is no attached secondary tuner, we call set_params to program | 187 | // if there is no attached secondary tuner, we call set_params to program |
148 | // a potential tuner attached somewhere else | 188 | // a potential tuner attached somewhere else |
149 | if (state->config.no_tuner) { | 189 | if (state->config.no_tuner) { |
150 | if (fe->ops.tuner_ops.set_params) { | 190 | if (fe->ops.tuner_ops.set_params) { |
151 | fe->ops.tuner_ops.set_params(fe, param); | 191 | fe->ops.tuner_ops.set_params(fe, param); |
152 | if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); | 192 | if (fe->ops.i2c_gate_ctrl) |
193 | fe->ops.i2c_gate_ctrl(fe, 0); | ||
153 | } | 194 | } |
154 | } | 195 | } |
155 | 196 | ||
@@ -213,6 +254,29 @@ static int zl10353_read_status(struct dvb_frontend *fe, fe_status_t *status) | |||
213 | return 0; | 254 | return 0; |
214 | } | 255 | } |
215 | 256 | ||
257 | static int zl10353_read_ber(struct dvb_frontend *fe, u32 *ber) | ||
258 | { | ||
259 | struct zl10353_state *state = fe->demodulator_priv; | ||
260 | |||
261 | *ber = zl10353_read_register(state, RS_ERR_CNT_2) << 16 | | ||
262 | zl10353_read_register(state, RS_ERR_CNT_1) << 8 | | ||
263 | zl10353_read_register(state, RS_ERR_CNT_0); | ||
264 | |||
265 | return 0; | ||
266 | } | ||
267 | |||
268 | static int zl10353_read_signal_strength(struct dvb_frontend *fe, u16 *strength) | ||
269 | { | ||
270 | struct zl10353_state *state = fe->demodulator_priv; | ||
271 | |||
272 | u16 signal = zl10353_read_register(state, AGC_GAIN_1) << 10 | | ||
273 | zl10353_read_register(state, AGC_GAIN_0) << 2 | 3; | ||
274 | |||
275 | *strength = ~signal; | ||
276 | |||
277 | return 0; | ||
278 | } | ||
279 | |||
216 | static int zl10353_read_snr(struct dvb_frontend *fe, u16 *snr) | 280 | static int zl10353_read_snr(struct dvb_frontend *fe, u16 *snr) |
217 | { | 281 | { |
218 | struct zl10353_state *state = fe->demodulator_priv; | 282 | struct zl10353_state *state = fe->demodulator_priv; |
@@ -227,6 +291,16 @@ static int zl10353_read_snr(struct dvb_frontend *fe, u16 *snr) | |||
227 | return 0; | 291 | return 0; |
228 | } | 292 | } |
229 | 293 | ||
294 | static int zl10353_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) | ||
295 | { | ||
296 | struct zl10353_state *state = fe->demodulator_priv; | ||
297 | |||
298 | *ucblocks = zl10353_read_register(state, RS_UBC_1) << 8 | | ||
299 | zl10353_read_register(state, RS_UBC_0); | ||
300 | |||
301 | return 0; | ||
302 | } | ||
303 | |||
230 | static int zl10353_get_tune_settings(struct dvb_frontend *fe, | 304 | static int zl10353_get_tune_settings(struct dvb_frontend *fe, |
231 | struct dvb_frontend_tune_settings | 305 | struct dvb_frontend_tune_settings |
232 | *fe_tune_settings) | 306 | *fe_tune_settings) |
@@ -261,6 +335,16 @@ static int zl10353_init(struct dvb_frontend *fe) | |||
261 | return 0; | 335 | return 0; |
262 | } | 336 | } |
263 | 337 | ||
338 | static int zl10353_i2c_gate_ctrl(struct dvb_frontend* fe, int enable) | ||
339 | { | ||
340 | u8 val = 0x0a; | ||
341 | |||
342 | if (enable) | ||
343 | val |= 0x10; | ||
344 | |||
345 | return zl10353_single_write(fe, 0x62, val); | ||
346 | } | ||
347 | |||
264 | static void zl10353_release(struct dvb_frontend *fe) | 348 | static void zl10353_release(struct dvb_frontend *fe) |
265 | { | 349 | { |
266 | struct zl10353_state *state = fe->demodulator_priv; | 350 | struct zl10353_state *state = fe->demodulator_priv; |
@@ -319,15 +403,22 @@ static struct dvb_frontend_ops zl10353_ops = { | |||
319 | 403 | ||
320 | .init = zl10353_init, | 404 | .init = zl10353_init, |
321 | .sleep = zl10353_sleep, | 405 | .sleep = zl10353_sleep, |
406 | .i2c_gate_ctrl = zl10353_i2c_gate_ctrl, | ||
322 | .write = zl10353_write, | 407 | .write = zl10353_write, |
323 | 408 | ||
324 | .set_frontend = zl10353_set_parameters, | 409 | .set_frontend = zl10353_set_parameters, |
325 | .get_tune_settings = zl10353_get_tune_settings, | 410 | .get_tune_settings = zl10353_get_tune_settings, |
326 | 411 | ||
327 | .read_status = zl10353_read_status, | 412 | .read_status = zl10353_read_status, |
413 | .read_ber = zl10353_read_ber, | ||
414 | .read_signal_strength = zl10353_read_signal_strength, | ||
328 | .read_snr = zl10353_read_snr, | 415 | .read_snr = zl10353_read_snr, |
416 | .read_ucblocks = zl10353_read_ucblocks, | ||
329 | }; | 417 | }; |
330 | 418 | ||
419 | module_param(debug, int, 0644); | ||
420 | MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); | ||
421 | |||
331 | module_param(debug_regs, int, 0644); | 422 | module_param(debug_regs, int, 0644); |
332 | MODULE_PARM_DESC(debug_regs, "Turn on/off frontend register dumps (default:off)."); | 423 | MODULE_PARM_DESC(debug_regs, "Turn on/off frontend register dumps (default:off)."); |
333 | 424 | ||
diff --git a/drivers/media/dvb/frontends/zl10353.h b/drivers/media/dvb/frontends/zl10353.h index 0bc0109737f1..cb274dc12b82 100644 --- a/drivers/media/dvb/frontends/zl10353.h +++ b/drivers/media/dvb/frontends/zl10353.h | |||
@@ -29,6 +29,9 @@ struct zl10353_config | |||
29 | /* demodulator's I2C address */ | 29 | /* demodulator's I2C address */ |
30 | u8 demod_address; | 30 | u8 demod_address; |
31 | 31 | ||
32 | /* frequencies in kHz */ | ||
33 | int adc_clock; // default: 22528 | ||
34 | |||
32 | /* set if no pll is connected to the secondary i2c bus */ | 35 | /* set if no pll is connected to the secondary i2c bus */ |
33 | int no_tuner; | 36 | int no_tuner; |
34 | 37 | ||
diff --git a/drivers/media/dvb/frontends/zl10353_priv.h b/drivers/media/dvb/frontends/zl10353_priv.h index b72224bd7dde..4962434b35e7 100644 --- a/drivers/media/dvb/frontends/zl10353_priv.h +++ b/drivers/media/dvb/frontends/zl10353_priv.h | |||
@@ -24,19 +24,31 @@ | |||
24 | 24 | ||
25 | #define ID_ZL10353 0x14 | 25 | #define ID_ZL10353 0x14 |
26 | 26 | ||
27 | #define msb(x) (((x) >> 8) & 0xff) | ||
28 | #define lsb(x) ((x) & 0xff) | ||
29 | |||
27 | enum zl10353_reg_addr { | 30 | enum zl10353_reg_addr { |
28 | INTERRUPT_0 = 0x00, | 31 | INTERRUPT_0 = 0x00, |
29 | INTERRUPT_1 = 0x01, | 32 | INTERRUPT_1 = 0x01, |
30 | INTERRUPT_2 = 0x02, | 33 | INTERRUPT_2 = 0x02, |
31 | INTERRUPT_3 = 0x03, | 34 | INTERRUPT_3 = 0x03, |
32 | INTERRUPT_4 = 0x04, | 35 | INTERRUPT_4 = 0x04, |
33 | INTERRUPT_5 = 0x05, | 36 | INTERRUPT_5 = 0x05, |
34 | STATUS_6 = 0x06, | 37 | STATUS_6 = 0x06, |
35 | STATUS_7 = 0x07, | 38 | STATUS_7 = 0x07, |
36 | STATUS_8 = 0x08, | 39 | STATUS_8 = 0x08, |
37 | STATUS_9 = 0x09, | 40 | STATUS_9 = 0x09, |
38 | SNR = 0x10, | 41 | AGC_GAIN_1 = 0x0A, |
39 | CHIP_ID = 0x7F, | 42 | AGC_GAIN_0 = 0x0B, |
43 | SNR = 0x10, | ||
44 | RS_ERR_CNT_2 = 0x11, | ||
45 | RS_ERR_CNT_1 = 0x12, | ||
46 | RS_ERR_CNT_0 = 0x13, | ||
47 | RS_UBC_1 = 0x14, | ||
48 | RS_UBC_0 = 0x15, | ||
49 | TRL_NOMINAL_RATE_1 = 0x65, | ||
50 | TRL_NOMINAL_RATE_0 = 0x66, | ||
51 | CHIP_ID = 0x7F, | ||
40 | }; | 52 | }; |
41 | 53 | ||
42 | #endif /* _ZL10353_PRIV_ */ | 54 | #endif /* _ZL10353_PRIV_ */ |
diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c index 366c1371ee97..29ed532ba966 100644 --- a/drivers/media/dvb/ttpci/av7110.c +++ b/drivers/media/dvb/ttpci/av7110.c | |||
@@ -51,6 +51,7 @@ | |||
51 | #include <linux/firmware.h> | 51 | #include <linux/firmware.h> |
52 | #include <linux/crc32.h> | 52 | #include <linux/crc32.h> |
53 | #include <linux/i2c.h> | 53 | #include <linux/i2c.h> |
54 | #include <linux/kthread.h> | ||
54 | 55 | ||
55 | #include <asm/system.h> | 56 | #include <asm/system.h> |
56 | 57 | ||
@@ -223,11 +224,10 @@ static void recover_arm(struct av7110 *av7110) | |||
223 | 224 | ||
224 | static void av7110_arm_sync(struct av7110 *av7110) | 225 | static void av7110_arm_sync(struct av7110 *av7110) |
225 | { | 226 | { |
226 | av7110->arm_rmmod = 1; | 227 | if (av7110->arm_thread) |
227 | wake_up_interruptible(&av7110->arm_wait); | 228 | kthread_stop(av7110->arm_thread); |
228 | 229 | ||
229 | while (av7110->arm_thread) | 230 | av7110->arm_thread = NULL; |
230 | msleep(1); | ||
231 | } | 231 | } |
232 | 232 | ||
233 | static int arm_thread(void *data) | 233 | static int arm_thread(void *data) |
@@ -238,17 +238,11 @@ static int arm_thread(void *data) | |||
238 | 238 | ||
239 | dprintk(4, "%p\n",av7110); | 239 | dprintk(4, "%p\n",av7110); |
240 | 240 | ||
241 | lock_kernel(); | ||
242 | daemonize("arm_mon"); | ||
243 | sigfillset(¤t->blocked); | ||
244 | unlock_kernel(); | ||
245 | |||
246 | av7110->arm_thread = current; | ||
247 | |||
248 | for (;;) { | 241 | for (;;) { |
249 | timeout = wait_event_interruptible_timeout(av7110->arm_wait, | 242 | timeout = wait_event_interruptible_timeout(av7110->arm_wait, |
250 | av7110->arm_rmmod, 5 * HZ); | 243 | kthread_should_stop(), 5 * HZ); |
251 | if (-ERESTARTSYS == timeout || av7110->arm_rmmod) { | 244 | |
245 | if (-ERESTARTSYS == timeout || kthread_should_stop()) { | ||
252 | /* got signal or told to quit*/ | 246 | /* got signal or told to quit*/ |
253 | break; | 247 | break; |
254 | } | 248 | } |
@@ -276,7 +270,6 @@ static int arm_thread(void *data) | |||
276 | av7110->arm_errors = 0; | 270 | av7110->arm_errors = 0; |
277 | } | 271 | } |
278 | 272 | ||
279 | av7110->arm_thread = NULL; | ||
280 | return 0; | 273 | return 0; |
281 | } | 274 | } |
282 | 275 | ||
@@ -695,8 +688,8 @@ static void gpioirq(unsigned long data) | |||
695 | static int dvb_osd_ioctl(struct inode *inode, struct file *file, | 688 | static int dvb_osd_ioctl(struct inode *inode, struct file *file, |
696 | unsigned int cmd, void *parg) | 689 | unsigned int cmd, void *parg) |
697 | { | 690 | { |
698 | struct dvb_device *dvbdev = (struct dvb_device *) file->private_data; | 691 | struct dvb_device *dvbdev = file->private_data; |
699 | struct av7110 *av7110 = (struct av7110 *) dvbdev->priv; | 692 | struct av7110 *av7110 = dvbdev->priv; |
700 | 693 | ||
701 | dprintk(4, "%p\n", av7110); | 694 | dprintk(4, "%p\n", av7110); |
702 | 695 | ||
@@ -786,7 +779,7 @@ int ChangePIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid, | |||
786 | static int StartHWFilter(struct dvb_demux_filter *dvbdmxfilter) | 779 | static int StartHWFilter(struct dvb_demux_filter *dvbdmxfilter) |
787 | { | 780 | { |
788 | struct dvb_demux_feed *dvbdmxfeed = dvbdmxfilter->feed; | 781 | struct dvb_demux_feed *dvbdmxfeed = dvbdmxfilter->feed; |
789 | struct av7110 *av7110 = (struct av7110 *) dvbdmxfeed->demux->priv; | 782 | struct av7110 *av7110 = dvbdmxfeed->demux->priv; |
790 | u16 buf[20]; | 783 | u16 buf[20]; |
791 | int ret, i; | 784 | int ret, i; |
792 | u16 handle; | 785 | u16 handle; |
@@ -835,7 +828,7 @@ static int StartHWFilter(struct dvb_demux_filter *dvbdmxfilter) | |||
835 | 828 | ||
836 | static int StopHWFilter(struct dvb_demux_filter *dvbdmxfilter) | 829 | static int StopHWFilter(struct dvb_demux_filter *dvbdmxfilter) |
837 | { | 830 | { |
838 | struct av7110 *av7110 = (struct av7110 *) dvbdmxfilter->feed->demux->priv; | 831 | struct av7110 *av7110 = dvbdmxfilter->feed->demux->priv; |
839 | u16 buf[3]; | 832 | u16 buf[3]; |
840 | u16 answ[2]; | 833 | u16 answ[2]; |
841 | int ret; | 834 | int ret; |
@@ -871,7 +864,7 @@ static int StopHWFilter(struct dvb_demux_filter *dvbdmxfilter) | |||
871 | static int dvb_feed_start_pid(struct dvb_demux_feed *dvbdmxfeed) | 864 | static int dvb_feed_start_pid(struct dvb_demux_feed *dvbdmxfeed) |
872 | { | 865 | { |
873 | struct dvb_demux *dvbdmx = dvbdmxfeed->demux; | 866 | struct dvb_demux *dvbdmx = dvbdmxfeed->demux; |
874 | struct av7110 *av7110 = (struct av7110 *) dvbdmx->priv; | 867 | struct av7110 *av7110 = dvbdmx->priv; |
875 | u16 *pid = dvbdmx->pids, npids[5]; | 868 | u16 *pid = dvbdmx->pids, npids[5]; |
876 | int i; | 869 | int i; |
877 | int ret = 0; | 870 | int ret = 0; |
@@ -914,7 +907,7 @@ static int dvb_feed_start_pid(struct dvb_demux_feed *dvbdmxfeed) | |||
914 | static int dvb_feed_stop_pid(struct dvb_demux_feed *dvbdmxfeed) | 907 | static int dvb_feed_stop_pid(struct dvb_demux_feed *dvbdmxfeed) |
915 | { | 908 | { |
916 | struct dvb_demux *dvbdmx = dvbdmxfeed->demux; | 909 | struct dvb_demux *dvbdmx = dvbdmxfeed->demux; |
917 | struct av7110 *av7110 = (struct av7110 *) dvbdmx->priv; | 910 | struct av7110 *av7110 = dvbdmx->priv; |
918 | u16 *pid = dvbdmx->pids, npids[5]; | 911 | u16 *pid = dvbdmx->pids, npids[5]; |
919 | int i; | 912 | int i; |
920 | 913 | ||
@@ -1103,9 +1096,9 @@ static int dvb_get_stc(struct dmx_demux *demux, unsigned int num, | |||
1103 | 1096 | ||
1104 | /* pointer casting paranoia... */ | 1097 | /* pointer casting paranoia... */ |
1105 | BUG_ON(!demux); | 1098 | BUG_ON(!demux); |
1106 | dvbdemux = (struct dvb_demux *) demux->priv; | 1099 | dvbdemux = demux->priv; |
1107 | BUG_ON(!dvbdemux); | 1100 | BUG_ON(!dvbdemux); |
1108 | av7110 = (struct av7110 *) dvbdemux->priv; | 1101 | av7110 = dvbdemux->priv; |
1109 | 1102 | ||
1110 | dprintk(4, "%p\n", av7110); | 1103 | dprintk(4, "%p\n", av7110); |
1111 | 1104 | ||
@@ -1137,7 +1130,7 @@ static int dvb_get_stc(struct dmx_demux *demux, unsigned int num, | |||
1137 | 1130 | ||
1138 | static int av7110_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone) | 1131 | static int av7110_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone) |
1139 | { | 1132 | { |
1140 | struct av7110* av7110 = (struct av7110*) fe->dvb->priv; | 1133 | struct av7110* av7110 = fe->dvb->priv; |
1141 | 1134 | ||
1142 | switch (tone) { | 1135 | switch (tone) { |
1143 | case SEC_TONE_ON: | 1136 | case SEC_TONE_ON: |
@@ -1197,7 +1190,7 @@ static int start_ts_capture(struct av7110 *budget) | |||
1197 | static int budget_start_feed(struct dvb_demux_feed *feed) | 1190 | static int budget_start_feed(struct dvb_demux_feed *feed) |
1198 | { | 1191 | { |
1199 | struct dvb_demux *demux = feed->demux; | 1192 | struct dvb_demux *demux = feed->demux; |
1200 | struct av7110 *budget = (struct av7110 *) demux->priv; | 1193 | struct av7110 *budget = demux->priv; |
1201 | int status; | 1194 | int status; |
1202 | 1195 | ||
1203 | dprintk(2, "av7110: %p\n", budget); | 1196 | dprintk(2, "av7110: %p\n", budget); |
@@ -1212,7 +1205,7 @@ static int budget_start_feed(struct dvb_demux_feed *feed) | |||
1212 | static int budget_stop_feed(struct dvb_demux_feed *feed) | 1205 | static int budget_stop_feed(struct dvb_demux_feed *feed) |
1213 | { | 1206 | { |
1214 | struct dvb_demux *demux = feed->demux; | 1207 | struct dvb_demux *demux = feed->demux; |
1215 | struct av7110 *budget = (struct av7110 *) demux->priv; | 1208 | struct av7110 *budget = demux->priv; |
1216 | int status; | 1209 | int status; |
1217 | 1210 | ||
1218 | dprintk(2, "budget: %p\n", budget); | 1211 | dprintk(2, "budget: %p\n", budget); |
@@ -1551,7 +1544,7 @@ static int get_firmware(struct av7110* av7110) | |||
1551 | 1544 | ||
1552 | static int alps_bsrv2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params) | 1545 | static int alps_bsrv2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params) |
1553 | { | 1546 | { |
1554 | struct av7110* av7110 = (struct av7110*) fe->dvb->priv; | 1547 | struct av7110* av7110 = fe->dvb->priv; |
1555 | u8 pwr = 0; | 1548 | u8 pwr = 0; |
1556 | u8 buf[4]; | 1549 | u8 buf[4]; |
1557 | struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) }; | 1550 | struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) }; |
@@ -1702,7 +1695,7 @@ static int alps_tdlb7_tuner_set_params(struct dvb_frontend* fe, struct dvb_front | |||
1702 | static int alps_tdlb7_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name) | 1695 | static int alps_tdlb7_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name) |
1703 | { | 1696 | { |
1704 | #if defined(CONFIG_DVB_SP8870) || defined(CONFIG_DVB_SP8870_MODULE) | 1697 | #if defined(CONFIG_DVB_SP8870) || defined(CONFIG_DVB_SP8870_MODULE) |
1705 | struct av7110* av7110 = (struct av7110*) fe->dvb->priv; | 1698 | struct av7110* av7110 = fe->dvb->priv; |
1706 | 1699 | ||
1707 | return request_firmware(fw, name, &av7110->dev->pci->dev); | 1700 | return request_firmware(fw, name, &av7110->dev->pci->dev); |
1708 | #else | 1701 | #else |
@@ -1867,7 +1860,7 @@ static struct stv0297_config nexusca_stv0297_config = { | |||
1867 | 1860 | ||
1868 | static int grundig_29504_401_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params) | 1861 | static int grundig_29504_401_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params) |
1869 | { | 1862 | { |
1870 | struct av7110* av7110 = (struct av7110*) fe->dvb->priv; | 1863 | struct av7110* av7110 = fe->dvb->priv; |
1871 | u32 div; | 1864 | u32 div; |
1872 | u8 cfg, cpump, band_select; | 1865 | u8 cfg, cpump, band_select; |
1873 | u8 data[4]; | 1866 | u8 data[4]; |
@@ -2338,6 +2331,7 @@ static int __devinit av7110_attach(struct saa7146_dev* dev, | |||
2338 | const int length = TS_WIDTH * TS_HEIGHT; | 2331 | const int length = TS_WIDTH * TS_HEIGHT; |
2339 | struct pci_dev *pdev = dev->pci; | 2332 | struct pci_dev *pdev = dev->pci; |
2340 | struct av7110 *av7110; | 2333 | struct av7110 *av7110; |
2334 | struct task_struct *thread; | ||
2341 | int ret, count = 0; | 2335 | int ret, count = 0; |
2342 | 2336 | ||
2343 | dprintk(4, "dev: %p\n", dev); | 2337 | dprintk(4, "dev: %p\n", dev); |
@@ -2622,9 +2616,12 @@ static int __devinit av7110_attach(struct saa7146_dev* dev, | |||
2622 | printk ("dvb-ttpci: Warning, firmware version 0x%04x is too old. " | 2616 | printk ("dvb-ttpci: Warning, firmware version 0x%04x is too old. " |
2623 | "System might be unstable!\n", FW_VERSION(av7110->arm_app)); | 2617 | "System might be unstable!\n", FW_VERSION(av7110->arm_app)); |
2624 | 2618 | ||
2625 | ret = kernel_thread(arm_thread, (void *) av7110, 0); | 2619 | thread = kthread_run(arm_thread, (void *) av7110, "arm_mon"); |
2626 | if (ret < 0) | 2620 | if (IS_ERR(thread)) { |
2621 | ret = PTR_ERR(thread); | ||
2627 | goto err_stop_arm_9; | 2622 | goto err_stop_arm_9; |
2623 | } | ||
2624 | av7110->arm_thread = thread; | ||
2628 | 2625 | ||
2629 | /* set initial volume in mixer struct */ | 2626 | /* set initial volume in mixer struct */ |
2630 | av7110->mixer.volume_left = volume; | 2627 | av7110->mixer.volume_left = volume; |
diff --git a/drivers/media/dvb/ttpci/av7110.h b/drivers/media/dvb/ttpci/av7110.h index 9c79696da08a..b98bd453cade 100644 --- a/drivers/media/dvb/ttpci/av7110.h +++ b/drivers/media/dvb/ttpci/av7110.h | |||
@@ -35,7 +35,6 @@ | |||
35 | 35 | ||
36 | #define ANALOG_TUNER_VES1820 1 | 36 | #define ANALOG_TUNER_VES1820 1 |
37 | #define ANALOG_TUNER_STV0297 2 | 37 | #define ANALOG_TUNER_STV0297 2 |
38 | #define ANALOG_TUNER_VBI 0x100 | ||
39 | 38 | ||
40 | extern int av7110_debug; | 39 | extern int av7110_debug; |
41 | 40 | ||
@@ -205,7 +204,6 @@ struct av7110 { | |||
205 | struct task_struct *arm_thread; | 204 | struct task_struct *arm_thread; |
206 | wait_queue_head_t arm_wait; | 205 | wait_queue_head_t arm_wait; |
207 | u16 arm_loops; | 206 | u16 arm_loops; |
208 | int arm_rmmod; | ||
209 | 207 | ||
210 | void *debi_virt; | 208 | void *debi_virt; |
211 | dma_addr_t debi_bus; | 209 | dma_addr_t debi_bus; |
diff --git a/drivers/media/dvb/ttpci/av7110_av.c b/drivers/media/dvb/ttpci/av7110_av.c index 795e6e95915c..e719af807685 100644 --- a/drivers/media/dvb/ttpci/av7110_av.c +++ b/drivers/media/dvb/ttpci/av7110_av.c | |||
@@ -880,8 +880,8 @@ static int dvb_video_get_event (struct av7110 *av7110, struct video_event *event | |||
880 | 880 | ||
881 | static unsigned int dvb_video_poll(struct file *file, poll_table *wait) | 881 | static unsigned int dvb_video_poll(struct file *file, poll_table *wait) |
882 | { | 882 | { |
883 | struct dvb_device *dvbdev = (struct dvb_device *) file->private_data; | 883 | struct dvb_device *dvbdev = file->private_data; |
884 | struct av7110 *av7110 = (struct av7110 *) dvbdev->priv; | 884 | struct av7110 *av7110 = dvbdev->priv; |
885 | unsigned int mask = 0; | 885 | unsigned int mask = 0; |
886 | 886 | ||
887 | dprintk(2, "av7110:%p, \n", av7110); | 887 | dprintk(2, "av7110:%p, \n", av7110); |
@@ -908,8 +908,8 @@ static unsigned int dvb_video_poll(struct file *file, poll_table *wait) | |||
908 | static ssize_t dvb_video_write(struct file *file, const char __user *buf, | 908 | static ssize_t dvb_video_write(struct file *file, const char __user *buf, |
909 | size_t count, loff_t *ppos) | 909 | size_t count, loff_t *ppos) |
910 | { | 910 | { |
911 | struct dvb_device *dvbdev = (struct dvb_device *) file->private_data; | 911 | struct dvb_device *dvbdev = file->private_data; |
912 | struct av7110 *av7110 = (struct av7110 *) dvbdev->priv; | 912 | struct av7110 *av7110 = dvbdev->priv; |
913 | 913 | ||
914 | dprintk(2, "av7110:%p, \n", av7110); | 914 | dprintk(2, "av7110:%p, \n", av7110); |
915 | 915 | ||
@@ -924,8 +924,8 @@ static ssize_t dvb_video_write(struct file *file, const char __user *buf, | |||
924 | 924 | ||
925 | static unsigned int dvb_audio_poll(struct file *file, poll_table *wait) | 925 | static unsigned int dvb_audio_poll(struct file *file, poll_table *wait) |
926 | { | 926 | { |
927 | struct dvb_device *dvbdev = (struct dvb_device *) file->private_data; | 927 | struct dvb_device *dvbdev = file->private_data; |
928 | struct av7110 *av7110 = (struct av7110 *) dvbdev->priv; | 928 | struct av7110 *av7110 = dvbdev->priv; |
929 | unsigned int mask = 0; | 929 | unsigned int mask = 0; |
930 | 930 | ||
931 | dprintk(2, "av7110:%p, \n", av7110); | 931 | dprintk(2, "av7110:%p, \n", av7110); |
@@ -944,8 +944,8 @@ static unsigned int dvb_audio_poll(struct file *file, poll_table *wait) | |||
944 | static ssize_t dvb_audio_write(struct file *file, const char __user *buf, | 944 | static ssize_t dvb_audio_write(struct file *file, const char __user *buf, |
945 | size_t count, loff_t *ppos) | 945 | size_t count, loff_t *ppos) |
946 | { | 946 | { |
947 | struct dvb_device *dvbdev = (struct dvb_device *) file->private_data; | 947 | struct dvb_device *dvbdev = file->private_data; |
948 | struct av7110 *av7110 = (struct av7110 *) dvbdev->priv; | 948 | struct av7110 *av7110 = dvbdev->priv; |
949 | 949 | ||
950 | dprintk(2, "av7110:%p, \n", av7110); | 950 | dprintk(2, "av7110:%p, \n", av7110); |
951 | 951 | ||
@@ -989,8 +989,8 @@ static int play_iframe(struct av7110 *av7110, u8 __user *buf, unsigned int len, | |||
989 | static int dvb_video_ioctl(struct inode *inode, struct file *file, | 989 | static int dvb_video_ioctl(struct inode *inode, struct file *file, |
990 | unsigned int cmd, void *parg) | 990 | unsigned int cmd, void *parg) |
991 | { | 991 | { |
992 | struct dvb_device *dvbdev = (struct dvb_device *) file->private_data; | 992 | struct dvb_device *dvbdev = file->private_data; |
993 | struct av7110 *av7110 = (struct av7110 *) dvbdev->priv; | 993 | struct av7110 *av7110 = dvbdev->priv; |
994 | unsigned long arg = (unsigned long) parg; | 994 | unsigned long arg = (unsigned long) parg; |
995 | int ret = 0; | 995 | int ret = 0; |
996 | 996 | ||
@@ -1203,8 +1203,8 @@ static int dvb_video_ioctl(struct inode *inode, struct file *file, | |||
1203 | static int dvb_audio_ioctl(struct inode *inode, struct file *file, | 1203 | static int dvb_audio_ioctl(struct inode *inode, struct file *file, |
1204 | unsigned int cmd, void *parg) | 1204 | unsigned int cmd, void *parg) |
1205 | { | 1205 | { |
1206 | struct dvb_device *dvbdev = (struct dvb_device *) file->private_data; | 1206 | struct dvb_device *dvbdev = file->private_data; |
1207 | struct av7110 *av7110 = (struct av7110 *) dvbdev->priv; | 1207 | struct av7110 *av7110 = dvbdev->priv; |
1208 | unsigned long arg = (unsigned long) parg; | 1208 | unsigned long arg = (unsigned long) parg; |
1209 | int ret = 0; | 1209 | int ret = 0; |
1210 | 1210 | ||
@@ -1349,8 +1349,8 @@ static int dvb_audio_ioctl(struct inode *inode, struct file *file, | |||
1349 | 1349 | ||
1350 | static int dvb_video_open(struct inode *inode, struct file *file) | 1350 | static int dvb_video_open(struct inode *inode, struct file *file) |
1351 | { | 1351 | { |
1352 | struct dvb_device *dvbdev = (struct dvb_device *) file->private_data; | 1352 | struct dvb_device *dvbdev = file->private_data; |
1353 | struct av7110 *av7110 = (struct av7110 *) dvbdev->priv; | 1353 | struct av7110 *av7110 = dvbdev->priv; |
1354 | int err; | 1354 | int err; |
1355 | 1355 | ||
1356 | dprintk(2, "av7110:%p, \n", av7110); | 1356 | dprintk(2, "av7110:%p, \n", av7110); |
@@ -1374,8 +1374,8 @@ static int dvb_video_open(struct inode *inode, struct file *file) | |||
1374 | 1374 | ||
1375 | static int dvb_video_release(struct inode *inode, struct file *file) | 1375 | static int dvb_video_release(struct inode *inode, struct file *file) |
1376 | { | 1376 | { |
1377 | struct dvb_device *dvbdev = (struct dvb_device *) file->private_data; | 1377 | struct dvb_device *dvbdev = file->private_data; |
1378 | struct av7110 *av7110 = (struct av7110 *) dvbdev->priv; | 1378 | struct av7110 *av7110 = dvbdev->priv; |
1379 | 1379 | ||
1380 | dprintk(2, "av7110:%p, \n", av7110); | 1380 | dprintk(2, "av7110:%p, \n", av7110); |
1381 | 1381 | ||
@@ -1388,9 +1388,9 @@ static int dvb_video_release(struct inode *inode, struct file *file) | |||
1388 | 1388 | ||
1389 | static int dvb_audio_open(struct inode *inode, struct file *file) | 1389 | static int dvb_audio_open(struct inode *inode, struct file *file) |
1390 | { | 1390 | { |
1391 | struct dvb_device *dvbdev = (struct dvb_device *) file->private_data; | 1391 | struct dvb_device *dvbdev = file->private_data; |
1392 | struct av7110 *av7110 = (struct av7110 *) dvbdev->priv; | 1392 | struct av7110 *av7110 = dvbdev->priv; |
1393 | int err=dvb_generic_open(inode, file); | 1393 | int err = dvb_generic_open(inode, file); |
1394 | 1394 | ||
1395 | dprintk(2, "av7110:%p, \n", av7110); | 1395 | dprintk(2, "av7110:%p, \n", av7110); |
1396 | 1396 | ||
@@ -1403,8 +1403,8 @@ static int dvb_audio_open(struct inode *inode, struct file *file) | |||
1403 | 1403 | ||
1404 | static int dvb_audio_release(struct inode *inode, struct file *file) | 1404 | static int dvb_audio_release(struct inode *inode, struct file *file) |
1405 | { | 1405 | { |
1406 | struct dvb_device *dvbdev = (struct dvb_device *) file->private_data; | 1406 | struct dvb_device *dvbdev = file->private_data; |
1407 | struct av7110 *av7110 = (struct av7110 *) dvbdev->priv; | 1407 | struct av7110 *av7110 = dvbdev->priv; |
1408 | 1408 | ||
1409 | dprintk(2, "av7110:%p, \n", av7110); | 1409 | dprintk(2, "av7110:%p, \n", av7110); |
1410 | 1410 | ||
diff --git a/drivers/media/dvb/ttpci/av7110_ca.c b/drivers/media/dvb/ttpci/av7110_ca.c index 4251a97d420e..e9b4e88e7932 100644 --- a/drivers/media/dvb/ttpci/av7110_ca.c +++ b/drivers/media/dvb/ttpci/av7110_ca.c | |||
@@ -214,8 +214,8 @@ static ssize_t ci_ll_read(struct dvb_ringbuffer *cibuf, struct file *file, | |||
214 | 214 | ||
215 | static int dvb_ca_open(struct inode *inode, struct file *file) | 215 | static int dvb_ca_open(struct inode *inode, struct file *file) |
216 | { | 216 | { |
217 | struct dvb_device *dvbdev = (struct dvb_device *) file->private_data; | 217 | struct dvb_device *dvbdev = file->private_data; |
218 | struct av7110 *av7110 = (struct av7110 *) dvbdev->priv; | 218 | struct av7110 *av7110 = dvbdev->priv; |
219 | int err = dvb_generic_open(inode, file); | 219 | int err = dvb_generic_open(inode, file); |
220 | 220 | ||
221 | dprintk(8, "av7110:%p\n",av7110); | 221 | dprintk(8, "av7110:%p\n",av7110); |
@@ -228,8 +228,8 @@ static int dvb_ca_open(struct inode *inode, struct file *file) | |||
228 | 228 | ||
229 | static unsigned int dvb_ca_poll (struct file *file, poll_table *wait) | 229 | static unsigned int dvb_ca_poll (struct file *file, poll_table *wait) |
230 | { | 230 | { |
231 | struct dvb_device *dvbdev = (struct dvb_device *) file->private_data; | 231 | struct dvb_device *dvbdev = file->private_data; |
232 | struct av7110 *av7110 = (struct av7110 *) dvbdev->priv; | 232 | struct av7110 *av7110 = dvbdev->priv; |
233 | struct dvb_ringbuffer *rbuf = &av7110->ci_rbuffer; | 233 | struct dvb_ringbuffer *rbuf = &av7110->ci_rbuffer; |
234 | struct dvb_ringbuffer *wbuf = &av7110->ci_wbuffer; | 234 | struct dvb_ringbuffer *wbuf = &av7110->ci_wbuffer; |
235 | unsigned int mask = 0; | 235 | unsigned int mask = 0; |
@@ -251,8 +251,8 @@ static unsigned int dvb_ca_poll (struct file *file, poll_table *wait) | |||
251 | static int dvb_ca_ioctl(struct inode *inode, struct file *file, | 251 | static int dvb_ca_ioctl(struct inode *inode, struct file *file, |
252 | unsigned int cmd, void *parg) | 252 | unsigned int cmd, void *parg) |
253 | { | 253 | { |
254 | struct dvb_device *dvbdev = (struct dvb_device *) file->private_data; | 254 | struct dvb_device *dvbdev = file->private_data; |
255 | struct av7110 *av7110 = (struct av7110 *) dvbdev->priv; | 255 | struct av7110 *av7110 = dvbdev->priv; |
256 | unsigned long arg = (unsigned long) parg; | 256 | unsigned long arg = (unsigned long) parg; |
257 | 257 | ||
258 | dprintk(8, "av7110:%p\n",av7110); | 258 | dprintk(8, "av7110:%p\n",av7110); |
@@ -329,8 +329,8 @@ static int dvb_ca_ioctl(struct inode *inode, struct file *file, | |||
329 | static ssize_t dvb_ca_write(struct file *file, const char __user *buf, | 329 | static ssize_t dvb_ca_write(struct file *file, const char __user *buf, |
330 | size_t count, loff_t *ppos) | 330 | size_t count, loff_t *ppos) |
331 | { | 331 | { |
332 | struct dvb_device *dvbdev = (struct dvb_device *) file->private_data; | 332 | struct dvb_device *dvbdev = file->private_data; |
333 | struct av7110 *av7110 = (struct av7110 *) dvbdev->priv; | 333 | struct av7110 *av7110 = dvbdev->priv; |
334 | 334 | ||
335 | dprintk(8, "av7110:%p\n",av7110); | 335 | dprintk(8, "av7110:%p\n",av7110); |
336 | return ci_ll_write(&av7110->ci_wbuffer, file, buf, count, ppos); | 336 | return ci_ll_write(&av7110->ci_wbuffer, file, buf, count, ppos); |
@@ -339,15 +339,13 @@ static ssize_t dvb_ca_write(struct file *file, const char __user *buf, | |||
339 | static ssize_t dvb_ca_read(struct file *file, char __user *buf, | 339 | static ssize_t dvb_ca_read(struct file *file, char __user *buf, |
340 | size_t count, loff_t *ppos) | 340 | size_t count, loff_t *ppos) |
341 | { | 341 | { |
342 | struct dvb_device *dvbdev = (struct dvb_device *) file->private_data; | 342 | struct dvb_device *dvbdev = file->private_data; |
343 | struct av7110 *av7110 = (struct av7110 *) dvbdev->priv; | 343 | struct av7110 *av7110 = dvbdev->priv; |
344 | 344 | ||
345 | dprintk(8, "av7110:%p\n",av7110); | 345 | dprintk(8, "av7110:%p\n",av7110); |
346 | return ci_ll_read(&av7110->ci_rbuffer, file, buf, count, ppos); | 346 | return ci_ll_read(&av7110->ci_rbuffer, file, buf, count, ppos); |
347 | } | 347 | } |
348 | 348 | ||
349 | |||
350 | |||
351 | static struct file_operations dvb_ca_fops = { | 349 | static struct file_operations dvb_ca_fops = { |
352 | .owner = THIS_MODULE, | 350 | .owner = THIS_MODULE, |
353 | .read = dvb_ca_read, | 351 | .read = dvb_ca_read, |
diff --git a/drivers/media/dvb/ttpci/av7110_ir.c b/drivers/media/dvb/ttpci/av7110_ir.c index e4544ea2b89b..f59465bb0af3 100644 --- a/drivers/media/dvb/ttpci/av7110_ir.c +++ b/drivers/media/dvb/ttpci/av7110_ir.c | |||
@@ -4,6 +4,7 @@ | |||
4 | #include <linux/moduleparam.h> | 4 | #include <linux/moduleparam.h> |
5 | #include <linux/input.h> | 5 | #include <linux/input.h> |
6 | #include <linux/proc_fs.h> | 6 | #include <linux/proc_fs.h> |
7 | #include <linux/kernel.h> | ||
7 | #include <asm/bitops.h> | 8 | #include <asm/bitops.h> |
8 | 9 | ||
9 | #include "av7110.h" | 10 | #include "av7110.h" |
@@ -16,6 +17,7 @@ | |||
16 | static int av_cnt; | 17 | static int av_cnt; |
17 | static struct av7110 *av_list[4]; | 18 | static struct av7110 *av_list[4]; |
18 | static struct input_dev *input_dev; | 19 | static struct input_dev *input_dev; |
20 | static char input_phys[32]; | ||
19 | 21 | ||
20 | static u8 delay_timer_finished; | 22 | static u8 delay_timer_finished; |
21 | 23 | ||
@@ -217,7 +219,7 @@ int __devinit av7110_ir_init(struct av7110 *av7110) | |||
217 | static struct proc_dir_entry *e; | 219 | static struct proc_dir_entry *e; |
218 | int err; | 220 | int err; |
219 | 221 | ||
220 | if (av_cnt >= sizeof av_list/sizeof av_list[0]) | 222 | if (av_cnt >= ARRAY_SIZE(av_list)) |
221 | return -ENOSPC; | 223 | return -ENOSPC; |
222 | 224 | ||
223 | av7110_setup_irc_config(av7110, 0x0001); | 225 | av7110_setup_irc_config(av7110, 0x0001); |
@@ -231,8 +233,22 @@ int __devinit av7110_ir_init(struct av7110 *av7110) | |||
231 | if (!input_dev) | 233 | if (!input_dev) |
232 | return -ENOMEM; | 234 | return -ENOMEM; |
233 | 235 | ||
236 | snprintf(input_phys, sizeof(input_phys), | ||
237 | "pci-%s/ir0", pci_name(av7110->dev->pci)); | ||
238 | |||
234 | input_dev->name = "DVB on-card IR receiver"; | 239 | input_dev->name = "DVB on-card IR receiver"; |
235 | 240 | ||
241 | input_dev->phys = input_phys; | ||
242 | input_dev->id.bustype = BUS_PCI; | ||
243 | input_dev->id.version = 1; | ||
244 | if (av7110->dev->pci->subsystem_vendor) { | ||
245 | input_dev->id.vendor = av7110->dev->pci->subsystem_vendor; | ||
246 | input_dev->id.product = av7110->dev->pci->subsystem_device; | ||
247 | } else { | ||
248 | input_dev->id.vendor = av7110->dev->pci->vendor; | ||
249 | input_dev->id.product = av7110->dev->pci->device; | ||
250 | } | ||
251 | input_dev->cdev.dev = &av7110->dev->pci->dev; | ||
236 | set_bit(EV_KEY, input_dev->evbit); | 252 | set_bit(EV_KEY, input_dev->evbit); |
237 | set_bit(EV_REP, input_dev->evbit); | 253 | set_bit(EV_REP, input_dev->evbit); |
238 | input_register_keys(); | 254 | input_register_keys(); |
diff --git a/drivers/media/dvb/ttpci/av7110_v4l.c b/drivers/media/dvb/ttpci/av7110_v4l.c index dbfd5e7b4be0..cde5d3ae7ec7 100644 --- a/drivers/media/dvb/ttpci/av7110_v4l.c +++ b/drivers/media/dvb/ttpci/av7110_v4l.c | |||
@@ -140,17 +140,6 @@ static int ves1820_writereg(struct saa7146_dev *dev, u8 addr, u8 reg, u8 data) | |||
140 | return 0; | 140 | return 0; |
141 | } | 141 | } |
142 | 142 | ||
143 | static int stv0297_writereg(struct saa7146_dev *dev, u8 addr, u8 reg, u8 data) | ||
144 | { | ||
145 | u8 buf [] = { reg, data }; | ||
146 | struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = buf, .len = 2 }; | ||
147 | |||
148 | if (1 != saa7146_i2c_transfer(dev, &msg, 1, 1)) | ||
149 | return -1; | ||
150 | return 0; | ||
151 | } | ||
152 | |||
153 | |||
154 | static int tuner_write(struct saa7146_dev *dev, u8 addr, u8 data [4]) | 143 | static int tuner_write(struct saa7146_dev *dev, u8 addr, u8 data [4]) |
155 | { | 144 | { |
156 | struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = data, .len = 4 }; | 145 | struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = data, .len = 4 }; |
@@ -193,6 +182,7 @@ static int ves1820_set_tv_freq(struct saa7146_dev *dev, u32 freq) | |||
193 | 182 | ||
194 | static int stv0297_set_tv_freq(struct saa7146_dev *dev, u32 freq) | 183 | static int stv0297_set_tv_freq(struct saa7146_dev *dev, u32 freq) |
195 | { | 184 | { |
185 | struct av7110 *av7110 = (struct av7110*)dev->ext_priv; | ||
196 | u32 div; | 186 | u32 div; |
197 | u8 data[4]; | 187 | u8 data[4]; |
198 | 188 | ||
@@ -213,8 +203,8 @@ static int stv0297_set_tv_freq(struct saa7146_dev *dev, u32 freq) | |||
213 | else | 203 | else |
214 | return -EINVAL; | 204 | return -EINVAL; |
215 | 205 | ||
216 | stv0297_writereg(dev, 0x1C, 0x87, 0x78); | 206 | if (av7110->fe->ops.i2c_gate_ctrl) |
217 | stv0297_writereg(dev, 0x1C, 0x86, 0xc8); | 207 | av7110->fe->ops.i2c_gate_ctrl(av7110->fe, 1); |
218 | return tuner_write(dev, 0x63, data); | 208 | return tuner_write(dev, 0x63, data); |
219 | } | 209 | } |
220 | 210 | ||
@@ -817,20 +807,20 @@ int av7110_init_v4l(struct av7110 *av7110) | |||
817 | saa7146_vv_release(dev); | 807 | saa7146_vv_release(dev); |
818 | return -ENODEV; | 808 | return -ENODEV; |
819 | } | 809 | } |
820 | if (saa7146_register_device(&av7110->vbi_dev, dev, "av7110", VFL_TYPE_VBI)) { | 810 | if (saa7146_register_device(&av7110->vbi_dev, dev, "av7110", VFL_TYPE_VBI)) |
821 | ERR(("cannot register vbi v4l2 device. skipping.\n")); | 811 | ERR(("cannot register vbi v4l2 device. skipping.\n")); |
822 | } else { | ||
823 | if (av7110->analog_tuner_flags) | ||
824 | av7110->analog_tuner_flags |= ANALOG_TUNER_VBI; | ||
825 | } | ||
826 | return 0; | 812 | return 0; |
827 | } | 813 | } |
828 | 814 | ||
829 | int av7110_exit_v4l(struct av7110 *av7110) | 815 | int av7110_exit_v4l(struct av7110 *av7110) |
830 | { | 816 | { |
817 | struct saa7146_dev* dev = av7110->dev; | ||
818 | |||
831 | saa7146_unregister_device(&av7110->v4l_dev, av7110->dev); | 819 | saa7146_unregister_device(&av7110->v4l_dev, av7110->dev); |
832 | if (av7110->analog_tuner_flags & ANALOG_TUNER_VBI) | 820 | saa7146_unregister_device(&av7110->vbi_dev, av7110->dev); |
833 | saa7146_unregister_device(&av7110->vbi_dev, av7110->dev); | 821 | |
822 | saa7146_vv_release(dev); | ||
823 | |||
834 | return 0; | 824 | return 0; |
835 | } | 825 | } |
836 | 826 | ||
diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c index 89ab4b59155c..3035b224c7a3 100644 --- a/drivers/media/dvb/ttpci/budget-av.c +++ b/drivers/media/dvb/ttpci/budget-av.c | |||
@@ -1089,6 +1089,8 @@ static int budget_av_detach(struct saa7146_dev *dev) | |||
1089 | msleep(200); | 1089 | msleep(200); |
1090 | 1090 | ||
1091 | saa7146_unregister_device(&budget_av->vd, dev); | 1091 | saa7146_unregister_device(&budget_av->vd, dev); |
1092 | |||
1093 | saa7146_vv_release(dev); | ||
1092 | } | 1094 | } |
1093 | 1095 | ||
1094 | if (budget_av->budget.ci_present) | 1096 | if (budget_av->budget.ci_present) |
@@ -1145,6 +1147,7 @@ static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio | |||
1145 | if ((err = saa7146_register_device(&budget_av->vd, dev, "knc1", VFL_TYPE_GRABBER))) { | 1147 | if ((err = saa7146_register_device(&budget_av->vd, dev, "knc1", VFL_TYPE_GRABBER))) { |
1146 | /* fixme: proper cleanup here */ | 1148 | /* fixme: proper cleanup here */ |
1147 | ERR(("cannot register capture v4l2 device.\n")); | 1149 | ERR(("cannot register capture v4l2 device.\n")); |
1150 | saa7146_vv_release(dev); | ||
1148 | return err; | 1151 | return err; |
1149 | } | 1152 | } |
1150 | 1153 | ||
diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c index f2066b47baee..464feaf1a9ad 100644 --- a/drivers/media/dvb/ttpci/budget-ci.c +++ b/drivers/media/dvb/ttpci/budget-ci.c | |||
@@ -29,8 +29,6 @@ | |||
29 | * the project's page is at http://www.linuxtv.org/dvb/ | 29 | * the project's page is at http://www.linuxtv.org/dvb/ |
30 | */ | 30 | */ |
31 | 31 | ||
32 | #include "budget.h" | ||
33 | |||
34 | #include <linux/module.h> | 32 | #include <linux/module.h> |
35 | #include <linux/errno.h> | 33 | #include <linux/errno.h> |
36 | #include <linux/slab.h> | 34 | #include <linux/slab.h> |
@@ -39,6 +37,8 @@ | |||
39 | #include <linux/spinlock.h> | 37 | #include <linux/spinlock.h> |
40 | #include <media/ir-common.h> | 38 | #include <media/ir-common.h> |
41 | 39 | ||
40 | #include "budget.h" | ||
41 | |||
42 | #include "dvb_ca_en50221.h" | 42 | #include "dvb_ca_en50221.h" |
43 | #include "stv0299.h" | 43 | #include "stv0299.h" |
44 | #include "stv0297.h" | 44 | #include "stv0297.h" |
@@ -130,6 +130,7 @@ static void msp430_ir_interrupt(unsigned long data) | |||
130 | int toggle; | 130 | int toggle; |
131 | static int prev_toggle = -1; | 131 | static int prev_toggle = -1; |
132 | static u32 ir_key; | 132 | static u32 ir_key; |
133 | static int state = 0; | ||
133 | u32 command = ttpci_budget_debiread(&budget_ci->budget, DEBINOSWAP, DEBIADDR_IR, 2, 1, 0) >> 8; | 134 | u32 command = ttpci_budget_debiread(&budget_ci->budget, DEBINOSWAP, DEBIADDR_IR, 2, 1, 0) >> 8; |
134 | 135 | ||
135 | /* | 136 | /* |
@@ -138,21 +139,34 @@ static void msp430_ir_interrupt(unsigned long data) | |||
138 | * type1: X1CCCCCC, C = command bits (0 - 63) | 139 | * type1: X1CCCCCC, C = command bits (0 - 63) |
139 | * type2: X0TDDDDD, D = device bits (0 - 31), T = RC5 toggle bit | 140 | * type2: X0TDDDDD, D = device bits (0 - 31), T = RC5 toggle bit |
140 | * | 141 | * |
141 | * More than one command byte may be generated before the device byte | 142 | * Each signal from the remote control can generate one or more command |
142 | * Only when we have both, a correct keypress is generated | 143 | * bytes and one or more device bytes. For the repeated bytes, the |
144 | * highest bit (X) is set. The first command byte is always generated | ||
145 | * before the first device byte. Other than that, no specific order | ||
146 | * seems to apply. | ||
147 | * | ||
148 | * Only when we have a command and device byte, a keypress is | ||
149 | * generated. | ||
143 | */ | 150 | */ |
144 | 151 | ||
152 | if (ir_debug) | ||
153 | printk("budget_ci: received byte 0x%02x\n", command); | ||
154 | |||
155 | /* Is this a repeated byte? */ | ||
156 | if (command & 0x80) | ||
157 | return; | ||
158 | |||
145 | /* Is this a RC5 command byte? */ | 159 | /* Is this a RC5 command byte? */ |
146 | if (command & 0x40) { | 160 | if (command & 0x40) { |
147 | if (ir_debug) | 161 | state = 1; |
148 | printk("budget_ci: received command byte 0x%02x\n", command); | ||
149 | ir_key = command & 0x3f; | 162 | ir_key = command & 0x3f; |
150 | return; | 163 | return; |
151 | } | 164 | } |
152 | 165 | ||
153 | /* It's a RC5 device byte */ | 166 | /* It's a RC5 device byte */ |
154 | if (ir_debug) | 167 | if (!state) |
155 | printk("budget_ci: received device byte 0x%02x\n", command); | 168 | return; |
169 | state = 0; | ||
156 | device = command & 0x1f; | 170 | device = command & 0x1f; |
157 | toggle = command & 0x20; | 171 | toggle = command & 0x20; |
158 | 172 | ||
@@ -223,7 +237,6 @@ static int msp430_ir_init(struct budget_ci *budget_ci) | |||
223 | switch (budget_ci->budget.dev->pci->subsystem_device) { | 237 | switch (budget_ci->budget.dev->pci->subsystem_device) { |
224 | case 0x100c: | 238 | case 0x100c: |
225 | case 0x100f: | 239 | case 0x100f: |
226 | case 0x1010: | ||
227 | case 0x1011: | 240 | case 0x1011: |
228 | case 0x1012: | 241 | case 0x1012: |
229 | case 0x1017: | 242 | case 0x1017: |
@@ -236,6 +249,16 @@ static int msp430_ir_init(struct budget_ci *budget_ci) | |||
236 | else | 249 | else |
237 | budget_ci->ir.rc5_device = rc5_device; | 250 | budget_ci->ir.rc5_device = rc5_device; |
238 | break; | 251 | break; |
252 | case 0x1010: | ||
253 | /* for the Technotrend 1500 bundled remote */ | ||
254 | ir_input_init(input_dev, &budget_ci->ir.state, | ||
255 | IR_TYPE_RC5, ir_codes_tt_1500); | ||
256 | |||
257 | if (rc5_device < 0) | ||
258 | budget_ci->ir.rc5_device = IR_DEVICE_ANY; | ||
259 | else | ||
260 | budget_ci->ir.rc5_device = rc5_device; | ||
261 | break; | ||
239 | default: | 262 | default: |
240 | /* unknown remote */ | 263 | /* unknown remote */ |
241 | ir_input_init(input_dev, &budget_ci->ir.state, | 264 | ir_input_init(input_dev, &budget_ci->ir.state, |
@@ -869,6 +892,17 @@ static struct tda1004x_config philips_tdm1316l_config = { | |||
869 | .request_firmware = philips_tdm1316l_request_firmware, | 892 | .request_firmware = philips_tdm1316l_request_firmware, |
870 | }; | 893 | }; |
871 | 894 | ||
895 | static struct tda1004x_config philips_tdm1316l_config_invert = { | ||
896 | |||
897 | .demod_address = 0x8, | ||
898 | .invert = 1, | ||
899 | .invert_oclk = 0, | ||
900 | .xtal_freq = TDA10046_XTAL_4M, | ||
901 | .agc_config = TDA10046_AGC_DEFAULT, | ||
902 | .if_freq = TDA10046_FREQ_3617, | ||
903 | .request_firmware = philips_tdm1316l_request_firmware, | ||
904 | }; | ||
905 | |||
872 | static int dvbc_philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) | 906 | static int dvbc_philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) |
873 | { | 907 | { |
874 | struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv; | 908 | struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv; |
@@ -1092,9 +1126,8 @@ static void frontend_init(struct budget_ci *budget_ci) | |||
1092 | 1126 | ||
1093 | case 0x1012: // TT DVB-T CI budget (tda10046/Philips tdm1316l(tda6651tt)) | 1127 | case 0x1012: // TT DVB-T CI budget (tda10046/Philips tdm1316l(tda6651tt)) |
1094 | budget_ci->tuner_pll_address = 0x60; | 1128 | budget_ci->tuner_pll_address = 0x60; |
1095 | philips_tdm1316l_config.invert = 1; | ||
1096 | budget_ci->budget.dvb_frontend = | 1129 | budget_ci->budget.dvb_frontend = |
1097 | dvb_attach(tda10046_attach, &philips_tdm1316l_config, &budget_ci->budget.i2c_adap); | 1130 | dvb_attach(tda10046_attach, &philips_tdm1316l_config_invert, &budget_ci->budget.i2c_adap); |
1098 | if (budget_ci->budget.dvb_frontend) { | 1131 | if (budget_ci->budget.dvb_frontend) { |
1099 | budget_ci->budget.dvb_frontend->ops.tuner_ops.init = philips_tdm1316l_tuner_init; | 1132 | budget_ci->budget.dvb_frontend->ops.tuner_ops.init = philips_tdm1316l_tuner_init; |
1100 | budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = philips_tdm1316l_tuner_set_params; | 1133 | budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = philips_tdm1316l_tuner_set_params; |
diff --git a/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/drivers/media/dvb/ttusb-dec/ttusb_dec.c index bd6e7baae2ec..78c98b089975 100644 --- a/drivers/media/dvb/ttusb-dec/ttusb_dec.c +++ b/drivers/media/dvb/ttusb-dec/ttusb_dec.c | |||
@@ -20,8 +20,6 @@ | |||
20 | * | 20 | * |
21 | */ | 21 | */ |
22 | 22 | ||
23 | #include <linux/mutex.h> | ||
24 | |||
25 | #include <linux/list.h> | 23 | #include <linux/list.h> |
26 | #include <linux/module.h> | 24 | #include <linux/module.h> |
27 | #include <linux/moduleparam.h> | 25 | #include <linux/moduleparam.h> |
@@ -35,6 +33,8 @@ | |||
35 | #include <linux/init.h> | 33 | #include <linux/init.h> |
36 | #include <linux/input.h> | 34 | #include <linux/input.h> |
37 | 35 | ||
36 | #include <linux/mutex.h> | ||
37 | |||
38 | #include "dmxdev.h" | 38 | #include "dmxdev.h" |
39 | #include "dvb_demux.h" | 39 | #include "dvb_demux.h" |
40 | #include "dvb_filter.h" | 40 | #include "dvb_filter.h" |
diff --git a/drivers/media/radio/radio-aztech.c b/drivers/media/radio/radio-aztech.c index 19d45cc940b5..9f1addae6928 100644 --- a/drivers/media/radio/radio-aztech.c +++ b/drivers/media/radio/radio-aztech.c | |||
@@ -180,136 +180,163 @@ static int az_setfreq(struct az_device *dev, unsigned long frequency) | |||
180 | return 0; | 180 | return 0; |
181 | } | 181 | } |
182 | 182 | ||
183 | static int az_do_ioctl(struct inode *inode, struct file *file, | 183 | static int vidioc_querycap (struct file *file, void *priv, |
184 | unsigned int cmd, void *arg) | 184 | struct v4l2_capability *v) |
185 | { | ||
186 | strlcpy(v->driver, "radio-aztech", sizeof (v->driver)); | ||
187 | strlcpy(v->card, "Aztech Radio", sizeof (v->card)); | ||
188 | sprintf(v->bus_info,"ISA"); | ||
189 | v->version = RADIO_VERSION; | ||
190 | v->capabilities = V4L2_CAP_TUNER; | ||
191 | return 0; | ||
192 | } | ||
193 | |||
194 | static int vidioc_g_tuner (struct file *file, void *priv, | ||
195 | struct v4l2_tuner *v) | ||
185 | { | 196 | { |
186 | struct video_device *dev = video_devdata(file); | 197 | struct video_device *dev = video_devdata(file); |
187 | struct az_device *az = dev->priv; | 198 | struct az_device *az = dev->priv; |
188 | 199 | ||
189 | switch(cmd) | 200 | if (v->index > 0) |
190 | { | 201 | return -EINVAL; |
191 | case VIDIOC_QUERYCAP: | ||
192 | { | ||
193 | struct v4l2_capability *v = arg; | ||
194 | memset(v,0,sizeof(*v)); | ||
195 | strlcpy(v->driver, "radio-aztech", sizeof (v->driver)); | ||
196 | strlcpy(v->card, "Aztech Radio", sizeof (v->card)); | ||
197 | sprintf(v->bus_info,"ISA"); | ||
198 | v->version = RADIO_VERSION; | ||
199 | v->capabilities = V4L2_CAP_TUNER; | ||
200 | 202 | ||
201 | return 0; | 203 | strcpy(v->name, "FM"); |
202 | } | 204 | v->type = V4L2_TUNER_RADIO; |
203 | case VIDIOC_G_TUNER: | ||
204 | { | ||
205 | struct v4l2_tuner *v = arg; | ||
206 | |||
207 | if (v->index > 0) | ||
208 | return -EINVAL; | ||
209 | |||
210 | memset(v,0,sizeof(*v)); | ||
211 | strcpy(v->name, "FM"); | ||
212 | v->type = V4L2_TUNER_RADIO; | ||
213 | |||
214 | v->rangelow=(87*16000); | ||
215 | v->rangehigh=(108*16000); | ||
216 | v->rxsubchans =V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO; | ||
217 | v->capability=V4L2_TUNER_CAP_LOW; | ||
218 | if(az_getstereo(az)) | ||
219 | v->audmode = V4L2_TUNER_MODE_STEREO; | ||
220 | else | ||
221 | v->audmode = V4L2_TUNER_MODE_MONO; | ||
222 | v->signal=0xFFFF*az_getsigstr(az); | ||
223 | 205 | ||
224 | return 0; | 206 | v->rangelow=(87*16000); |
225 | } | 207 | v->rangehigh=(108*16000); |
226 | case VIDIOC_S_TUNER: | 208 | v->rxsubchans =V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO; |
227 | { | 209 | v->capability=V4L2_TUNER_CAP_LOW; |
228 | struct v4l2_tuner *v = arg; | 210 | if(az_getstereo(az)) |
211 | v->audmode = V4L2_TUNER_MODE_STEREO; | ||
212 | else | ||
213 | v->audmode = V4L2_TUNER_MODE_MONO; | ||
214 | v->signal=0xFFFF*az_getsigstr(az); | ||
229 | 215 | ||
230 | if (v->index > 0) | 216 | return 0; |
231 | return -EINVAL; | 217 | } |
232 | 218 | ||
233 | return 0; | ||
234 | } | ||
235 | case VIDIOC_S_FREQUENCY: | ||
236 | { | ||
237 | struct v4l2_frequency *f = arg; | ||
238 | 219 | ||
239 | az->curfreq = f->frequency; | 220 | static int vidioc_s_tuner (struct file *file, void *priv, |
240 | az_setfreq(az, az->curfreq); | 221 | struct v4l2_tuner *v) |
241 | return 0; | 222 | { |
242 | } | 223 | if (v->index > 0) |
243 | case VIDIOC_G_FREQUENCY: | 224 | return -EINVAL; |
244 | { | ||
245 | struct v4l2_frequency *f = arg; | ||
246 | 225 | ||
247 | f->type = V4L2_TUNER_RADIO; | 226 | return 0; |
248 | f->frequency = az->curfreq; | 227 | } |
249 | 228 | ||
250 | return 0; | 229 | static int vidioc_g_audio (struct file *file, void *priv, |
251 | } | 230 | struct v4l2_audio *a) |
231 | { | ||
232 | if (a->index > 1) | ||
233 | return -EINVAL; | ||
252 | 234 | ||
253 | case VIDIOC_QUERYCTRL: | 235 | strcpy(a->name, "Radio"); |
254 | { | 236 | a->capability = V4L2_AUDCAP_STEREO; |
255 | struct v4l2_queryctrl *qc = arg; | 237 | return 0; |
256 | int i; | 238 | } |
257 | 239 | ||
258 | for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { | 240 | static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) |
259 | if (qc->id && qc->id == radio_qctrl[i].id) { | 241 | { |
260 | memcpy(qc, &(radio_qctrl[i]), | 242 | *i = 0; |
261 | sizeof(*qc)); | 243 | return 0; |
262 | return (0); | 244 | } |
263 | } | 245 | |
264 | } | 246 | static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) |
265 | return -EINVAL; | 247 | { |
266 | } | 248 | if (i != 0) |
267 | case VIDIOC_G_CTRL: | 249 | return -EINVAL; |
268 | { | 250 | return 0; |
269 | struct v4l2_control *ctrl= arg; | 251 | } |
270 | 252 | ||
271 | switch (ctrl->id) { | 253 | |
272 | case V4L2_CID_AUDIO_MUTE: | 254 | static int vidioc_s_audio (struct file *file, void *priv, |
273 | if (az->curvol==0) | 255 | struct v4l2_audio *a) |
274 | ctrl->value=1; | 256 | { |
275 | else | 257 | if (a->index != 0) |
276 | ctrl->value=0; | 258 | return -EINVAL; |
277 | return (0); | 259 | |
278 | case V4L2_CID_AUDIO_VOLUME: | 260 | return 0; |
279 | ctrl->value=az->curvol * 6554; | 261 | } |
280 | return (0); | 262 | |
281 | } | 263 | static int vidioc_s_frequency (struct file *file, void *priv, |
282 | return -EINVAL; | 264 | struct v4l2_frequency *f) |
283 | } | 265 | { |
284 | case VIDIOC_S_CTRL: | 266 | struct video_device *dev = video_devdata(file); |
285 | { | 267 | struct az_device *az = dev->priv; |
286 | struct v4l2_control *ctrl= arg; | 268 | |
287 | 269 | az->curfreq = f->frequency; | |
288 | switch (ctrl->id) { | 270 | az_setfreq(az, az->curfreq); |
289 | case V4L2_CID_AUDIO_MUTE: | 271 | return 0; |
290 | if (ctrl->value) { | 272 | } |
291 | az_setvol(az,0); | 273 | |
292 | } else { | 274 | static int vidioc_g_frequency (struct file *file, void *priv, |
293 | az_setvol(az,az->curvol); | 275 | struct v4l2_frequency *f) |
294 | } | 276 | { |
295 | return (0); | 277 | struct video_device *dev = video_devdata(file); |
296 | case V4L2_CID_AUDIO_VOLUME: | 278 | struct az_device *az = dev->priv; |
297 | az_setvol(az,ctrl->value); | 279 | |
298 | return (0); | 280 | f->type = V4L2_TUNER_RADIO; |
299 | } | 281 | f->frequency = az->curfreq; |
300 | return -EINVAL; | 282 | |
283 | return 0; | ||
284 | } | ||
285 | |||
286 | static int vidioc_queryctrl (struct file *file, void *priv, | ||
287 | struct v4l2_queryctrl *qc) | ||
288 | { | ||
289 | int i; | ||
290 | |||
291 | for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { | ||
292 | if (qc->id && qc->id == radio_qctrl[i].id) { | ||
293 | memcpy(qc, &(radio_qctrl[i]), | ||
294 | sizeof(*qc)); | ||
295 | return (0); | ||
301 | } | 296 | } |
297 | } | ||
298 | return -EINVAL; | ||
299 | } | ||
300 | |||
301 | static int vidioc_g_ctrl (struct file *file, void *priv, | ||
302 | struct v4l2_control *ctrl) | ||
303 | { | ||
304 | struct video_device *dev = video_devdata(file); | ||
305 | struct az_device *az = dev->priv; | ||
302 | 306 | ||
303 | default: | 307 | switch (ctrl->id) { |
304 | return v4l_compat_translate_ioctl(inode,file,cmd,arg, | 308 | case V4L2_CID_AUDIO_MUTE: |
305 | az_do_ioctl); | 309 | if (az->curvol==0) |
310 | ctrl->value=1; | ||
311 | else | ||
312 | ctrl->value=0; | ||
313 | return (0); | ||
314 | case V4L2_CID_AUDIO_VOLUME: | ||
315 | ctrl->value=az->curvol * 6554; | ||
316 | return (0); | ||
306 | } | 317 | } |
318 | return -EINVAL; | ||
307 | } | 319 | } |
308 | 320 | ||
309 | static int az_ioctl(struct inode *inode, struct file *file, | 321 | static int vidioc_s_ctrl (struct file *file, void *priv, |
310 | unsigned int cmd, unsigned long arg) | 322 | struct v4l2_control *ctrl) |
311 | { | 323 | { |
312 | return video_usercopy(inode, file, cmd, arg, az_do_ioctl); | 324 | struct video_device *dev = video_devdata(file); |
325 | struct az_device *az = dev->priv; | ||
326 | |||
327 | switch (ctrl->id) { | ||
328 | case V4L2_CID_AUDIO_MUTE: | ||
329 | if (ctrl->value) { | ||
330 | az_setvol(az,0); | ||
331 | } else { | ||
332 | az_setvol(az,az->curvol); | ||
333 | } | ||
334 | return (0); | ||
335 | case V4L2_CID_AUDIO_VOLUME: | ||
336 | az_setvol(az,ctrl->value); | ||
337 | return (0); | ||
338 | } | ||
339 | return -EINVAL; | ||
313 | } | 340 | } |
314 | 341 | ||
315 | static struct az_device aztech_unit; | 342 | static struct az_device aztech_unit; |
@@ -318,20 +345,35 @@ static const struct file_operations aztech_fops = { | |||
318 | .owner = THIS_MODULE, | 345 | .owner = THIS_MODULE, |
319 | .open = video_exclusive_open, | 346 | .open = video_exclusive_open, |
320 | .release = video_exclusive_release, | 347 | .release = video_exclusive_release, |
321 | .ioctl = az_ioctl, | 348 | .ioctl = video_ioctl2, |
322 | .compat_ioctl = v4l_compat_ioctl32, | 349 | .compat_ioctl = v4l_compat_ioctl32, |
323 | .llseek = no_llseek, | 350 | .llseek = no_llseek, |
324 | }; | 351 | }; |
325 | 352 | ||
326 | static struct video_device aztech_radio= | 353 | static struct video_device aztech_radio= |
327 | { | 354 | { |
328 | .owner = THIS_MODULE, | 355 | .owner = THIS_MODULE, |
329 | .name = "Aztech radio", | 356 | .name = "Aztech radio", |
330 | .type = VID_TYPE_TUNER, | 357 | .type = VID_TYPE_TUNER, |
331 | .hardware = 0, | 358 | .hardware = 0, |
332 | .fops = &aztech_fops, | 359 | .fops = &aztech_fops, |
360 | .vidioc_querycap = vidioc_querycap, | ||
361 | .vidioc_g_tuner = vidioc_g_tuner, | ||
362 | .vidioc_s_tuner = vidioc_s_tuner, | ||
363 | .vidioc_g_audio = vidioc_g_audio, | ||
364 | .vidioc_s_audio = vidioc_s_audio, | ||
365 | .vidioc_g_input = vidioc_g_input, | ||
366 | .vidioc_s_input = vidioc_s_input, | ||
367 | .vidioc_g_frequency = vidioc_g_frequency, | ||
368 | .vidioc_s_frequency = vidioc_s_frequency, | ||
369 | .vidioc_queryctrl = vidioc_queryctrl, | ||
370 | .vidioc_g_ctrl = vidioc_g_ctrl, | ||
371 | .vidioc_s_ctrl = vidioc_s_ctrl, | ||
333 | }; | 372 | }; |
334 | 373 | ||
374 | module_param_named(debug,aztech_radio.debug, int, 0644); | ||
375 | MODULE_PARM_DESC(debug,"activates debug info"); | ||
376 | |||
335 | static int __init aztech_init(void) | 377 | static int __init aztech_init(void) |
336 | { | 378 | { |
337 | if(io==-1) | 379 | if(io==-1) |
diff --git a/drivers/media/radio/radio-gemtek-pci.c b/drivers/media/radio/radio-gemtek-pci.c index 05e5aa77025f..74976cba869f 100644 --- a/drivers/media/radio/radio-gemtek-pci.c +++ b/drivers/media/radio/radio-gemtek-pci.c | |||
@@ -89,14 +89,6 @@ static struct v4l2_queryctrl radio_qctrl[] = { | |||
89 | #define GEMTEK_PCI_RANGE_HIGH (108*16000) | 89 | #define GEMTEK_PCI_RANGE_HIGH (108*16000) |
90 | #endif | 90 | #endif |
91 | 91 | ||
92 | #ifndef TRUE | ||
93 | #define TRUE (1) | ||
94 | #endif | ||
95 | |||
96 | #ifndef FALSE | ||
97 | #define FALSE (0) | ||
98 | #endif | ||
99 | |||
100 | struct gemtek_pci_card { | 92 | struct gemtek_pci_card { |
101 | struct video_device *videodev; | 93 | struct video_device *videodev; |
102 | 94 | ||
@@ -146,12 +138,12 @@ static void __gemtek_pci_cmd( u16 value, u32 port, u8 *last_byte, int keep ) | |||
146 | 138 | ||
147 | static inline void gemtek_pci_nil( u32 port, u8 *last_byte ) | 139 | static inline void gemtek_pci_nil( u32 port, u8 *last_byte ) |
148 | { | 140 | { |
149 | __gemtek_pci_cmd( 0x00, port, last_byte, FALSE ); | 141 | __gemtek_pci_cmd( 0x00, port, last_byte, false ); |
150 | } | 142 | } |
151 | 143 | ||
152 | static inline void gemtek_pci_cmd( u16 cmd, u32 port, u8 *last_byte ) | 144 | static inline void gemtek_pci_cmd( u16 cmd, u32 port, u8 *last_byte ) |
153 | { | 145 | { |
154 | __gemtek_pci_cmd( cmd, port, last_byte, TRUE ); | 146 | __gemtek_pci_cmd( cmd, port, last_byte, true ); |
155 | } | 147 | } |
156 | 148 | ||
157 | static void gemtek_pci_setfrequency( struct gemtek_pci_card *card, unsigned long frequency ) | 149 | static void gemtek_pci_setfrequency( struct gemtek_pci_card *card, unsigned long frequency ) |
@@ -184,14 +176,14 @@ static void gemtek_pci_setfrequency( struct gemtek_pci_card *card, unsigned long | |||
184 | static inline void gemtek_pci_mute( struct gemtek_pci_card *card ) | 176 | static inline void gemtek_pci_mute( struct gemtek_pci_card *card ) |
185 | { | 177 | { |
186 | outb( 0x1f, card->iobase ); | 178 | outb( 0x1f, card->iobase ); |
187 | card->mute = TRUE; | 179 | card->mute = true; |
188 | } | 180 | } |
189 | 181 | ||
190 | static inline void gemtek_pci_unmute( struct gemtek_pci_card *card ) | 182 | static inline void gemtek_pci_unmute( struct gemtek_pci_card *card ) |
191 | { | 183 | { |
192 | if ( card->mute ) { | 184 | if ( card->mute ) { |
193 | gemtek_pci_setfrequency( card, card->current_frequency ); | 185 | gemtek_pci_setfrequency( card, card->current_frequency ); |
194 | card->mute = FALSE; | 186 | card->mute = false; |
195 | } | 187 | } |
196 | } | 188 | } |
197 | 189 | ||
@@ -259,7 +251,7 @@ static int gemtek_pci_do_ioctl(struct inode *inode, struct file *file, | |||
259 | 251 | ||
260 | gemtek_pci_setfrequency( card, f->frequency ); | 252 | gemtek_pci_setfrequency( card, f->frequency ); |
261 | card->current_frequency = f->frequency; | 253 | card->current_frequency = f->frequency; |
262 | card->mute = FALSE; | 254 | card->mute = false; |
263 | return 0; | 255 | return 0; |
264 | } | 256 | } |
265 | case VIDIOC_QUERYCTRL: | 257 | case VIDIOC_QUERYCTRL: |
diff --git a/drivers/media/radio/radio-maxiradio.c b/drivers/media/radio/radio-maxiradio.c index 6beeb74004b1..8e184cfc1c94 100644 --- a/drivers/media/radio/radio-maxiradio.c +++ b/drivers/media/radio/radio-maxiradio.c | |||
@@ -27,7 +27,9 @@ | |||
27 | * BUGS: | 27 | * BUGS: |
28 | * - card unmutes if you change frequency | 28 | * - card unmutes if you change frequency |
29 | * | 29 | * |
30 | * Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@infradead.org> | 30 | * (c) 2006, 2007 by Mauro Carvalho Chehab <mchehab@infradead.org>: |
31 | * - Conversion to V4L2 API | ||
32 | * - Uses video_ioctl2 for parsing and to add debug support | ||
31 | */ | 33 | */ |
32 | 34 | ||
33 | 35 | ||
@@ -43,10 +45,18 @@ | |||
43 | #include <linux/videodev2.h> | 45 | #include <linux/videodev2.h> |
44 | #include <media/v4l2-common.h> | 46 | #include <media/v4l2-common.h> |
45 | 47 | ||
46 | #define DRIVER_VERSION "0.76" | 48 | #define DRIVER_VERSION "0.77" |
47 | 49 | ||
48 | #include <linux/version.h> /* for KERNEL_VERSION MACRO */ | 50 | #include <linux/version.h> /* for KERNEL_VERSION MACRO */ |
49 | #define RADIO_VERSION KERNEL_VERSION(0,7,6) | 51 | #define RADIO_VERSION KERNEL_VERSION(0,7,7) |
52 | |||
53 | static struct video_device maxiradio_radio; | ||
54 | |||
55 | #define dprintk(num, fmt, arg...) \ | ||
56 | do { \ | ||
57 | if (maxiradio_radio.debug >= num) \ | ||
58 | printk(KERN_DEBUG "%s: " fmt, \ | ||
59 | maxiradio_radio.name, ## arg); } while (0) | ||
50 | 60 | ||
51 | static struct v4l2_queryctrl radio_qctrl[] = { | 61 | static struct v4l2_queryctrl radio_qctrl[] = { |
52 | { | 62 | { |
@@ -81,30 +91,21 @@ module_param(radio_nr, int, 0); | |||
81 | #define FREQ_IF 171200 /* 10.7*16000 */ | 91 | #define FREQ_IF 171200 /* 10.7*16000 */ |
82 | #define FREQ_STEP 200 /* 12.5*16 */ | 92 | #define FREQ_STEP 200 /* 12.5*16 */ |
83 | 93 | ||
84 | #define FREQ2BITS(x) ((( (unsigned int)(x)+FREQ_IF+(FREQ_STEP<<1))\ | 94 | /* (x==fmhz*16*1000) -> bits */ |
85 | /(FREQ_STEP<<2))<<2) /* (x==fmhz*16*1000) -> bits */ | 95 | #define FREQ2BITS(x) ((( (unsigned int)(x)+FREQ_IF+(FREQ_STEP<<1)) \ |
96 | /(FREQ_STEP<<2))<<2) | ||
86 | 97 | ||
87 | #define BITS2FREQ(x) ((x) * FREQ_STEP - FREQ_IF) | 98 | #define BITS2FREQ(x) ((x) * FREQ_STEP - FREQ_IF) |
88 | 99 | ||
89 | 100 | ||
90 | static int radio_ioctl(struct inode *inode, struct file *file, | ||
91 | unsigned int cmd, unsigned long arg); | ||
92 | |||
93 | static const struct file_operations maxiradio_fops = { | 101 | static const struct file_operations maxiradio_fops = { |
94 | .owner = THIS_MODULE, | 102 | .owner = THIS_MODULE, |
95 | .open = video_exclusive_open, | 103 | .open = video_exclusive_open, |
96 | .release = video_exclusive_release, | 104 | .release = video_exclusive_release, |
97 | .ioctl = radio_ioctl, | 105 | .ioctl = video_ioctl2, |
98 | .compat_ioctl = v4l_compat_ioctl32, | 106 | .compat_ioctl = v4l_compat_ioctl32, |
99 | .llseek = no_llseek, | 107 | .llseek = no_llseek, |
100 | }; | 108 | }; |
101 | static struct video_device maxiradio_radio = | ||
102 | { | ||
103 | .owner = THIS_MODULE, | ||
104 | .name = "Maxi Radio FM2000 radio", | ||
105 | .type = VID_TYPE_TUNER, | ||
106 | .fops = &maxiradio_fops, | ||
107 | }; | ||
108 | 109 | ||
109 | static struct radio_device | 110 | static struct radio_device |
110 | { | 111 | { |
@@ -116,12 +117,14 @@ static struct radio_device | |||
116 | unsigned long freq; | 117 | unsigned long freq; |
117 | 118 | ||
118 | struct mutex lock; | 119 | struct mutex lock; |
119 | } radio_unit = {0, 0, 0, 0, }; | 120 | } radio_unit = { |
120 | 121 | .muted =1, | |
122 | .freq = FREQ_LO, | ||
123 | }; | ||
121 | 124 | ||
122 | static void outbit(unsigned long bit, __u16 io) | 125 | static void outbit(unsigned long bit, __u16 io) |
123 | { | 126 | { |
124 | if(bit != 0) | 127 | if (bit != 0) |
125 | { | 128 | { |
126 | outb( power|wren|data ,io); udelay(4); | 129 | outb( power|wren|data ,io); udelay(4); |
127 | outb( power|wren|data|clk ,io); udelay(4); | 130 | outb( power|wren|data|clk ,io); udelay(4); |
@@ -137,14 +140,20 @@ static void outbit(unsigned long bit, __u16 io) | |||
137 | 140 | ||
138 | static void turn_power(__u16 io, int p) | 141 | static void turn_power(__u16 io, int p) |
139 | { | 142 | { |
140 | if(p != 0) outb(power, io); else outb(0,io); | 143 | if (p != 0) { |
144 | dprintk(1, "Radio powered on\n"); | ||
145 | outb(power, io); | ||
146 | } else { | ||
147 | dprintk(1, "Radio powered off\n"); | ||
148 | outb(0,io); | ||
149 | } | ||
141 | } | 150 | } |
142 | 151 | ||
143 | 152 | static void set_freq(__u16 io, __u32 freq) | |
144 | static void set_freq(__u16 io, __u32 data) | ||
145 | { | 153 | { |
146 | unsigned long int si; | 154 | unsigned long int si; |
147 | int bl; | 155 | int bl; |
156 | int data = FREQ2BITS(freq); | ||
148 | 157 | ||
149 | /* TEA5757 shift register bits (see pdf) */ | 158 | /* TEA5757 shift register bits (see pdf) */ |
150 | 159 | ||
@@ -163,161 +172,225 @@ static void set_freq(__u16 io, __u32 data) | |||
163 | outbit(0,io); // 16 search level | 172 | outbit(0,io); // 16 search level |
164 | 173 | ||
165 | si = 0x8000; | 174 | si = 0x8000; |
166 | for(bl = 1; bl <= 16 ; bl++) { outbit(data & si,io); si >>=1; } | 175 | for (bl = 1; bl <= 16 ; bl++) { |
176 | outbit(data & si,io); | ||
177 | si >>=1; | ||
178 | } | ||
167 | 179 | ||
168 | outb(power,io); | 180 | dprintk(1, "Radio freq set to %d.%02d MHz\n", |
181 | freq / 16000, | ||
182 | freq % 16000 * 100 / 16000); | ||
183 | |||
184 | turn_power(io, 1); | ||
169 | } | 185 | } |
170 | 186 | ||
171 | static int get_stereo(__u16 io) | 187 | static int get_stereo(__u16 io) |
172 | { | 188 | { |
173 | outb(power,io); udelay(4); | 189 | outb(power,io); |
190 | udelay(4); | ||
191 | |||
174 | return !(inb(io) & mo_st); | 192 | return !(inb(io) & mo_st); |
175 | } | 193 | } |
176 | 194 | ||
177 | static int get_tune(__u16 io) | 195 | static int get_tune(__u16 io) |
178 | { | 196 | { |
179 | outb(power+clk,io); udelay(4); | 197 | outb(power+clk,io); |
198 | udelay(4); | ||
199 | |||
180 | return !(inb(io) & mo_st); | 200 | return !(inb(io) & mo_st); |
181 | } | 201 | } |
182 | 202 | ||
183 | 203 | ||
184 | static inline int radio_function(struct inode *inode, struct file *file, | 204 | static int vidioc_querycap (struct file *file, void *priv, |
185 | unsigned int cmd, void *arg) | 205 | struct v4l2_capability *v) |
206 | { | ||
207 | strlcpy(v->driver, "radio-maxiradio", sizeof (v->driver)); | ||
208 | strlcpy(v->card, "Maxi Radio FM2000 radio", sizeof (v->card)); | ||
209 | sprintf(v->bus_info,"ISA"); | ||
210 | v->version = RADIO_VERSION; | ||
211 | v->capabilities = V4L2_CAP_TUNER; | ||
212 | |||
213 | return 0; | ||
214 | } | ||
215 | |||
216 | static int vidioc_g_tuner (struct file *file, void *priv, | ||
217 | struct v4l2_tuner *v) | ||
186 | { | 218 | { |
187 | struct video_device *dev = video_devdata(file); | 219 | struct video_device *dev = video_devdata(file); |
188 | struct radio_device *card=dev->priv; | 220 | struct radio_device *card=dev->priv; |
189 | 221 | ||
190 | switch(cmd) { | 222 | if (v->index > 0) |
191 | case VIDIOC_QUERYCAP: | 223 | return -EINVAL; |
192 | { | ||
193 | struct v4l2_capability *v = arg; | ||
194 | memset(v,0,sizeof(*v)); | ||
195 | strlcpy(v->driver, "radio-maxiradio", sizeof (v->driver)); | ||
196 | strlcpy(v->card, "Maxi Radio FM2000 radio", sizeof (v->card)); | ||
197 | sprintf(v->bus_info,"ISA"); | ||
198 | v->version = RADIO_VERSION; | ||
199 | v->capabilities = V4L2_CAP_TUNER; | ||
200 | 224 | ||
201 | return 0; | 225 | memset(v,0,sizeof(*v)); |
202 | } | 226 | strcpy(v->name, "FM"); |
203 | case VIDIOC_G_TUNER: | 227 | v->type = V4L2_TUNER_RADIO; |
204 | { | ||
205 | struct v4l2_tuner *v = arg; | ||
206 | 228 | ||
207 | if (v->index > 0) | 229 | v->rangelow=FREQ_LO; |
208 | return -EINVAL; | 230 | v->rangehigh=FREQ_HI; |
231 | v->rxsubchans =V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO; | ||
232 | v->capability=V4L2_TUNER_CAP_LOW; | ||
233 | if(get_stereo(card->io)) | ||
234 | v->audmode = V4L2_TUNER_MODE_STEREO; | ||
235 | else | ||
236 | v->audmode = V4L2_TUNER_MODE_MONO; | ||
237 | v->signal=0xffff*get_tune(card->io); | ||
209 | 238 | ||
210 | memset(v,0,sizeof(*v)); | 239 | return 0; |
211 | strcpy(v->name, "FM"); | 240 | } |
212 | v->type = V4L2_TUNER_RADIO; | ||
213 | 241 | ||
214 | v->rangelow=FREQ_LO; | 242 | static int vidioc_s_tuner (struct file *file, void *priv, |
215 | v->rangehigh=FREQ_HI; | 243 | struct v4l2_tuner *v) |
216 | v->rxsubchans =V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO; | 244 | { |
217 | v->capability=V4L2_TUNER_CAP_LOW; | 245 | if (v->index > 0) |
218 | if(get_stereo(card->io)) | 246 | return -EINVAL; |
219 | v->audmode = V4L2_TUNER_MODE_STEREO; | ||
220 | else | ||
221 | v->audmode = V4L2_TUNER_MODE_MONO; | ||
222 | v->signal=0xffff*get_tune(card->io); | ||
223 | 247 | ||
224 | return 0; | 248 | return 0; |
225 | } | 249 | } |
226 | case VIDIOC_S_TUNER: | ||
227 | { | ||
228 | struct v4l2_tuner *v = arg; | ||
229 | 250 | ||
230 | if (v->index > 0) | 251 | static int vidioc_g_audio (struct file *file, void *priv, |
231 | return -EINVAL; | 252 | struct v4l2_audio *a) |
253 | { | ||
254 | if (a->index > 1) | ||
255 | return -EINVAL; | ||
232 | 256 | ||
233 | return 0; | 257 | strcpy(a->name, "FM"); |
234 | } | 258 | a->capability = V4L2_AUDCAP_STEREO; |
235 | case VIDIOC_S_FREQUENCY: | 259 | return 0; |
236 | { | 260 | } |
237 | struct v4l2_frequency *f = arg; | ||
238 | 261 | ||
239 | if (f->frequency < FREQ_LO || f->frequency > FREQ_HI) | 262 | static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) |
240 | return -EINVAL; | 263 | { |
264 | *i = 0; | ||
241 | 265 | ||
242 | card->freq = f->frequency; | 266 | return 0; |
243 | set_freq(card->io, FREQ2BITS(card->freq)); | 267 | } |
244 | msleep(125); | ||
245 | return 0; | ||
246 | } | ||
247 | case VIDIOC_G_FREQUENCY: | ||
248 | { | ||
249 | struct v4l2_frequency *f = arg; | ||
250 | 268 | ||
251 | f->type = V4L2_TUNER_RADIO; | 269 | static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) |
252 | f->frequency = card->freq; | 270 | { |
271 | if (i != 0) | ||
272 | return -EINVAL; | ||
253 | 273 | ||
254 | return 0; | 274 | return 0; |
255 | } | 275 | } |
256 | case VIDIOC_QUERYCTRL: | 276 | |
257 | { | 277 | |
258 | struct v4l2_queryctrl *qc = arg; | 278 | static int vidioc_s_audio (struct file *file, void *priv, |
259 | int i; | 279 | struct v4l2_audio *a) |
260 | 280 | { | |
261 | for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { | 281 | if (a->index != 0) |
262 | if (qc->id && qc->id == radio_qctrl[i].id) { | 282 | return -EINVAL; |
263 | memcpy(qc, &(radio_qctrl[i]), | 283 | |
264 | sizeof(*qc)); | 284 | return 0; |
265 | return (0); | 285 | } |
266 | } | 286 | |
267 | } | 287 | static int vidioc_s_frequency (struct file *file, void *priv, |
268 | return -EINVAL; | 288 | struct v4l2_frequency *f) |
269 | } | 289 | { |
270 | case VIDIOC_G_CTRL: | 290 | struct video_device *dev = video_devdata(file); |
271 | { | 291 | struct radio_device *card=dev->priv; |
272 | struct v4l2_control *ctrl= arg; | ||
273 | |||
274 | switch (ctrl->id) { | ||
275 | case V4L2_CID_AUDIO_MUTE: | ||
276 | ctrl->value=card->muted; | ||
277 | return (0); | ||
278 | } | ||
279 | return -EINVAL; | ||
280 | } | ||
281 | case VIDIOC_S_CTRL: | ||
282 | { | ||
283 | struct v4l2_control *ctrl= arg; | ||
284 | |||
285 | switch (ctrl->id) { | ||
286 | case V4L2_CID_AUDIO_MUTE: | ||
287 | card->muted = ctrl->value; | ||
288 | if(card->muted) | ||
289 | turn_power(card->io, 0); | ||
290 | else | ||
291 | set_freq(card->io, FREQ2BITS(card->freq)); | ||
292 | return 0; | ||
293 | } | ||
294 | return -EINVAL; | ||
295 | } | ||
296 | 292 | ||
297 | default: | 293 | if (f->frequency < FREQ_LO || f->frequency > FREQ_HI) { |
298 | return v4l_compat_translate_ioctl(inode,file,cmd,arg, | 294 | dprintk(1, "radio freq (%d.%02d MHz) out of range (%d-%d)\n", |
299 | radio_function); | 295 | f->frequency / 16000, |
296 | f->frequency % 16000 * 100 / 16000, | ||
297 | FREQ_LO / 16000, FREQ_HI / 16000); | ||
300 | 298 | ||
299 | return -EINVAL; | ||
301 | } | 300 | } |
301 | |||
302 | card->freq = f->frequency; | ||
303 | set_freq(card->io, card->freq); | ||
304 | msleep(125); | ||
305 | |||
306 | return 0; | ||
302 | } | 307 | } |
303 | 308 | ||
304 | static int radio_ioctl(struct inode *inode, struct file *file, | 309 | static int vidioc_g_frequency (struct file *file, void *priv, |
305 | unsigned int cmd, unsigned long arg) | 310 | struct v4l2_frequency *f) |
306 | { | 311 | { |
307 | struct video_device *dev = video_devdata(file); | 312 | struct video_device *dev = video_devdata(file); |
308 | struct radio_device *card=dev->priv; | 313 | struct radio_device *card=dev->priv; |
309 | int ret; | ||
310 | 314 | ||
311 | mutex_lock(&card->lock); | 315 | f->type = V4L2_TUNER_RADIO; |
312 | ret = video_usercopy(inode, file, cmd, arg, radio_function); | 316 | f->frequency = card->freq; |
313 | mutex_unlock(&card->lock); | 317 | |
314 | return ret; | 318 | dprintk(4, "radio freq is %d.%02d MHz", |
319 | f->frequency / 16000, | ||
320 | f->frequency % 16000 * 100 / 16000); | ||
321 | |||
322 | return 0; | ||
315 | } | 323 | } |
316 | 324 | ||
317 | MODULE_AUTHOR("Dimitromanolakis Apostolos, apdim@grecian.net"); | 325 | static int vidioc_queryctrl (struct file *file, void *priv, |
318 | MODULE_DESCRIPTION("Radio driver for the Guillemot Maxi Radio FM2000 radio."); | 326 | struct v4l2_queryctrl *qc) |
319 | MODULE_LICENSE("GPL"); | 327 | { |
328 | int i; | ||
320 | 329 | ||
330 | for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { | ||
331 | if (qc->id && qc->id == radio_qctrl[i].id) { | ||
332 | memcpy(qc, &(radio_qctrl[i]), sizeof(*qc)); | ||
333 | return (0); | ||
334 | } | ||
335 | } | ||
336 | |||
337 | return -EINVAL; | ||
338 | } | ||
339 | |||
340 | static int vidioc_g_ctrl (struct file *file, void *priv, | ||
341 | struct v4l2_control *ctrl) | ||
342 | { | ||
343 | struct video_device *dev = video_devdata(file); | ||
344 | struct radio_device *card=dev->priv; | ||
345 | |||
346 | switch (ctrl->id) { | ||
347 | case V4L2_CID_AUDIO_MUTE: | ||
348 | ctrl->value=card->muted; | ||
349 | return (0); | ||
350 | } | ||
351 | |||
352 | return -EINVAL; | ||
353 | } | ||
354 | |||
355 | static int vidioc_s_ctrl (struct file *file, void *priv, | ||
356 | struct v4l2_control *ctrl) | ||
357 | { | ||
358 | struct video_device *dev = video_devdata(file); | ||
359 | struct radio_device *card=dev->priv; | ||
360 | |||
361 | switch (ctrl->id) { | ||
362 | case V4L2_CID_AUDIO_MUTE: | ||
363 | card->muted = ctrl->value; | ||
364 | if(card->muted) | ||
365 | turn_power(card->io, 0); | ||
366 | else | ||
367 | set_freq(card->io, card->freq); | ||
368 | return 0; | ||
369 | } | ||
370 | |||
371 | return -EINVAL; | ||
372 | } | ||
373 | |||
374 | static struct video_device maxiradio_radio = | ||
375 | { | ||
376 | .owner = THIS_MODULE, | ||
377 | .name = "Maxi Radio FM2000 radio", | ||
378 | .type = VID_TYPE_TUNER, | ||
379 | .fops = &maxiradio_fops, | ||
380 | |||
381 | .vidioc_querycap = vidioc_querycap, | ||
382 | .vidioc_g_tuner = vidioc_g_tuner, | ||
383 | .vidioc_s_tuner = vidioc_s_tuner, | ||
384 | .vidioc_g_audio = vidioc_g_audio, | ||
385 | .vidioc_s_audio = vidioc_s_audio, | ||
386 | .vidioc_g_input = vidioc_g_input, | ||
387 | .vidioc_s_input = vidioc_s_input, | ||
388 | .vidioc_g_frequency = vidioc_g_frequency, | ||
389 | .vidioc_s_frequency = vidioc_s_frequency, | ||
390 | .vidioc_queryctrl = vidioc_queryctrl, | ||
391 | .vidioc_g_ctrl = vidioc_g_ctrl, | ||
392 | .vidioc_s_ctrl = vidioc_s_ctrl, | ||
393 | }; | ||
321 | 394 | ||
322 | static int __devinit maxiradio_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | 395 | static int __devinit maxiradio_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) |
323 | { | 396 | { |
@@ -334,7 +407,7 @@ static int __devinit maxiradio_init_one(struct pci_dev *pdev, const struct pci_d | |||
334 | mutex_init(&radio_unit.lock); | 407 | mutex_init(&radio_unit.lock); |
335 | maxiradio_radio.priv = &radio_unit; | 408 | maxiradio_radio.priv = &radio_unit; |
336 | 409 | ||
337 | if(video_register_device(&maxiradio_radio, VFL_TYPE_RADIO, radio_nr)==-1) { | 410 | if (video_register_device(&maxiradio_radio, VFL_TYPE_RADIO, radio_nr)==-1) { |
338 | printk("radio-maxiradio: can't register device!"); | 411 | printk("radio-maxiradio: can't register device!"); |
339 | goto err_out_free_region; | 412 | goto err_out_free_region; |
340 | } | 413 | } |
@@ -389,3 +462,10 @@ static void __exit maxiradio_radio_exit(void) | |||
389 | 462 | ||
390 | module_init(maxiradio_radio_init); | 463 | module_init(maxiradio_radio_init); |
391 | module_exit(maxiradio_radio_exit); | 464 | module_exit(maxiradio_radio_exit); |
465 | |||
466 | MODULE_AUTHOR("Dimitromanolakis Apostolos, apdim@grecian.net"); | ||
467 | MODULE_DESCRIPTION("Radio driver for the Guillemot Maxi Radio FM2000 radio."); | ||
468 | MODULE_LICENSE("GPL"); | ||
469 | |||
470 | module_param_named(debug,maxiradio_radio.debug, int, 0644); | ||
471 | MODULE_PARM_DESC(debug,"activates debug info"); | ||
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 57357db31b8a..7a6105153f23 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig | |||
@@ -342,7 +342,7 @@ endmenu # encoder / decoder chips | |||
342 | 342 | ||
343 | config VIDEO_VIVI | 343 | config VIDEO_VIVI |
344 | tristate "Virtual Video Driver" | 344 | tristate "Virtual Video Driver" |
345 | depends on VIDEO_V4L2 && !SPARC32 && !SPARC64 | 345 | depends on VIDEO_V4L2 && !SPARC32 && !SPARC64 && PCI |
346 | select VIDEO_BUF | 346 | select VIDEO_BUF |
347 | default n | 347 | default n |
348 | ---help--- | 348 | ---help--- |
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index 9b1f3f06bb7c..44ccaed40b49 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile | |||
@@ -113,4 +113,3 @@ obj-$(CONFIG_USB_QUICKCAM_MESSENGER) += usbvideo/ | |||
113 | obj-$(CONFIG_VIDEO_VIVI) += vivi.o | 113 | obj-$(CONFIG_VIDEO_VIVI) += vivi.o |
114 | 114 | ||
115 | EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core | 115 | EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core |
116 | extra-cflags-$(CONFIG_VIDEO_V4L1_COMPAT) += -DCONFIG_VIDEO_V4L1_COMPAT | ||
diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c index 21ebe8f13815..6addc42df045 100644 --- a/drivers/media/video/bt8xx/bttv-cards.c +++ b/drivers/media/video/bt8xx/bttv-cards.c | |||
@@ -307,6 +307,7 @@ static struct CARD { | |||
307 | { 0x07711461, BTTV_BOARD_AVDVBT_771, "AVermedia AverTV DVB-T 771" }, | 307 | { 0x07711461, BTTV_BOARD_AVDVBT_771, "AVermedia AverTV DVB-T 771" }, |
308 | { 0x07611461, BTTV_BOARD_AVDVBT_761, "AverMedia AverTV DVB-T 761" }, | 308 | { 0x07611461, BTTV_BOARD_AVDVBT_761, "AverMedia AverTV DVB-T 761" }, |
309 | { 0xdb1018ac, BTTV_BOARD_DVICO_DVBT_LITE, "DViCO FusionHDTV DVB-T Lite" }, | 309 | { 0xdb1018ac, BTTV_BOARD_DVICO_DVBT_LITE, "DViCO FusionHDTV DVB-T Lite" }, |
310 | { 0xdb1118ac, BTTV_BOARD_DVICO_DVBT_LITE, "Ultraview DVB-T Lite" }, | ||
310 | { 0xd50018ac, BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE, "DViCO FusionHDTV 5 Lite" }, | 311 | { 0xd50018ac, BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE, "DViCO FusionHDTV 5 Lite" }, |
311 | { 0x00261822, BTTV_BOARD_TWINHAN_DST, "DNTV Live! Mini "}, | 312 | { 0x00261822, BTTV_BOARD_TWINHAN_DST, "DNTV Live! Mini "}, |
312 | 313 | ||
@@ -578,14 +579,9 @@ struct tvcard bttv_tvcards[] = { | |||
578 | .svhs = 2, | 579 | .svhs = 2, |
579 | .gpiomask = 0x01fe00, | 580 | .gpiomask = 0x01fe00, |
580 | .muxsel = { 2, 3, 1, 1 }, | 581 | .muxsel = { 2, 3, 1, 1 }, |
581 | #if 0 | ||
582 | /* old */ | ||
583 | .gpiomux = { 0x01c000, 0, 0x018000, 0x014000, 0x002000 }, | ||
584 | #else | ||
585 | /* 2003-10-20 by "Anton A. Arapov" <arapov@mail.ru> */ | 582 | /* 2003-10-20 by "Anton A. Arapov" <arapov@mail.ru> */ |
586 | .gpiomux = { 0x001e00, 0, 0x018000, 0x014000 }, | 583 | .gpiomux = { 0x001e00, 0, 0x018000, 0x014000 }, |
587 | .gpiomute = 0x002000, | 584 | .gpiomute = 0x002000, |
588 | #endif | ||
589 | .needs_tvaudio = 1, | 585 | .needs_tvaudio = 1, |
590 | .pll = PLL_28, | 586 | .pll = PLL_28, |
591 | .tuner_type = -1, | 587 | .tuner_type = -1, |
@@ -894,15 +890,10 @@ struct tvcard bttv_tvcards[] = { | |||
894 | .tuner = 0, | 890 | .tuner = 0, |
895 | .svhs = 2, | 891 | .svhs = 2, |
896 | .muxsel = { 2, 3, 1, 1, 0 }, /* TV, CVid, SVid, CVid over SVid connector */ | 892 | .muxsel = { 2, 3, 1, 1, 0 }, /* TV, CVid, SVid, CVid over SVid connector */ |
897 | #if 0 | ||
898 | .gpiomask = 0xc33000, | ||
899 | .gpiomux = { 0x422000,0x1000,0x0000,0x620000,0x800000 }, | ||
900 | #else | ||
901 | /* Alexander Varakin <avarakin@hotmail.com> [stereo version] */ | 893 | /* Alexander Varakin <avarakin@hotmail.com> [stereo version] */ |
902 | .gpiomask = 0xb33000, | 894 | .gpiomask = 0xb33000, |
903 | .gpiomux = { 0x122000,0x1000,0x0000,0x620000 }, | 895 | .gpiomux = { 0x122000,0x1000,0x0000,0x620000 }, |
904 | .gpiomute = 0x800000, | 896 | .gpiomute = 0x800000, |
905 | #endif | ||
906 | /* Audio Routing for "WinFast 2000 XP" (no tv stereo !) | 897 | /* Audio Routing for "WinFast 2000 XP" (no tv stereo !) |
907 | gpio23 -- hef4052:nEnable (0x800000) | 898 | gpio23 -- hef4052:nEnable (0x800000) |
908 | gpio12 -- hef4052:A1 | 899 | gpio12 -- hef4052:A1 |
@@ -1937,11 +1928,6 @@ struct tvcard bttv_tvcards[] = { | |||
1937 | .video_inputs = 4, | 1928 | .video_inputs = 4, |
1938 | .audio_inputs = 1, | 1929 | .audio_inputs = 1, |
1939 | .tuner = -1, | 1930 | .tuner = -1, |
1940 | #if 0 /* TODO ... */ | ||
1941 | .svhs = OSPREY540_SVID_ANALOG, | ||
1942 | .muxsel = { [OSPREY540_COMP_ANALOG] = 2, | ||
1943 | [OSPREY540_SVID_ANALOG] = 3, }, | ||
1944 | #endif | ||
1945 | .pll = PLL_28, | 1931 | .pll = PLL_28, |
1946 | .tuner_type = -1, | 1932 | .tuner_type = -1, |
1947 | .tuner_addr = ADDR_UNSET, | 1933 | .tuner_addr = ADDR_UNSET, |
@@ -1949,10 +1935,6 @@ struct tvcard bttv_tvcards[] = { | |||
1949 | .no_msp34xx = 1, | 1935 | .no_msp34xx = 1, |
1950 | .no_tda9875 = 1, | 1936 | .no_tda9875 = 1, |
1951 | .no_tda7432 = 1, | 1937 | .no_tda7432 = 1, |
1952 | #if 0 /* TODO ... */ | ||
1953 | .muxsel_hook = osprey_540_muxsel, | ||
1954 | .picture_hook = osprey_540_set_picture, | ||
1955 | #endif | ||
1956 | }, | 1938 | }, |
1957 | 1939 | ||
1958 | /* ---- card 0x5C ---------------------------------- */ | 1940 | /* ---- card 0x5C ---------------------------------- */ |
@@ -2627,9 +2609,6 @@ struct tvcard bttv_tvcards[] = { | |||
2627 | .tuner_addr = ADDR_UNSET, | 2609 | .tuner_addr = ADDR_UNSET, |
2628 | .radio_addr = ADDR_UNSET, | 2610 | .radio_addr = ADDR_UNSET, |
2629 | .has_radio = 0, | 2611 | .has_radio = 0, |
2630 | #if 0 | ||
2631 | .has_remote = 1, | ||
2632 | #endif | ||
2633 | }, | 2612 | }, |
2634 | [BTTV_BOARD_SUPER_TV] = { | 2613 | [BTTV_BOARD_SUPER_TV] = { |
2635 | /* Rick C <cryptdragoon@gmail.com> */ | 2614 | /* Rick C <cryptdragoon@gmail.com> */ |
diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index 41fd09d7d11e..5720b77ac9a7 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c | |||
@@ -9,6 +9,10 @@ | |||
9 | some v4l2 code lines are taken from Justin's bttv2 driver which is | 9 | some v4l2 code lines are taken from Justin's bttv2 driver which is |
10 | (c) 2000 Justin Schoeman <justin@suntiger.ee.up.ac.za> | 10 | (c) 2000 Justin Schoeman <justin@suntiger.ee.up.ac.za> |
11 | 11 | ||
12 | Cropping and overscan support | ||
13 | Copyright (C) 2005, 2006 Michael H. Schimek <mschimek@gmx.at> | ||
14 | Sponsored by OPQ Systems AB | ||
15 | |||
12 | This program is free software; you can redistribute it and/or modify | 16 | This program is free software; you can redistribute it and/or modify |
13 | it under the terms of the GNU General Public License as published by | 17 | it under the terms of the GNU General Public License as published by |
14 | the Free Software Foundation; either version 2 of the License, or | 18 | the Free Software Foundation; either version 2 of the License, or |
@@ -64,6 +68,7 @@ static unsigned int radio[BTTV_MAX]; | |||
64 | static unsigned int irq_debug; | 68 | static unsigned int irq_debug; |
65 | static unsigned int gbuffers = 8; | 69 | static unsigned int gbuffers = 8; |
66 | static unsigned int gbufsize = 0x208000; | 70 | static unsigned int gbufsize = 0x208000; |
71 | static unsigned int reset_crop = 1; | ||
67 | 72 | ||
68 | static int video_nr = -1; | 73 | static int video_nr = -1; |
69 | static int radio_nr = -1; | 74 | static int radio_nr = -1; |
@@ -103,6 +108,7 @@ module_param(radio_nr, int, 0444); | |||
103 | module_param(vbi_nr, int, 0444); | 108 | module_param(vbi_nr, int, 0444); |
104 | module_param(gbuffers, int, 0444); | 109 | module_param(gbuffers, int, 0444); |
105 | module_param(gbufsize, int, 0444); | 110 | module_param(gbufsize, int, 0444); |
111 | module_param(reset_crop, int, 0444); | ||
106 | 112 | ||
107 | module_param(v4l2, int, 0644); | 113 | module_param(v4l2, int, 0644); |
108 | module_param(bigendian, int, 0644); | 114 | module_param(bigendian, int, 0644); |
@@ -129,6 +135,8 @@ MODULE_PARM_DESC(bttv_debug,"debug messages, default is 0 (no)"); | |||
129 | MODULE_PARM_DESC(irq_debug,"irq handler debug messages, default is 0 (no)"); | 135 | MODULE_PARM_DESC(irq_debug,"irq handler debug messages, default is 0 (no)"); |
130 | MODULE_PARM_DESC(gbuffers,"number of capture buffers. range 2-32, default 8"); | 136 | MODULE_PARM_DESC(gbuffers,"number of capture buffers. range 2-32, default 8"); |
131 | MODULE_PARM_DESC(gbufsize,"size of the capture buffers, default is 0x208000"); | 137 | MODULE_PARM_DESC(gbufsize,"size of the capture buffers, default is 0x208000"); |
138 | MODULE_PARM_DESC(reset_crop,"reset cropping parameters at open(), default " | ||
139 | "is 1 (yes) for compatibility with older applications"); | ||
132 | MODULE_PARM_DESC(automute,"mute audio on bad/missing video signal, default is 1 (yes)"); | 140 | MODULE_PARM_DESC(automute,"mute audio on bad/missing video signal, default is 1 (yes)"); |
133 | MODULE_PARM_DESC(chroma_agc,"enables the AGC of chroma signal, default is 0 (no)"); | 141 | MODULE_PARM_DESC(chroma_agc,"enables the AGC of chroma signal, default is 0 (no)"); |
134 | MODULE_PARM_DESC(adc_crush,"enables the luminance ADC crush, default is 1 (yes)"); | 142 | MODULE_PARM_DESC(adc_crush,"enables the luminance ADC crush, default is 1 (yes)"); |
@@ -192,6 +200,33 @@ static u8 SRAM_Table[][60] = | |||
192 | } | 200 | } |
193 | }; | 201 | }; |
194 | 202 | ||
203 | /* minhdelayx1 first video pixel we can capture on a line and | ||
204 | hdelayx1 start of active video, both relative to rising edge of | ||
205 | /HRESET pulse (0H) in 1 / fCLKx1. | ||
206 | swidth width of active video and | ||
207 | totalwidth total line width, both in 1 / fCLKx1. | ||
208 | sqwidth total line width in square pixels. | ||
209 | vdelay start of active video in 2 * field lines relative to | ||
210 | trailing edge of /VRESET pulse (VDELAY register). | ||
211 | sheight height of active video in 2 * field lines. | ||
212 | videostart0 ITU-R frame line number of the line corresponding | ||
213 | to vdelay in the first field. */ | ||
214 | #define CROPCAP(minhdelayx1, hdelayx1, swidth, totalwidth, sqwidth, \ | ||
215 | vdelay, sheight, videostart0) \ | ||
216 | .cropcap.bounds.left = minhdelayx1, \ | ||
217 | /* * 2 because vertically we count field lines times two, */ \ | ||
218 | /* e.g. 23 * 2 to 23 * 2 + 576 in PAL-BGHI defrect. */ \ | ||
219 | .cropcap.bounds.top = (videostart0) * 2 - (vdelay) + MIN_VDELAY, \ | ||
220 | /* 4 is a safety margin at the end of the line. */ \ | ||
221 | .cropcap.bounds.width = (totalwidth) - (minhdelayx1) - 4, \ | ||
222 | .cropcap.bounds.height = (sheight) + (vdelay) - MIN_VDELAY, \ | ||
223 | .cropcap.defrect.left = hdelayx1, \ | ||
224 | .cropcap.defrect.top = (videostart0) * 2, \ | ||
225 | .cropcap.defrect.width = swidth, \ | ||
226 | .cropcap.defrect.height = sheight, \ | ||
227 | .cropcap.pixelaspect.numerator = totalwidth, \ | ||
228 | .cropcap.pixelaspect.denominator = sqwidth, | ||
229 | |||
195 | const struct bttv_tvnorm bttv_tvnorms[] = { | 230 | const struct bttv_tvnorm bttv_tvnorms[] = { |
196 | /* PAL-BDGHI */ | 231 | /* PAL-BDGHI */ |
197 | /* max. active video is actually 922, but 924 is divisible by 4 and 3! */ | 232 | /* max. active video is actually 922, but 924 is divisible by 4 and 3! */ |
@@ -210,11 +245,26 @@ const struct bttv_tvnorm bttv_tvnorms[] = { | |||
210 | .hdelayx1 = 186, | 245 | .hdelayx1 = 186, |
211 | .hactivex1 = 924, | 246 | .hactivex1 = 924, |
212 | .vdelay = 0x20, | 247 | .vdelay = 0x20, |
213 | .vbipack = 255, | 248 | .vbipack = 255, /* min (2048 / 4, 0x1ff) & 0xff */ |
214 | .sram = 0, | 249 | .sram = 0, |
215 | /* ITU-R frame line number of the first VBI line | 250 | /* ITU-R frame line number of the first VBI line |
216 | we can capture, of the first and second field. */ | 251 | we can capture, of the first and second field. |
217 | .vbistart = { 7,320 }, | 252 | The last line is determined by cropcap.bounds. */ |
253 | .vbistart = { 7, 320 }, | ||
254 | CROPCAP(/* minhdelayx1 */ 68, | ||
255 | /* hdelayx1 */ 186, | ||
256 | /* Should be (768 * 1135 + 944 / 2) / 944. | ||
257 | cropcap.defrect is used for image width | ||
258 | checks, so we keep the old value 924. */ | ||
259 | /* swidth */ 924, | ||
260 | /* totalwidth */ 1135, | ||
261 | /* sqwidth */ 944, | ||
262 | /* vdelay */ 0x20, | ||
263 | /* sheight */ 576, | ||
264 | /* videostart0 */ 23) | ||
265 | /* bt878 (and bt848?) can capture another | ||
266 | line below active video. */ | ||
267 | .cropcap.bounds.height = (576 + 2) + 0x20 - 2, | ||
218 | },{ | 268 | },{ |
219 | .v4l2_id = V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_KR, | 269 | .v4l2_id = V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_KR, |
220 | .name = "NTSC", | 270 | .name = "NTSC", |
@@ -229,9 +279,18 @@ const struct bttv_tvnorm bttv_tvnorms[] = { | |||
229 | .hdelayx1 = 128, | 279 | .hdelayx1 = 128, |
230 | .hactivex1 = 910, | 280 | .hactivex1 = 910, |
231 | .vdelay = 0x1a, | 281 | .vdelay = 0x1a, |
232 | .vbipack = 144, | 282 | .vbipack = 144, /* min (1600 / 4, 0x1ff) & 0xff */ |
233 | .sram = 1, | 283 | .sram = 1, |
234 | .vbistart = { 10, 273 }, | 284 | .vbistart = { 10, 273 }, |
285 | CROPCAP(/* minhdelayx1 */ 68, | ||
286 | /* hdelayx1 */ 128, | ||
287 | /* Should be (640 * 910 + 780 / 2) / 780? */ | ||
288 | /* swidth */ 768, | ||
289 | /* totalwidth */ 910, | ||
290 | /* sqwidth */ 780, | ||
291 | /* vdelay */ 0x1a, | ||
292 | /* sheight */ 480, | ||
293 | /* videostart0 */ 23) | ||
235 | },{ | 294 | },{ |
236 | .v4l2_id = V4L2_STD_SECAM, | 295 | .v4l2_id = V4L2_STD_SECAM, |
237 | .name = "SECAM", | 296 | .name = "SECAM", |
@@ -249,6 +308,14 @@ const struct bttv_tvnorm bttv_tvnorms[] = { | |||
249 | .vbipack = 255, | 308 | .vbipack = 255, |
250 | .sram = 0, /* like PAL, correct? */ | 309 | .sram = 0, /* like PAL, correct? */ |
251 | .vbistart = { 7, 320 }, | 310 | .vbistart = { 7, 320 }, |
311 | CROPCAP(/* minhdelayx1 */ 68, | ||
312 | /* hdelayx1 */ 186, | ||
313 | /* swidth */ 924, | ||
314 | /* totalwidth */ 1135, | ||
315 | /* sqwidth */ 944, | ||
316 | /* vdelay */ 0x20, | ||
317 | /* sheight */ 576, | ||
318 | /* videostart0 */ 23) | ||
252 | },{ | 319 | },{ |
253 | .v4l2_id = V4L2_STD_PAL_Nc, | 320 | .v4l2_id = V4L2_STD_PAL_Nc, |
254 | .name = "PAL-Nc", | 321 | .name = "PAL-Nc", |
@@ -266,6 +333,14 @@ const struct bttv_tvnorm bttv_tvnorms[] = { | |||
266 | .vbipack = 144, | 333 | .vbipack = 144, |
267 | .sram = -1, | 334 | .sram = -1, |
268 | .vbistart = { 7, 320 }, | 335 | .vbistart = { 7, 320 }, |
336 | CROPCAP(/* minhdelayx1 */ 68, | ||
337 | /* hdelayx1 */ 130, | ||
338 | /* swidth */ (640 * 910 + 780 / 2) / 780, | ||
339 | /* totalwidth */ 910, | ||
340 | /* sqwidth */ 780, | ||
341 | /* vdelay */ 0x1a, | ||
342 | /* sheight */ 576, | ||
343 | /* videostart0 */ 23) | ||
269 | },{ | 344 | },{ |
270 | .v4l2_id = V4L2_STD_PAL_M, | 345 | .v4l2_id = V4L2_STD_PAL_M, |
271 | .name = "PAL-M", | 346 | .name = "PAL-M", |
@@ -283,6 +358,14 @@ const struct bttv_tvnorm bttv_tvnorms[] = { | |||
283 | .vbipack = 144, | 358 | .vbipack = 144, |
284 | .sram = -1, | 359 | .sram = -1, |
285 | .vbistart = { 10, 273 }, | 360 | .vbistart = { 10, 273 }, |
361 | CROPCAP(/* minhdelayx1 */ 68, | ||
362 | /* hdelayx1 */ 135, | ||
363 | /* swidth */ (640 * 910 + 780 / 2) / 780, | ||
364 | /* totalwidth */ 910, | ||
365 | /* sqwidth */ 780, | ||
366 | /* vdelay */ 0x1a, | ||
367 | /* sheight */ 480, | ||
368 | /* videostart0 */ 23) | ||
286 | },{ | 369 | },{ |
287 | .v4l2_id = V4L2_STD_PAL_N, | 370 | .v4l2_id = V4L2_STD_PAL_N, |
288 | .name = "PAL-N", | 371 | .name = "PAL-N", |
@@ -299,7 +382,15 @@ const struct bttv_tvnorm bttv_tvnorms[] = { | |||
299 | .vdelay = 0x20, | 382 | .vdelay = 0x20, |
300 | .vbipack = 144, | 383 | .vbipack = 144, |
301 | .sram = -1, | 384 | .sram = -1, |
302 | .vbistart = { 7, 320}, | 385 | .vbistart = { 7, 320 }, |
386 | CROPCAP(/* minhdelayx1 */ 68, | ||
387 | /* hdelayx1 */ 186, | ||
388 | /* swidth */ (768 * 1135 + 944 / 2) / 944, | ||
389 | /* totalwidth */ 1135, | ||
390 | /* sqwidth */ 944, | ||
391 | /* vdelay */ 0x20, | ||
392 | /* sheight */ 576, | ||
393 | /* videostart0 */ 23) | ||
303 | },{ | 394 | },{ |
304 | .v4l2_id = V4L2_STD_NTSC_M_JP, | 395 | .v4l2_id = V4L2_STD_NTSC_M_JP, |
305 | .name = "NTSC-JP", | 396 | .name = "NTSC-JP", |
@@ -316,7 +407,15 @@ const struct bttv_tvnorm bttv_tvnorms[] = { | |||
316 | .vdelay = 0x16, | 407 | .vdelay = 0x16, |
317 | .vbipack = 144, | 408 | .vbipack = 144, |
318 | .sram = -1, | 409 | .sram = -1, |
319 | .vbistart = {10, 273}, | 410 | .vbistart = { 10, 273 }, |
411 | CROPCAP(/* minhdelayx1 */ 68, | ||
412 | /* hdelayx1 */ 135, | ||
413 | /* swidth */ (640 * 910 + 780 / 2) / 780, | ||
414 | /* totalwidth */ 910, | ||
415 | /* sqwidth */ 780, | ||
416 | /* vdelay */ 0x16, | ||
417 | /* sheight */ 480, | ||
418 | /* videostart0 */ 23) | ||
320 | },{ | 419 | },{ |
321 | /* that one hopefully works with the strange timing | 420 | /* that one hopefully works with the strange timing |
322 | * which video recorders produce when playing a NTSC | 421 | * which video recorders produce when playing a NTSC |
@@ -338,6 +437,14 @@ const struct bttv_tvnorm bttv_tvnorms[] = { | |||
338 | .vtotal = 524, | 437 | .vtotal = 524, |
339 | .sram = -1, | 438 | .sram = -1, |
340 | .vbistart = { 10, 273 }, | 439 | .vbistart = { 10, 273 }, |
440 | CROPCAP(/* minhdelayx1 */ 68, | ||
441 | /* hdelayx1 */ 186, | ||
442 | /* swidth */ 924, | ||
443 | /* totalwidth */ 1135, | ||
444 | /* sqwidth */ 944, | ||
445 | /* vdelay */ 0x1a, | ||
446 | /* sheight */ 480, | ||
447 | /* videostart0 */ 23) | ||
341 | } | 448 | } |
342 | }; | 449 | }; |
343 | static const unsigned int BTTV_TVNORMS = ARRAY_SIZE(bttv_tvnorms); | 450 | static const unsigned int BTTV_TVNORMS = ARRAY_SIZE(bttv_tvnorms); |
@@ -678,25 +785,89 @@ static const int BTTV_CTLS = ARRAY_SIZE(bttv_ctls); | |||
678 | /* ----------------------------------------------------------------------- */ | 785 | /* ----------------------------------------------------------------------- */ |
679 | /* resource management */ | 786 | /* resource management */ |
680 | 787 | ||
788 | /* | ||
789 | RESOURCE_ allocated by freed by | ||
790 | |||
791 | VIDEO_READ bttv_read 1) bttv_read 2) | ||
792 | |||
793 | VIDEO_STREAM VIDIOC_STREAMON VIDIOC_STREAMOFF | ||
794 | VIDIOC_QBUF 1) bttv_release | ||
795 | VIDIOCMCAPTURE 1) | ||
796 | |||
797 | OVERLAY VIDIOCCAPTURE on VIDIOCCAPTURE off | ||
798 | VIDIOC_OVERLAY on VIDIOC_OVERLAY off | ||
799 | 3) bttv_release | ||
800 | |||
801 | VBI VIDIOC_STREAMON VIDIOC_STREAMOFF | ||
802 | VIDIOC_QBUF 1) bttv_release | ||
803 | bttv_read, bttv_poll 1) 4) | ||
804 | |||
805 | 1) The resource must be allocated when we enter buffer prepare functions | ||
806 | and remain allocated while buffers are in the DMA queue. | ||
807 | 2) This is a single frame read. | ||
808 | 3) VIDIOC_S_FBUF and VIDIOC_S_FMT (OVERLAY) still work when | ||
809 | RESOURCE_OVERLAY is allocated. | ||
810 | 4) This is a continuous read, implies VIDIOC_STREAMON. | ||
811 | |||
812 | Note this driver permits video input and standard changes regardless if | ||
813 | resources are allocated. | ||
814 | */ | ||
815 | |||
816 | #define VBI_RESOURCES (RESOURCE_VBI) | ||
817 | #define VIDEO_RESOURCES (RESOURCE_VIDEO_READ | \ | ||
818 | RESOURCE_VIDEO_STREAM | \ | ||
819 | RESOURCE_OVERLAY) | ||
820 | |||
681 | static | 821 | static |
682 | int check_alloc_btres(struct bttv *btv, struct bttv_fh *fh, int bit) | 822 | int check_alloc_btres(struct bttv *btv, struct bttv_fh *fh, int bit) |
683 | { | 823 | { |
824 | int xbits; /* mutual exclusive resources */ | ||
825 | |||
684 | if (fh->resources & bit) | 826 | if (fh->resources & bit) |
685 | /* have it already allocated */ | 827 | /* have it already allocated */ |
686 | return 1; | 828 | return 1; |
687 | 829 | ||
830 | xbits = bit; | ||
831 | if (bit & (RESOURCE_VIDEO_READ | RESOURCE_VIDEO_STREAM)) | ||
832 | xbits |= RESOURCE_VIDEO_READ | RESOURCE_VIDEO_STREAM; | ||
833 | |||
688 | /* is it free? */ | 834 | /* is it free? */ |
689 | mutex_lock(&btv->reslock); | 835 | mutex_lock(&btv->lock); |
690 | if (btv->resources & bit) { | 836 | if (btv->resources & xbits) { |
691 | /* no, someone else uses it */ | 837 | /* no, someone else uses it */ |
692 | mutex_unlock(&btv->reslock); | 838 | goto fail; |
693 | return 0; | 839 | } |
840 | |||
841 | if ((bit & VIDEO_RESOURCES) | ||
842 | && 0 == (btv->resources & VIDEO_RESOURCES)) { | ||
843 | /* Do crop - use current, don't - use default parameters. */ | ||
844 | __s32 top = btv->crop[!!fh->do_crop].rect.top; | ||
845 | |||
846 | if (btv->vbi_end > top) | ||
847 | goto fail; | ||
848 | |||
849 | /* We cannot capture the same line as video and VBI data. | ||
850 | Claim scan lines crop[].rect.top to bottom. */ | ||
851 | btv->crop_start = top; | ||
852 | } else if (bit & VBI_RESOURCES) { | ||
853 | __s32 end = fh->vbi_fmt.end; | ||
854 | |||
855 | if (end > btv->crop_start) | ||
856 | goto fail; | ||
857 | |||
858 | /* Claim scan lines above fh->vbi_fmt.end. */ | ||
859 | btv->vbi_end = end; | ||
694 | } | 860 | } |
861 | |||
695 | /* it's free, grab it */ | 862 | /* it's free, grab it */ |
696 | fh->resources |= bit; | 863 | fh->resources |= bit; |
697 | btv->resources |= bit; | 864 | btv->resources |= bit; |
698 | mutex_unlock(&btv->reslock); | 865 | mutex_unlock(&btv->lock); |
699 | return 1; | 866 | return 1; |
867 | |||
868 | fail: | ||
869 | mutex_unlock(&btv->lock); | ||
870 | return 0; | ||
700 | } | 871 | } |
701 | 872 | ||
702 | static | 873 | static |
@@ -711,6 +882,35 @@ int locked_btres(struct bttv *btv, int bit) | |||
711 | return (btv->resources & bit); | 882 | return (btv->resources & bit); |
712 | } | 883 | } |
713 | 884 | ||
885 | /* Call with btv->lock down. */ | ||
886 | static void | ||
887 | disclaim_vbi_lines(struct bttv *btv) | ||
888 | { | ||
889 | btv->vbi_end = 0; | ||
890 | } | ||
891 | |||
892 | /* Call with btv->lock down. */ | ||
893 | static void | ||
894 | disclaim_video_lines(struct bttv *btv) | ||
895 | { | ||
896 | const struct bttv_tvnorm *tvnorm; | ||
897 | u8 crop; | ||
898 | |||
899 | tvnorm = &bttv_tvnorms[btv->tvnorm]; | ||
900 | btv->crop_start = tvnorm->cropcap.bounds.top | ||
901 | + tvnorm->cropcap.bounds.height; | ||
902 | |||
903 | /* VBI capturing ends at VDELAY, start of video capturing, no | ||
904 | matter how many lines the VBI RISC program expects. When video | ||
905 | capturing is off, it shall no longer "preempt" VBI capturing, | ||
906 | so we set VDELAY to maximum. */ | ||
907 | crop = btread(BT848_E_CROP) | 0xc0; | ||
908 | btwrite(crop, BT848_E_CROP); | ||
909 | btwrite(0xfe, BT848_E_VDELAY_LO); | ||
910 | btwrite(crop, BT848_O_CROP); | ||
911 | btwrite(0xfe, BT848_O_VDELAY_LO); | ||
912 | } | ||
913 | |||
714 | static | 914 | static |
715 | void free_btres(struct bttv *btv, struct bttv_fh *fh, int bits) | 915 | void free_btres(struct bttv *btv, struct bttv_fh *fh, int bits) |
716 | { | 916 | { |
@@ -718,10 +918,19 @@ void free_btres(struct bttv *btv, struct bttv_fh *fh, int bits) | |||
718 | /* trying to free ressources not allocated by us ... */ | 918 | /* trying to free ressources not allocated by us ... */ |
719 | printk("bttv: BUG! (btres)\n"); | 919 | printk("bttv: BUG! (btres)\n"); |
720 | } | 920 | } |
721 | mutex_lock(&btv->reslock); | 921 | mutex_lock(&btv->lock); |
722 | fh->resources &= ~bits; | 922 | fh->resources &= ~bits; |
723 | btv->resources &= ~bits; | 923 | btv->resources &= ~bits; |
724 | mutex_unlock(&btv->reslock); | 924 | |
925 | bits = btv->resources; | ||
926 | |||
927 | if (0 == (bits & VIDEO_RESOURCES)) | ||
928 | disclaim_video_lines(btv); | ||
929 | |||
930 | if (0 == (bits & VBI_RESOURCES)) | ||
931 | disclaim_vbi_lines(btv); | ||
932 | |||
933 | mutex_unlock(&btv->lock); | ||
725 | } | 934 | } |
726 | 935 | ||
727 | /* ----------------------------------------------------------------------- */ | 936 | /* ----------------------------------------------------------------------- */ |
@@ -1030,6 +1239,36 @@ i2c_vidiocschan(struct bttv *btv) | |||
1030 | bttv_tda9880_setnorm(btv,btv->tvnorm); | 1239 | bttv_tda9880_setnorm(btv,btv->tvnorm); |
1031 | } | 1240 | } |
1032 | 1241 | ||
1242 | static void | ||
1243 | bttv_crop_calc_limits(struct bttv_crop *c) | ||
1244 | { | ||
1245 | /* Scale factor min. 1:1, max. 16:1. Min. image size | ||
1246 | 48 x 32. Scaled width must be a multiple of 4. */ | ||
1247 | |||
1248 | if (1) { | ||
1249 | /* For bug compatibility with VIDIOCGCAP and image | ||
1250 | size checks in earlier driver versions. */ | ||
1251 | c->min_scaled_width = 48; | ||
1252 | c->min_scaled_height = 32; | ||
1253 | } else { | ||
1254 | c->min_scaled_width = | ||
1255 | (max(48, c->rect.width >> 4) + 3) & ~3; | ||
1256 | c->min_scaled_height = | ||
1257 | max(32, c->rect.height >> 4); | ||
1258 | } | ||
1259 | |||
1260 | c->max_scaled_width = c->rect.width & ~3; | ||
1261 | c->max_scaled_height = c->rect.height; | ||
1262 | } | ||
1263 | |||
1264 | static void | ||
1265 | bttv_crop_reset(struct bttv_crop *c, int norm) | ||
1266 | { | ||
1267 | c->rect = bttv_tvnorms[norm].cropcap.defrect; | ||
1268 | bttv_crop_calc_limits(c); | ||
1269 | } | ||
1270 | |||
1271 | /* Call with btv->lock down. */ | ||
1033 | static int | 1272 | static int |
1034 | set_tvnorm(struct bttv *btv, unsigned int norm) | 1273 | set_tvnorm(struct bttv *btv, unsigned int norm) |
1035 | { | 1274 | { |
@@ -1038,9 +1277,24 @@ set_tvnorm(struct bttv *btv, unsigned int norm) | |||
1038 | if (norm < 0 || norm >= BTTV_TVNORMS) | 1277 | if (norm < 0 || norm >= BTTV_TVNORMS) |
1039 | return -EINVAL; | 1278 | return -EINVAL; |
1040 | 1279 | ||
1041 | btv->tvnorm = norm; | ||
1042 | tvnorm = &bttv_tvnorms[norm]; | 1280 | tvnorm = &bttv_tvnorms[norm]; |
1043 | 1281 | ||
1282 | if (btv->tvnorm < 0 || | ||
1283 | btv->tvnorm >= BTTV_TVNORMS || | ||
1284 | 0 != memcmp(&bttv_tvnorms[btv->tvnorm].cropcap, | ||
1285 | &tvnorm->cropcap, | ||
1286 | sizeof (tvnorm->cropcap))) { | ||
1287 | bttv_crop_reset(&btv->crop[0], norm); | ||
1288 | btv->crop[1] = btv->crop[0]; /* current = default */ | ||
1289 | |||
1290 | if (0 == (btv->resources & VIDEO_RESOURCES)) { | ||
1291 | btv->crop_start = tvnorm->cropcap.bounds.top | ||
1292 | + tvnorm->cropcap.bounds.height; | ||
1293 | } | ||
1294 | } | ||
1295 | |||
1296 | btv->tvnorm = norm; | ||
1297 | |||
1044 | btwrite(tvnorm->adelay, BT848_ADELAY); | 1298 | btwrite(tvnorm->adelay, BT848_ADELAY); |
1045 | btwrite(tvnorm->bdelay, BT848_BDELAY); | 1299 | btwrite(tvnorm->bdelay, BT848_BDELAY); |
1046 | btaor(tvnorm->iform,~(BT848_IFORM_NORM|BT848_IFORM_XTBOTH), | 1300 | btaor(tvnorm->iform,~(BT848_IFORM_NORM|BT848_IFORM_XTBOTH), |
@@ -1057,6 +1311,7 @@ set_tvnorm(struct bttv *btv, unsigned int norm) | |||
1057 | return 0; | 1311 | return 0; |
1058 | } | 1312 | } |
1059 | 1313 | ||
1314 | /* Call with btv->lock down. */ | ||
1060 | static void | 1315 | static void |
1061 | set_input(struct bttv *btv, unsigned int input) | 1316 | set_input(struct bttv *btv, unsigned int input) |
1062 | { | 1317 | { |
@@ -1459,13 +1714,13 @@ bttv_switch_overlay(struct bttv *btv, struct bttv_fh *fh, | |||
1459 | btv->loop_irq |= 1; | 1714 | btv->loop_irq |= 1; |
1460 | bttv_set_dma(btv, 0x03); | 1715 | bttv_set_dma(btv, 0x03); |
1461 | spin_unlock_irqrestore(&btv->s_lock,flags); | 1716 | spin_unlock_irqrestore(&btv->s_lock,flags); |
1462 | if (NULL == new) | ||
1463 | free_btres(btv,fh,RESOURCE_OVERLAY); | ||
1464 | if (NULL != old) { | 1717 | if (NULL != old) { |
1465 | dprintk("switch_overlay: old=%p state is %d\n",old,old->vb.state); | 1718 | dprintk("switch_overlay: old=%p state is %d\n",old,old->vb.state); |
1466 | bttv_dma_free(&fh->cap,btv, old); | 1719 | bttv_dma_free(&fh->cap,btv, old); |
1467 | kfree(old); | 1720 | kfree(old); |
1468 | } | 1721 | } |
1722 | if (NULL == new) | ||
1723 | free_btres(btv,fh,RESOURCE_OVERLAY); | ||
1469 | dprintk("switch_overlay: done\n"); | 1724 | dprintk("switch_overlay: done\n"); |
1470 | return retval; | 1725 | return retval; |
1471 | } | 1726 | } |
@@ -1479,7 +1734,10 @@ static int bttv_prepare_buffer(struct videobuf_queue *q,struct bttv *btv, | |||
1479 | unsigned int width, unsigned int height, | 1734 | unsigned int width, unsigned int height, |
1480 | enum v4l2_field field) | 1735 | enum v4l2_field field) |
1481 | { | 1736 | { |
1737 | struct bttv_fh *fh = q->priv_data; | ||
1482 | int redo_dma_risc = 0; | 1738 | int redo_dma_risc = 0; |
1739 | struct bttv_crop c; | ||
1740 | int norm; | ||
1483 | int rc; | 1741 | int rc; |
1484 | 1742 | ||
1485 | /* check settings */ | 1743 | /* check settings */ |
@@ -1491,12 +1749,52 @@ static int bttv_prepare_buffer(struct videobuf_queue *q,struct bttv *btv, | |||
1491 | if (width*height > buf->vb.bsize) | 1749 | if (width*height > buf->vb.bsize) |
1492 | return -EINVAL; | 1750 | return -EINVAL; |
1493 | buf->vb.size = buf->vb.bsize; | 1751 | buf->vb.size = buf->vb.bsize; |
1752 | |||
1753 | /* Make sure tvnorm and vbi_end remain consistent | ||
1754 | until we're done. */ | ||
1755 | mutex_lock(&btv->lock); | ||
1756 | |||
1757 | norm = btv->tvnorm; | ||
1758 | |||
1759 | /* In this mode capturing always starts at defrect.top | ||
1760 | (default VDELAY), ignoring cropping parameters. */ | ||
1761 | if (btv->vbi_end > bttv_tvnorms[norm].cropcap.defrect.top) { | ||
1762 | mutex_unlock(&btv->lock); | ||
1763 | return -EINVAL; | ||
1764 | } | ||
1765 | |||
1766 | mutex_unlock(&btv->lock); | ||
1767 | |||
1768 | c.rect = bttv_tvnorms[norm].cropcap.defrect; | ||
1494 | } else { | 1769 | } else { |
1495 | if (width < 48 || | 1770 | mutex_lock(&btv->lock); |
1496 | height < 32 || | 1771 | |
1497 | width > bttv_tvnorms[btv->tvnorm].swidth || | 1772 | norm = btv->tvnorm; |
1498 | height > bttv_tvnorms[btv->tvnorm].sheight) | 1773 | c = btv->crop[!!fh->do_crop]; |
1774 | |||
1775 | mutex_unlock(&btv->lock); | ||
1776 | |||
1777 | if (width < c.min_scaled_width || | ||
1778 | width > c.max_scaled_width || | ||
1779 | height < c.min_scaled_height) | ||
1499 | return -EINVAL; | 1780 | return -EINVAL; |
1781 | |||
1782 | switch (field) { | ||
1783 | case V4L2_FIELD_TOP: | ||
1784 | case V4L2_FIELD_BOTTOM: | ||
1785 | case V4L2_FIELD_ALTERNATE: | ||
1786 | /* btv->crop counts frame lines. Max. scale | ||
1787 | factor is 16:1 for frames, 8:1 for fields. */ | ||
1788 | if (height * 2 > c.max_scaled_height) | ||
1789 | return -EINVAL; | ||
1790 | break; | ||
1791 | |||
1792 | default: | ||
1793 | if (height > c.max_scaled_height) | ||
1794 | return -EINVAL; | ||
1795 | break; | ||
1796 | } | ||
1797 | |||
1500 | buf->vb.size = (width * height * fmt->depth) >> 3; | 1798 | buf->vb.size = (width * height * fmt->depth) >> 3; |
1501 | if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) | 1799 | if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) |
1502 | return -EINVAL; | 1800 | return -EINVAL; |
@@ -1505,12 +1803,17 @@ static int bttv_prepare_buffer(struct videobuf_queue *q,struct bttv *btv, | |||
1505 | /* alloc + fill struct bttv_buffer (if changed) */ | 1803 | /* alloc + fill struct bttv_buffer (if changed) */ |
1506 | if (buf->vb.width != width || buf->vb.height != height || | 1804 | if (buf->vb.width != width || buf->vb.height != height || |
1507 | buf->vb.field != field || | 1805 | buf->vb.field != field || |
1508 | buf->tvnorm != btv->tvnorm || buf->fmt != fmt) { | 1806 | buf->tvnorm != norm || buf->fmt != fmt || |
1807 | buf->crop.top != c.rect.top || | ||
1808 | buf->crop.left != c.rect.left || | ||
1809 | buf->crop.width != c.rect.width || | ||
1810 | buf->crop.height != c.rect.height) { | ||
1509 | buf->vb.width = width; | 1811 | buf->vb.width = width; |
1510 | buf->vb.height = height; | 1812 | buf->vb.height = height; |
1511 | buf->vb.field = field; | 1813 | buf->vb.field = field; |
1512 | buf->tvnorm = btv->tvnorm; | 1814 | buf->tvnorm = norm; |
1513 | buf->fmt = fmt; | 1815 | buf->fmt = fmt; |
1816 | buf->crop = c.rect; | ||
1514 | redo_dma_risc = 1; | 1817 | redo_dma_risc = 1; |
1515 | } | 1818 | } |
1516 | 1819 | ||
@@ -1577,7 +1880,7 @@ static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb) | |||
1577 | struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb); | 1880 | struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb); |
1578 | struct bttv_fh *fh = q->priv_data; | 1881 | struct bttv_fh *fh = q->priv_data; |
1579 | 1882 | ||
1580 | bttv_dma_free(&fh->cap,fh->btv,buf); | 1883 | bttv_dma_free(q,fh->btv,buf); |
1581 | } | 1884 | } |
1582 | 1885 | ||
1583 | static struct videobuf_queue_ops bttv_video_qops = { | 1886 | static struct videobuf_queue_ops bttv_video_qops = { |
@@ -1939,11 +2242,179 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) | |||
1939 | return 0; | 2242 | return 0; |
1940 | } | 2243 | } |
1941 | 2244 | ||
1942 | static int verify_window(const struct bttv_tvnorm *tvn, | 2245 | /* Given cropping boundaries b and the scaled width and height of a |
1943 | struct v4l2_window *win, int fixup) | 2246 | single field or frame, which must not exceed hardware limits, this |
2247 | function adjusts the cropping parameters c. */ | ||
2248 | static void | ||
2249 | bttv_crop_adjust (struct bttv_crop * c, | ||
2250 | const struct v4l2_rect * b, | ||
2251 | __s32 width, | ||
2252 | __s32 height, | ||
2253 | enum v4l2_field field) | ||
2254 | { | ||
2255 | __s32 frame_height = height << !V4L2_FIELD_HAS_BOTH(field); | ||
2256 | __s32 max_left; | ||
2257 | __s32 max_top; | ||
2258 | |||
2259 | if (width < c->min_scaled_width) { | ||
2260 | /* Max. hor. scale factor 16:1. */ | ||
2261 | c->rect.width = width * 16; | ||
2262 | } else if (width > c->max_scaled_width) { | ||
2263 | /* Min. hor. scale factor 1:1. */ | ||
2264 | c->rect.width = width; | ||
2265 | |||
2266 | max_left = b->left + b->width - width; | ||
2267 | max_left = min(max_left, (__s32) MAX_HDELAY); | ||
2268 | if (c->rect.left > max_left) | ||
2269 | c->rect.left = max_left; | ||
2270 | } | ||
2271 | |||
2272 | if (height < c->min_scaled_height) { | ||
2273 | /* Max. vert. scale factor 16:1, single fields 8:1. */ | ||
2274 | c->rect.height = height * 16; | ||
2275 | } else if (frame_height > c->max_scaled_height) { | ||
2276 | /* Min. vert. scale factor 1:1. | ||
2277 | Top and height count field lines times two. */ | ||
2278 | c->rect.height = (frame_height + 1) & ~1; | ||
2279 | |||
2280 | max_top = b->top + b->height - c->rect.height; | ||
2281 | if (c->rect.top > max_top) | ||
2282 | c->rect.top = max_top; | ||
2283 | } | ||
2284 | |||
2285 | bttv_crop_calc_limits(c); | ||
2286 | } | ||
2287 | |||
2288 | /* Returns an error if scaling to a frame or single field with the given | ||
2289 | width and height is not possible with the current cropping parameters | ||
2290 | and width aligned according to width_mask. If adjust_size is TRUE the | ||
2291 | function may adjust the width and/or height instead, rounding width | ||
2292 | to (width + width_bias) & width_mask. If adjust_crop is TRUE it may | ||
2293 | also adjust the current cropping parameters to get closer to the | ||
2294 | desired image size. */ | ||
2295 | static int | ||
2296 | limit_scaled_size (struct bttv_fh * fh, | ||
2297 | __s32 * width, | ||
2298 | __s32 * height, | ||
2299 | enum v4l2_field field, | ||
2300 | unsigned int width_mask, | ||
2301 | unsigned int width_bias, | ||
2302 | int adjust_size, | ||
2303 | int adjust_crop) | ||
2304 | { | ||
2305 | struct bttv *btv = fh->btv; | ||
2306 | const struct v4l2_rect *b; | ||
2307 | struct bttv_crop *c; | ||
2308 | __s32 min_width; | ||
2309 | __s32 min_height; | ||
2310 | __s32 max_width; | ||
2311 | __s32 max_height; | ||
2312 | int rc; | ||
2313 | |||
2314 | BUG_ON((int) width_mask >= 0 || | ||
2315 | width_bias >= (unsigned int) -width_mask); | ||
2316 | |||
2317 | /* Make sure tvnorm, vbi_end and the current cropping parameters | ||
2318 | remain consistent until we're done. */ | ||
2319 | mutex_lock(&btv->lock); | ||
2320 | |||
2321 | b = &bttv_tvnorms[btv->tvnorm].cropcap.bounds; | ||
2322 | |||
2323 | /* Do crop - use current, don't - use default parameters. */ | ||
2324 | c = &btv->crop[!!fh->do_crop]; | ||
2325 | |||
2326 | if (fh->do_crop | ||
2327 | && adjust_size | ||
2328 | && adjust_crop | ||
2329 | && !locked_btres(btv, VIDEO_RESOURCES)) { | ||
2330 | min_width = 48; | ||
2331 | min_height = 32; | ||
2332 | |||
2333 | /* We cannot scale up. When the scaled image is larger | ||
2334 | than crop.rect we adjust the crop.rect as required | ||
2335 | by the V4L2 spec, hence cropcap.bounds are our limit. */ | ||
2336 | max_width = min(b->width, (__s32) MAX_HACTIVE); | ||
2337 | max_height = b->height; | ||
2338 | |||
2339 | /* We cannot capture the same line as video and VBI data. | ||
2340 | Note btv->vbi_end is really a minimum, see | ||
2341 | bttv_vbi_try_fmt(). */ | ||
2342 | if (btv->vbi_end > b->top) { | ||
2343 | max_height -= btv->vbi_end - b->top; | ||
2344 | rc = -EBUSY; | ||
2345 | if (min_height > max_height) | ||
2346 | goto fail; | ||
2347 | } | ||
2348 | } else { | ||
2349 | rc = -EBUSY; | ||
2350 | if (btv->vbi_end > c->rect.top) | ||
2351 | goto fail; | ||
2352 | |||
2353 | min_width = c->min_scaled_width; | ||
2354 | min_height = c->min_scaled_height; | ||
2355 | max_width = c->max_scaled_width; | ||
2356 | max_height = c->max_scaled_height; | ||
2357 | |||
2358 | adjust_crop = 0; | ||
2359 | } | ||
2360 | |||
2361 | min_width = (min_width - width_mask - 1) & width_mask; | ||
2362 | max_width = max_width & width_mask; | ||
2363 | |||
2364 | /* Max. scale factor is 16:1 for frames, 8:1 for fields. */ | ||
2365 | min_height = min_height; | ||
2366 | /* Min. scale factor is 1:1. */ | ||
2367 | max_height >>= !V4L2_FIELD_HAS_BOTH(field); | ||
2368 | |||
2369 | if (adjust_size) { | ||
2370 | *width = clamp(*width, min_width, max_width); | ||
2371 | *height = clamp(*height, min_height, max_height); | ||
2372 | |||
2373 | /* Round after clamping to avoid overflow. */ | ||
2374 | *width = (*width + width_bias) & width_mask; | ||
2375 | |||
2376 | if (adjust_crop) { | ||
2377 | bttv_crop_adjust(c, b, *width, *height, field); | ||
2378 | |||
2379 | if (btv->vbi_end > c->rect.top) { | ||
2380 | /* Move the crop window out of the way. */ | ||
2381 | c->rect.top = btv->vbi_end; | ||
2382 | } | ||
2383 | } | ||
2384 | } else { | ||
2385 | rc = -EINVAL; | ||
2386 | if (*width < min_width || | ||
2387 | *height < min_height || | ||
2388 | *width > max_width || | ||
2389 | *height > max_height || | ||
2390 | 0 != (*width & ~width_mask)) | ||
2391 | goto fail; | ||
2392 | } | ||
2393 | |||
2394 | rc = 0; /* success */ | ||
2395 | |||
2396 | fail: | ||
2397 | mutex_unlock(&btv->lock); | ||
2398 | |||
2399 | return rc; | ||
2400 | } | ||
2401 | |||
2402 | /* Returns an error if the given overlay window dimensions are not | ||
2403 | possible with the current cropping parameters. If adjust_size is | ||
2404 | TRUE the function may adjust the window width and/or height | ||
2405 | instead, however it always rounds the horizontal position and | ||
2406 | width as btcx_align() does. If adjust_crop is TRUE the function | ||
2407 | may also adjust the current cropping parameters to get closer | ||
2408 | to the desired window size. */ | ||
2409 | static int | ||
2410 | verify_window (struct bttv_fh * fh, | ||
2411 | struct v4l2_window * win, | ||
2412 | int adjust_size, | ||
2413 | int adjust_crop) | ||
1944 | { | 2414 | { |
1945 | enum v4l2_field field; | 2415 | enum v4l2_field field; |
1946 | int maxw, maxh; | 2416 | unsigned int width_mask; |
2417 | int rc; | ||
1947 | 2418 | ||
1948 | if (win->w.width < 48 || win->w.height < 32) | 2419 | if (win->w.width < 48 || win->w.height < 32) |
1949 | return -EINVAL; | 2420 | return -EINVAL; |
@@ -1951,32 +2422,52 @@ static int verify_window(const struct bttv_tvnorm *tvn, | |||
1951 | return -EINVAL; | 2422 | return -EINVAL; |
1952 | 2423 | ||
1953 | field = win->field; | 2424 | field = win->field; |
1954 | maxw = tvn->swidth; | ||
1955 | maxh = tvn->sheight; | ||
1956 | 2425 | ||
1957 | if (V4L2_FIELD_ANY == field) { | 2426 | if (V4L2_FIELD_ANY == field) { |
1958 | field = (win->w.height > maxh/2) | 2427 | __s32 height2; |
2428 | |||
2429 | height2 = fh->btv->crop[!!fh->do_crop].rect.height >> 1; | ||
2430 | field = (win->w.height > height2) | ||
1959 | ? V4L2_FIELD_INTERLACED | 2431 | ? V4L2_FIELD_INTERLACED |
1960 | : V4L2_FIELD_TOP; | 2432 | : V4L2_FIELD_TOP; |
1961 | } | 2433 | } |
1962 | switch (field) { | 2434 | switch (field) { |
1963 | case V4L2_FIELD_TOP: | 2435 | case V4L2_FIELD_TOP: |
1964 | case V4L2_FIELD_BOTTOM: | 2436 | case V4L2_FIELD_BOTTOM: |
1965 | maxh = maxh / 2; | ||
1966 | break; | ||
1967 | case V4L2_FIELD_INTERLACED: | 2437 | case V4L2_FIELD_INTERLACED: |
1968 | break; | 2438 | break; |
1969 | default: | 2439 | default: |
1970 | return -EINVAL; | 2440 | return -EINVAL; |
1971 | } | 2441 | } |
1972 | 2442 | ||
1973 | if (!fixup && (win->w.width > maxw || win->w.height > maxh)) | 2443 | /* 4-byte alignment. */ |
2444 | if (NULL == fh->ovfmt) | ||
1974 | return -EINVAL; | 2445 | return -EINVAL; |
2446 | width_mask = ~0; | ||
2447 | switch (fh->ovfmt->depth) { | ||
2448 | case 8: | ||
2449 | case 24: | ||
2450 | width_mask = ~3; | ||
2451 | break; | ||
2452 | case 16: | ||
2453 | width_mask = ~1; | ||
2454 | break; | ||
2455 | case 32: | ||
2456 | break; | ||
2457 | default: | ||
2458 | BUG(); | ||
2459 | } | ||
2460 | |||
2461 | win->w.width -= win->w.left & ~width_mask; | ||
2462 | win->w.left = (win->w.left - width_mask - 1) & width_mask; | ||
2463 | |||
2464 | rc = limit_scaled_size(fh, &win->w.width, &win->w.height, | ||
2465 | field, width_mask, | ||
2466 | /* width_bias: round down */ 0, | ||
2467 | adjust_size, adjust_crop); | ||
2468 | if (0 != rc) | ||
2469 | return rc; | ||
1975 | 2470 | ||
1976 | if (win->w.width > maxw) | ||
1977 | win->w.width = maxw; | ||
1978 | if (win->w.height > maxh) | ||
1979 | win->w.height = maxh; | ||
1980 | win->field = field; | 2471 | win->field = field; |
1981 | return 0; | 2472 | return 0; |
1982 | } | 2473 | } |
@@ -1991,7 +2482,9 @@ static int setup_window(struct bttv_fh *fh, struct bttv *btv, | |||
1991 | return -EINVAL; | 2482 | return -EINVAL; |
1992 | if (!(fh->ovfmt->flags & FORMAT_FLAGS_PACKED)) | 2483 | if (!(fh->ovfmt->flags & FORMAT_FLAGS_PACKED)) |
1993 | return -EINVAL; | 2484 | return -EINVAL; |
1994 | retval = verify_window(&bttv_tvnorms[btv->tvnorm],win,fixup); | 2485 | retval = verify_window(fh, win, |
2486 | /* adjust_size */ fixup, | ||
2487 | /* adjust_crop */ fixup); | ||
1995 | if (0 != retval) | 2488 | if (0 != retval) |
1996 | return retval; | 2489 | return retval; |
1997 | 2490 | ||
@@ -2048,6 +2541,7 @@ static int setup_window(struct bttv_fh *fh, struct bttv *btv, | |||
2048 | struct bttv_buffer *new; | 2541 | struct bttv_buffer *new; |
2049 | 2542 | ||
2050 | new = videobuf_alloc(sizeof(*new)); | 2543 | new = videobuf_alloc(sizeof(*new)); |
2544 | new->crop = btv->crop[!!fh->do_crop].rect; | ||
2051 | bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new); | 2545 | bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new); |
2052 | retval = bttv_switch_overlay(btv,fh,new); | 2546 | retval = bttv_switch_overlay(btv,fh,new); |
2053 | } | 2547 | } |
@@ -2080,7 +2574,7 @@ static int bttv_resource(struct bttv_fh *fh) | |||
2080 | 2574 | ||
2081 | switch (fh->type) { | 2575 | switch (fh->type) { |
2082 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | 2576 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: |
2083 | res = RESOURCE_VIDEO; | 2577 | res = RESOURCE_VIDEO_STREAM; |
2084 | break; | 2578 | break; |
2085 | case V4L2_BUF_TYPE_VBI_CAPTURE: | 2579 | case V4L2_BUF_TYPE_VBI_CAPTURE: |
2086 | res = RESOURCE_VBI; | 2580 | res = RESOURCE_VBI; |
@@ -2138,7 +2632,7 @@ static int bttv_g_fmt(struct bttv_fh *fh, struct v4l2_format *f) | |||
2138 | f->fmt.win.field = fh->ov.field; | 2632 | f->fmt.win.field = fh->ov.field; |
2139 | return 0; | 2633 | return 0; |
2140 | case V4L2_BUF_TYPE_VBI_CAPTURE: | 2634 | case V4L2_BUF_TYPE_VBI_CAPTURE: |
2141 | bttv_vbi_get_fmt(fh,f); | 2635 | bttv_vbi_get_fmt(fh, &f->fmt.vbi); |
2142 | return 0; | 2636 | return 0; |
2143 | default: | 2637 | default: |
2144 | return -EINVAL; | 2638 | return -EINVAL; |
@@ -2146,35 +2640,35 @@ static int bttv_g_fmt(struct bttv_fh *fh, struct v4l2_format *f) | |||
2146 | } | 2640 | } |
2147 | 2641 | ||
2148 | static int bttv_try_fmt(struct bttv_fh *fh, struct bttv *btv, | 2642 | static int bttv_try_fmt(struct bttv_fh *fh, struct bttv *btv, |
2149 | struct v4l2_format *f) | 2643 | struct v4l2_format *f, int adjust_crop) |
2150 | { | 2644 | { |
2151 | switch (f->type) { | 2645 | switch (f->type) { |
2152 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | 2646 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: |
2153 | { | 2647 | { |
2154 | const struct bttv_format *fmt; | 2648 | const struct bttv_format *fmt; |
2155 | enum v4l2_field field; | 2649 | enum v4l2_field field; |
2156 | unsigned int maxw,maxh; | 2650 | __s32 width, height; |
2651 | int rc; | ||
2157 | 2652 | ||
2158 | fmt = format_by_fourcc(f->fmt.pix.pixelformat); | 2653 | fmt = format_by_fourcc(f->fmt.pix.pixelformat); |
2159 | if (NULL == fmt) | 2654 | if (NULL == fmt) |
2160 | return -EINVAL; | 2655 | return -EINVAL; |
2161 | 2656 | ||
2162 | /* fixup format */ | ||
2163 | maxw = bttv_tvnorms[btv->tvnorm].swidth; | ||
2164 | maxh = bttv_tvnorms[btv->tvnorm].sheight; | ||
2165 | field = f->fmt.pix.field; | 2657 | field = f->fmt.pix.field; |
2166 | if (V4L2_FIELD_ANY == field) | 2658 | if (V4L2_FIELD_ANY == field) { |
2167 | field = (f->fmt.pix.height > maxh/2) | 2659 | __s32 height2; |
2660 | |||
2661 | height2 = btv->crop[!!fh->do_crop].rect.height >> 1; | ||
2662 | field = (f->fmt.pix.height > height2) | ||
2168 | ? V4L2_FIELD_INTERLACED | 2663 | ? V4L2_FIELD_INTERLACED |
2169 | : V4L2_FIELD_BOTTOM; | 2664 | : V4L2_FIELD_BOTTOM; |
2665 | } | ||
2170 | if (V4L2_FIELD_SEQ_BT == field) | 2666 | if (V4L2_FIELD_SEQ_BT == field) |
2171 | field = V4L2_FIELD_SEQ_TB; | 2667 | field = V4L2_FIELD_SEQ_TB; |
2172 | switch (field) { | 2668 | switch (field) { |
2173 | case V4L2_FIELD_TOP: | 2669 | case V4L2_FIELD_TOP: |
2174 | case V4L2_FIELD_BOTTOM: | 2670 | case V4L2_FIELD_BOTTOM: |
2175 | case V4L2_FIELD_ALTERNATE: | 2671 | case V4L2_FIELD_ALTERNATE: |
2176 | maxh = maxh/2; | ||
2177 | break; | ||
2178 | case V4L2_FIELD_INTERLACED: | 2672 | case V4L2_FIELD_INTERLACED: |
2179 | break; | 2673 | break; |
2180 | case V4L2_FIELD_SEQ_TB: | 2674 | case V4L2_FIELD_SEQ_TB: |
@@ -2185,28 +2679,29 @@ static int bttv_try_fmt(struct bttv_fh *fh, struct bttv *btv, | |||
2185 | return -EINVAL; | 2679 | return -EINVAL; |
2186 | } | 2680 | } |
2187 | 2681 | ||
2682 | width = f->fmt.pix.width; | ||
2683 | height = f->fmt.pix.height; | ||
2684 | |||
2685 | rc = limit_scaled_size(fh, &width, &height, field, | ||
2686 | /* width_mask: 4 pixels */ ~3, | ||
2687 | /* width_bias: nearest */ 2, | ||
2688 | /* adjust_size */ 1, | ||
2689 | adjust_crop); | ||
2690 | if (0 != rc) | ||
2691 | return rc; | ||
2692 | |||
2188 | /* update data for the application */ | 2693 | /* update data for the application */ |
2189 | f->fmt.pix.field = field; | 2694 | f->fmt.pix.field = field; |
2190 | if (f->fmt.pix.width < 48) | 2695 | pix_format_set_size(&f->fmt.pix, fmt, width, height); |
2191 | f->fmt.pix.width = 48; | ||
2192 | if (f->fmt.pix.height < 32) | ||
2193 | f->fmt.pix.height = 32; | ||
2194 | if (f->fmt.pix.width > maxw) | ||
2195 | f->fmt.pix.width = maxw; | ||
2196 | if (f->fmt.pix.height > maxh) | ||
2197 | f->fmt.pix.height = maxh; | ||
2198 | pix_format_set_size (&f->fmt.pix, fmt, | ||
2199 | f->fmt.pix.width & ~3, | ||
2200 | f->fmt.pix.height); | ||
2201 | 2696 | ||
2202 | return 0; | 2697 | return 0; |
2203 | } | 2698 | } |
2204 | case V4L2_BUF_TYPE_VIDEO_OVERLAY: | 2699 | case V4L2_BUF_TYPE_VIDEO_OVERLAY: |
2205 | return verify_window(&bttv_tvnorms[btv->tvnorm], | 2700 | return verify_window(fh, &f->fmt.win, |
2206 | &f->fmt.win, 1); | 2701 | /* adjust_size */ 1, |
2702 | /* adjust_crop */ 0); | ||
2207 | case V4L2_BUF_TYPE_VBI_CAPTURE: | 2703 | case V4L2_BUF_TYPE_VBI_CAPTURE: |
2208 | bttv_vbi_try_fmt(fh,f); | 2704 | return bttv_vbi_try_fmt(fh, &f->fmt.vbi); |
2209 | return 0; | ||
2210 | default: | 2705 | default: |
2211 | return -EINVAL; | 2706 | return -EINVAL; |
2212 | } | 2707 | } |
@@ -2225,7 +2720,7 @@ static int bttv_s_fmt(struct bttv_fh *fh, struct bttv *btv, | |||
2225 | retval = bttv_switch_type(fh,f->type); | 2720 | retval = bttv_switch_type(fh,f->type); |
2226 | if (0 != retval) | 2721 | if (0 != retval) |
2227 | return retval; | 2722 | return retval; |
2228 | retval = bttv_try_fmt(fh,btv,f); | 2723 | retval = bttv_try_fmt(fh,btv,f, /* adjust_crop */ 1); |
2229 | if (0 != retval) | 2724 | if (0 != retval) |
2230 | return retval; | 2725 | return retval; |
2231 | fmt = format_by_fourcc(f->fmt.pix.pixelformat); | 2726 | fmt = format_by_fourcc(f->fmt.pix.pixelformat); |
@@ -2254,12 +2749,7 @@ static int bttv_s_fmt(struct bttv_fh *fh, struct bttv *btv, | |||
2254 | retval = bttv_switch_type(fh,f->type); | 2749 | retval = bttv_switch_type(fh,f->type); |
2255 | if (0 != retval) | 2750 | if (0 != retval) |
2256 | return retval; | 2751 | return retval; |
2257 | if (locked_btres(fh->btv, RESOURCE_VBI)) | 2752 | return bttv_vbi_set_fmt(fh, &f->fmt.vbi); |
2258 | return -EBUSY; | ||
2259 | bttv_vbi_try_fmt(fh,f); | ||
2260 | bttv_vbi_setlines(fh,btv,f->fmt.vbi.count[0]); | ||
2261 | bttv_vbi_get_fmt(fh,f); | ||
2262 | return 0; | ||
2263 | default: | 2753 | default: |
2264 | return -EINVAL; | 2754 | return -EINVAL; |
2265 | } | 2755 | } |
@@ -2517,6 +3007,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, | |||
2517 | if (*on) { | 3007 | if (*on) { |
2518 | fh->ov.tvnorm = btv->tvnorm; | 3008 | fh->ov.tvnorm = btv->tvnorm; |
2519 | new = videobuf_alloc(sizeof(*new)); | 3009 | new = videobuf_alloc(sizeof(*new)); |
3010 | new->crop = btv->crop[!!fh->do_crop].rect; | ||
2520 | bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new); | 3011 | bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new); |
2521 | } else { | 3012 | } else { |
2522 | new = NULL; | 3013 | new = NULL; |
@@ -2551,10 +3042,16 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, | |||
2551 | struct video_mmap *vm = arg; | 3042 | struct video_mmap *vm = arg; |
2552 | struct bttv_buffer *buf; | 3043 | struct bttv_buffer *buf; |
2553 | enum v4l2_field field; | 3044 | enum v4l2_field field; |
3045 | __s32 height2; | ||
3046 | int res; | ||
2554 | 3047 | ||
2555 | if (vm->frame >= VIDEO_MAX_FRAME) | 3048 | if (vm->frame >= VIDEO_MAX_FRAME) |
2556 | return -EINVAL; | 3049 | return -EINVAL; |
2557 | 3050 | ||
3051 | res = bttv_resource(fh); | ||
3052 | if (!check_alloc_btres(btv, fh, res)) | ||
3053 | return -EBUSY; | ||
3054 | |||
2558 | mutex_lock(&fh->cap.lock); | 3055 | mutex_lock(&fh->cap.lock); |
2559 | retval = -EINVAL; | 3056 | retval = -EINVAL; |
2560 | buf = (struct bttv_buffer *)fh->cap.bufs[vm->frame]; | 3057 | buf = (struct bttv_buffer *)fh->cap.bufs[vm->frame]; |
@@ -2566,7 +3063,8 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, | |||
2566 | buf->vb.state == STATE_ACTIVE) | 3063 | buf->vb.state == STATE_ACTIVE) |
2567 | goto fh_unlock_and_return; | 3064 | goto fh_unlock_and_return; |
2568 | 3065 | ||
2569 | field = (vm->height > bttv_tvnorms[btv->tvnorm].sheight/2) | 3066 | height2 = btv->crop[!!fh->do_crop].rect.height >> 1; |
3067 | field = (vm->height > height2) | ||
2570 | ? V4L2_FIELD_INTERLACED | 3068 | ? V4L2_FIELD_INTERLACED |
2571 | : V4L2_FIELD_BOTTOM; | 3069 | : V4L2_FIELD_BOTTOM; |
2572 | retval = bttv_prepare_buffer(&fh->cap,btv,buf, | 3070 | retval = bttv_prepare_buffer(&fh->cap,btv,buf, |
@@ -2613,54 +3111,17 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, | |||
2613 | } | 3111 | } |
2614 | 3112 | ||
2615 | case VIDIOCGVBIFMT: | 3113 | case VIDIOCGVBIFMT: |
2616 | { | ||
2617 | struct vbi_format *fmt = (void *) arg; | ||
2618 | struct v4l2_format fmt2; | ||
2619 | |||
2620 | if (fh->type != V4L2_BUF_TYPE_VBI_CAPTURE) { | 3114 | if (fh->type != V4L2_BUF_TYPE_VBI_CAPTURE) { |
2621 | retval = bttv_switch_type(fh,V4L2_BUF_TYPE_VBI_CAPTURE); | 3115 | retval = bttv_switch_type(fh,V4L2_BUF_TYPE_VBI_CAPTURE); |
2622 | if (0 != retval) | 3116 | if (0 != retval) |
2623 | return retval; | 3117 | return retval; |
2624 | } | 3118 | } |
2625 | bttv_vbi_get_fmt(fh, &fmt2); | ||
2626 | |||
2627 | memset(fmt,0,sizeof(*fmt)); | ||
2628 | fmt->sampling_rate = fmt2.fmt.vbi.sampling_rate; | ||
2629 | fmt->samples_per_line = fmt2.fmt.vbi.samples_per_line; | ||
2630 | fmt->sample_format = VIDEO_PALETTE_RAW; | ||
2631 | fmt->start[0] = fmt2.fmt.vbi.start[0]; | ||
2632 | fmt->count[0] = fmt2.fmt.vbi.count[0]; | ||
2633 | fmt->start[1] = fmt2.fmt.vbi.start[1]; | ||
2634 | fmt->count[1] = fmt2.fmt.vbi.count[1]; | ||
2635 | if (fmt2.fmt.vbi.flags & V4L2_VBI_UNSYNC) | ||
2636 | fmt->flags |= VBI_UNSYNC; | ||
2637 | if (fmt2.fmt.vbi.flags & V4L2_VBI_INTERLACED) | ||
2638 | fmt->flags |= VBI_INTERLACED; | ||
2639 | return 0; | ||
2640 | } | ||
2641 | case VIDIOCSVBIFMT: | ||
2642 | { | ||
2643 | struct vbi_format *fmt = (void *) arg; | ||
2644 | struct v4l2_format fmt2; | ||
2645 | 3119 | ||
2646 | retval = bttv_switch_type(fh,V4L2_BUF_TYPE_VBI_CAPTURE); | 3120 | /* fall through */ |
2647 | if (0 != retval) | ||
2648 | return retval; | ||
2649 | bttv_vbi_get_fmt(fh, &fmt2); | ||
2650 | |||
2651 | if (fmt->sampling_rate != fmt2.fmt.vbi.sampling_rate || | ||
2652 | fmt->samples_per_line != fmt2.fmt.vbi.samples_per_line || | ||
2653 | fmt->sample_format != VIDEO_PALETTE_RAW || | ||
2654 | fmt->start[0] != fmt2.fmt.vbi.start[0] || | ||
2655 | fmt->start[1] != fmt2.fmt.vbi.start[1] || | ||
2656 | fmt->count[0] != fmt->count[1] || | ||
2657 | fmt->count[0] < 1 || | ||
2658 | fmt->count[0] > 32 /* VBI_MAXLINES */) | ||
2659 | return -EINVAL; | ||
2660 | 3121 | ||
2661 | bttv_vbi_setlines(fh,btv,fmt->count[0]); | 3122 | case VIDIOCSVBIFMT: |
2662 | return 0; | 3123 | return v4l_compat_translate_ioctl(inode, file, cmd, |
2663 | } | 3124 | arg, bttv_do_ioctl); |
2664 | 3125 | ||
2665 | case BTTV_VERSION: | 3126 | case BTTV_VERSION: |
2666 | case VIDIOCGFREQ: | 3127 | case VIDIOCGFREQ: |
@@ -2753,7 +3214,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, | |||
2753 | case VIDIOC_TRY_FMT: | 3214 | case VIDIOC_TRY_FMT: |
2754 | { | 3215 | { |
2755 | struct v4l2_format *f = arg; | 3216 | struct v4l2_format *f = arg; |
2756 | return bttv_try_fmt(fh,btv,f); | 3217 | return bttv_try_fmt(fh,btv,f, /* adjust_crop */ 0); |
2757 | } | 3218 | } |
2758 | case VIDIOC_G_FMT: | 3219 | case VIDIOC_G_FMT: |
2759 | { | 3220 | { |
@@ -2792,16 +3253,23 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, | |||
2792 | if (0 == (fmt->flags & FORMAT_FLAGS_PACKED)) | 3253 | if (0 == (fmt->flags & FORMAT_FLAGS_PACKED)) |
2793 | return -EINVAL; | 3254 | return -EINVAL; |
2794 | 3255 | ||
2795 | mutex_lock(&fh->cap.lock); | ||
2796 | retval = -EINVAL; | 3256 | retval = -EINVAL; |
2797 | if (fb->flags & V4L2_FBUF_FLAG_OVERLAY) { | 3257 | if (fb->flags & V4L2_FBUF_FLAG_OVERLAY) { |
2798 | if (fb->fmt.width > bttv_tvnorms[btv->tvnorm].swidth) | 3258 | __s32 width = fb->fmt.width; |
2799 | goto fh_unlock_and_return; | 3259 | __s32 height = fb->fmt.height; |
2800 | if (fb->fmt.height > bttv_tvnorms[btv->tvnorm].sheight) | 3260 | |
2801 | goto fh_unlock_and_return; | 3261 | retval = limit_scaled_size(fh, &width, &height, |
3262 | V4L2_FIELD_INTERLACED, | ||
3263 | /* width_mask */ ~3, | ||
3264 | /* width_bias */ 2, | ||
3265 | /* adjust_size */ 0, | ||
3266 | /* adjust_crop */ 0); | ||
3267 | if (0 != retval) | ||
3268 | return retval; | ||
2802 | } | 3269 | } |
2803 | 3270 | ||
2804 | /* ok, accept it */ | 3271 | /* ok, accept it */ |
3272 | mutex_lock(&fh->cap.lock); | ||
2805 | btv->fbuf.base = fb->base; | 3273 | btv->fbuf.base = fb->base; |
2806 | btv->fbuf.fmt.width = fb->fmt.width; | 3274 | btv->fbuf.fmt.width = fb->fmt.width; |
2807 | btv->fbuf.fmt.height = fb->fmt.height; | 3275 | btv->fbuf.fmt.height = fb->fmt.height; |
@@ -2828,6 +3296,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, | |||
2828 | struct bttv_buffer *new; | 3296 | struct bttv_buffer *new; |
2829 | 3297 | ||
2830 | new = videobuf_alloc(sizeof(*new)); | 3298 | new = videobuf_alloc(sizeof(*new)); |
3299 | new->crop = btv->crop[!!fh->do_crop].rect; | ||
2831 | bttv_overlay_risc(btv,&fh->ov,fh->ovfmt,new); | 3300 | bttv_overlay_risc(btv,&fh->ov,fh->ovfmt,new); |
2832 | retval = bttv_switch_overlay(btv,fh,new); | 3301 | retval = bttv_switch_overlay(btv,fh,new); |
2833 | } | 3302 | } |
@@ -2843,7 +3312,13 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, | |||
2843 | return videobuf_querybuf(bttv_queue(fh),arg); | 3312 | return videobuf_querybuf(bttv_queue(fh),arg); |
2844 | 3313 | ||
2845 | case VIDIOC_QBUF: | 3314 | case VIDIOC_QBUF: |
3315 | { | ||
3316 | int res = bttv_resource(fh); | ||
3317 | |||
3318 | if (!check_alloc_btres(btv, fh, res)) | ||
3319 | return -EBUSY; | ||
2846 | return videobuf_qbuf(bttv_queue(fh),arg); | 3320 | return videobuf_qbuf(bttv_queue(fh),arg); |
3321 | } | ||
2847 | 3322 | ||
2848 | case VIDIOC_DQBUF: | 3323 | case VIDIOC_DQBUF: |
2849 | return videobuf_dqbuf(bttv_queue(fh),arg, | 3324 | return videobuf_dqbuf(bttv_queue(fh),arg, |
@@ -2942,6 +3417,122 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, | |||
2942 | return v4l2_prio_change(&btv->prio, &fh->prio, *prio); | 3417 | return v4l2_prio_change(&btv->prio, &fh->prio, *prio); |
2943 | } | 3418 | } |
2944 | 3419 | ||
3420 | case VIDIOC_CROPCAP: | ||
3421 | { | ||
3422 | struct v4l2_cropcap *cap = arg; | ||
3423 | enum v4l2_buf_type type; | ||
3424 | |||
3425 | type = cap->type; | ||
3426 | |||
3427 | if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE && | ||
3428 | type != V4L2_BUF_TYPE_VIDEO_OVERLAY) | ||
3429 | return -EINVAL; | ||
3430 | |||
3431 | *cap = bttv_tvnorms[btv->tvnorm].cropcap; | ||
3432 | cap->type = type; | ||
3433 | |||
3434 | return 0; | ||
3435 | } | ||
3436 | case VIDIOC_G_CROP: | ||
3437 | { | ||
3438 | struct v4l2_crop * crop = arg; | ||
3439 | |||
3440 | if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && | ||
3441 | crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY) | ||
3442 | return -EINVAL; | ||
3443 | |||
3444 | /* No fh->do_crop = 1; because btv->crop[1] may be | ||
3445 | inconsistent with fh->width or fh->height and apps | ||
3446 | do not expect a change here. */ | ||
3447 | |||
3448 | crop->c = btv->crop[!!fh->do_crop].rect; | ||
3449 | |||
3450 | return 0; | ||
3451 | } | ||
3452 | case VIDIOC_S_CROP: | ||
3453 | { | ||
3454 | struct v4l2_crop *crop = arg; | ||
3455 | const struct v4l2_rect *b; | ||
3456 | struct bttv_crop c; | ||
3457 | __s32 b_left; | ||
3458 | __s32 b_top; | ||
3459 | __s32 b_right; | ||
3460 | __s32 b_bottom; | ||
3461 | |||
3462 | if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && | ||
3463 | crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY) | ||
3464 | return -EINVAL; | ||
3465 | |||
3466 | retval = v4l2_prio_check(&btv->prio,&fh->prio); | ||
3467 | if (0 != retval) | ||
3468 | return retval; | ||
3469 | |||
3470 | /* Make sure tvnorm, vbi_end and the current cropping | ||
3471 | parameters remain consistent until we're done. Note | ||
3472 | read() may change vbi_end in check_alloc_btres(). */ | ||
3473 | mutex_lock(&btv->lock); | ||
3474 | |||
3475 | retval = -EBUSY; | ||
3476 | |||
3477 | if (locked_btres(fh->btv, VIDEO_RESOURCES)) | ||
3478 | goto btv_unlock_and_return; | ||
3479 | |||
3480 | b = &bttv_tvnorms[btv->tvnorm].cropcap.bounds; | ||
3481 | |||
3482 | b_left = b->left; | ||
3483 | b_right = b_left + b->width; | ||
3484 | b_bottom = b->top + b->height; | ||
3485 | |||
3486 | b_top = max(b->top, btv->vbi_end); | ||
3487 | if (b_top + 32 >= b_bottom) | ||
3488 | goto btv_unlock_and_return; | ||
3489 | |||
3490 | /* Min. scaled size 48 x 32. */ | ||
3491 | c.rect.left = clamp(crop->c.left, b_left, b_right - 48); | ||
3492 | c.rect.left = min(c.rect.left, (__s32) MAX_HDELAY); | ||
3493 | |||
3494 | c.rect.width = clamp(crop->c.width, | ||
3495 | 48, b_right - c.rect.left); | ||
3496 | |||
3497 | c.rect.top = clamp(crop->c.top, b_top, b_bottom - 32); | ||
3498 | /* Top and height must be a multiple of two. */ | ||
3499 | c.rect.top = (c.rect.top + 1) & ~1; | ||
3500 | |||
3501 | c.rect.height = clamp(crop->c.height, | ||
3502 | 32, b_bottom - c.rect.top); | ||
3503 | c.rect.height = (c.rect.height + 1) & ~1; | ||
3504 | |||
3505 | bttv_crop_calc_limits(&c); | ||
3506 | |||
3507 | btv->crop[1] = c; | ||
3508 | |||
3509 | mutex_unlock(&btv->lock); | ||
3510 | |||
3511 | fh->do_crop = 1; | ||
3512 | |||
3513 | mutex_lock(&fh->cap.lock); | ||
3514 | |||
3515 | if (fh->width < c.min_scaled_width) { | ||
3516 | fh->width = c.min_scaled_width; | ||
3517 | btv->init.width = c.min_scaled_width; | ||
3518 | } else if (fh->width > c.max_scaled_width) { | ||
3519 | fh->width = c.max_scaled_width; | ||
3520 | btv->init.width = c.max_scaled_width; | ||
3521 | } | ||
3522 | |||
3523 | if (fh->height < c.min_scaled_height) { | ||
3524 | fh->height = c.min_scaled_height; | ||
3525 | btv->init.height = c.min_scaled_height; | ||
3526 | } else if (fh->height > c.max_scaled_height) { | ||
3527 | fh->height = c.max_scaled_height; | ||
3528 | btv->init.height = c.max_scaled_height; | ||
3529 | } | ||
3530 | |||
3531 | mutex_unlock(&fh->cap.lock); | ||
3532 | |||
3533 | return 0; | ||
3534 | } | ||
3535 | |||
2945 | case VIDIOC_ENUMSTD: | 3536 | case VIDIOC_ENUMSTD: |
2946 | case VIDIOC_G_STD: | 3537 | case VIDIOC_G_STD: |
2947 | case VIDIOC_S_STD: | 3538 | case VIDIOC_S_STD: |
@@ -2963,6 +3554,10 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, | |||
2963 | fh_unlock_and_return: | 3554 | fh_unlock_and_return: |
2964 | mutex_unlock(&fh->cap.lock); | 3555 | mutex_unlock(&fh->cap.lock); |
2965 | return retval; | 3556 | return retval; |
3557 | |||
3558 | btv_unlock_and_return: | ||
3559 | mutex_unlock(&btv->lock); | ||
3560 | return retval; | ||
2966 | } | 3561 | } |
2967 | 3562 | ||
2968 | static int bttv_ioctl(struct inode *inode, struct file *file, | 3563 | static int bttv_ioctl(struct inode *inode, struct file *file, |
@@ -2972,8 +3567,26 @@ static int bttv_ioctl(struct inode *inode, struct file *file, | |||
2972 | 3567 | ||
2973 | switch (cmd) { | 3568 | switch (cmd) { |
2974 | case BTTV_VBISIZE: | 3569 | case BTTV_VBISIZE: |
3570 | { | ||
3571 | const struct bttv_tvnorm *tvnorm; | ||
3572 | |||
3573 | tvnorm = fh->vbi_fmt.tvnorm; | ||
3574 | |||
3575 | if (fh->vbi_fmt.fmt.start[0] != tvnorm->vbistart[0] || | ||
3576 | fh->vbi_fmt.fmt.start[1] != tvnorm->vbistart[1] || | ||
3577 | fh->vbi_fmt.fmt.count[0] != fh->vbi_fmt.fmt.count[1]) { | ||
3578 | /* BTTV_VBISIZE cannot express these parameters, | ||
3579 | however open() resets the paramters to defaults | ||
3580 | and apps shouldn't call BTTV_VBISIZE after | ||
3581 | VIDIOC_S_FMT. */ | ||
3582 | return -EINVAL; | ||
3583 | } | ||
3584 | |||
2975 | bttv_switch_type(fh,V4L2_BUF_TYPE_VBI_CAPTURE); | 3585 | bttv_switch_type(fh,V4L2_BUF_TYPE_VBI_CAPTURE); |
2976 | return fh->lines * 2 * 2048; | 3586 | return (fh->vbi_fmt.fmt.count[0] * 2 |
3587 | * fh->vbi_fmt.fmt.samples_per_line); | ||
3588 | } | ||
3589 | |||
2977 | default: | 3590 | default: |
2978 | return video_usercopy(inode, file, cmd, arg, bttv_do_ioctl); | 3591 | return video_usercopy(inode, file, cmd, arg, bttv_do_ioctl); |
2979 | } | 3592 | } |
@@ -2992,10 +3605,14 @@ static ssize_t bttv_read(struct file *file, char __user *data, | |||
2992 | 3605 | ||
2993 | switch (fh->type) { | 3606 | switch (fh->type) { |
2994 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | 3607 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: |
2995 | if (locked_btres(fh->btv,RESOURCE_VIDEO)) | 3608 | if (!check_alloc_btres(fh->btv, fh, RESOURCE_VIDEO_READ)) { |
3609 | /* VIDEO_READ in use by another fh, | ||
3610 | or VIDEO_STREAM by any fh. */ | ||
2996 | return -EBUSY; | 3611 | return -EBUSY; |
3612 | } | ||
2997 | retval = videobuf_read_one(&fh->cap, data, count, ppos, | 3613 | retval = videobuf_read_one(&fh->cap, data, count, ppos, |
2998 | file->f_flags & O_NONBLOCK); | 3614 | file->f_flags & O_NONBLOCK); |
3615 | free_btres(fh->btv, fh, RESOURCE_VIDEO_READ); | ||
2999 | break; | 3616 | break; |
3000 | case V4L2_BUF_TYPE_VBI_CAPTURE: | 3617 | case V4L2_BUF_TYPE_VBI_CAPTURE: |
3001 | if (!check_alloc_btres(fh->btv,fh,RESOURCE_VBI)) | 3618 | if (!check_alloc_btres(fh->btv,fh,RESOURCE_VBI)) |
@@ -3021,7 +3638,7 @@ static unsigned int bttv_poll(struct file *file, poll_table *wait) | |||
3021 | return videobuf_poll_stream(file, &fh->vbi, wait); | 3638 | return videobuf_poll_stream(file, &fh->vbi, wait); |
3022 | } | 3639 | } |
3023 | 3640 | ||
3024 | if (check_btres(fh,RESOURCE_VIDEO)) { | 3641 | if (check_btres(fh,RESOURCE_VIDEO_STREAM)) { |
3025 | /* streaming capture */ | 3642 | /* streaming capture */ |
3026 | if (list_empty(&fh->cap.stream)) | 3643 | if (list_empty(&fh->cap.stream)) |
3027 | return POLLERR; | 3644 | return POLLERR; |
@@ -3031,7 +3648,7 @@ static unsigned int bttv_poll(struct file *file, poll_table *wait) | |||
3031 | mutex_lock(&fh->cap.lock); | 3648 | mutex_lock(&fh->cap.lock); |
3032 | if (NULL == fh->cap.read_buf) { | 3649 | if (NULL == fh->cap.read_buf) { |
3033 | /* need to capture a new frame */ | 3650 | /* need to capture a new frame */ |
3034 | if (locked_btres(fh->btv,RESOURCE_VIDEO)) { | 3651 | if (locked_btres(fh->btv,RESOURCE_VIDEO_STREAM)) { |
3035 | mutex_unlock(&fh->cap.lock); | 3652 | mutex_unlock(&fh->cap.lock); |
3036 | return POLLERR; | 3653 | return POLLERR; |
3037 | } | 3654 | } |
@@ -3117,8 +3734,23 @@ static int bttv_open(struct inode *inode, struct file *file) | |||
3117 | i2c_vidiocschan(btv); | 3734 | i2c_vidiocschan(btv); |
3118 | 3735 | ||
3119 | btv->users++; | 3736 | btv->users++; |
3120 | if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) | 3737 | |
3121 | bttv_vbi_setlines(fh,btv,16); | 3738 | /* The V4L2 spec requires one global set of cropping parameters |
3739 | which only change on request. These are stored in btv->crop[1]. | ||
3740 | However for compatibility with V4L apps and cropping unaware | ||
3741 | V4L2 apps we now reset the cropping parameters as seen through | ||
3742 | this fh, which is to say VIDIOC_G_CROP and scaling limit checks | ||
3743 | will use btv->crop[0], the default cropping parameters for the | ||
3744 | current video standard, and VIDIOC_S_FMT will not implicitely | ||
3745 | change the cropping parameters until VIDIOC_S_CROP has been | ||
3746 | called. */ | ||
3747 | fh->do_crop = !reset_crop; /* module parameter */ | ||
3748 | |||
3749 | /* Likewise there should be one global set of VBI capture | ||
3750 | parameters, but for compatibility with V4L apps and earlier | ||
3751 | driver versions each fh has its own parameters. */ | ||
3752 | bttv_vbi_fmt_reset(&fh->vbi_fmt, btv->tvnorm); | ||
3753 | |||
3122 | bttv_field_count(btv); | 3754 | bttv_field_count(btv); |
3123 | return 0; | 3755 | return 0; |
3124 | } | 3756 | } |
@@ -3133,14 +3765,17 @@ static int bttv_release(struct inode *inode, struct file *file) | |||
3133 | bttv_switch_overlay(btv,fh,NULL); | 3765 | bttv_switch_overlay(btv,fh,NULL); |
3134 | 3766 | ||
3135 | /* stop video capture */ | 3767 | /* stop video capture */ |
3136 | if (check_btres(fh, RESOURCE_VIDEO)) { | 3768 | if (check_btres(fh, RESOURCE_VIDEO_STREAM)) { |
3137 | videobuf_streamoff(&fh->cap); | 3769 | videobuf_streamoff(&fh->cap); |
3138 | free_btres(btv,fh,RESOURCE_VIDEO); | 3770 | free_btres(btv,fh,RESOURCE_VIDEO_STREAM); |
3139 | } | 3771 | } |
3140 | if (fh->cap.read_buf) { | 3772 | if (fh->cap.read_buf) { |
3141 | buffer_release(&fh->cap,fh->cap.read_buf); | 3773 | buffer_release(&fh->cap,fh->cap.read_buf); |
3142 | kfree(fh->cap.read_buf); | 3774 | kfree(fh->cap.read_buf); |
3143 | } | 3775 | } |
3776 | if (check_btres(fh, RESOURCE_VIDEO_READ)) { | ||
3777 | free_btres(btv, fh, RESOURCE_VIDEO_READ); | ||
3778 | } | ||
3144 | 3779 | ||
3145 | /* stop vbi capture */ | 3780 | /* stop vbi capture */ |
3146 | if (check_btres(fh, RESOURCE_VBI)) { | 3781 | if (check_btres(fh, RESOURCE_VBI)) { |
@@ -3997,7 +4632,6 @@ static int __devinit bttv_probe(struct pci_dev *dev, | |||
3997 | 4632 | ||
3998 | /* initialize structs / fill in defaults */ | 4633 | /* initialize structs / fill in defaults */ |
3999 | mutex_init(&btv->lock); | 4634 | mutex_init(&btv->lock); |
4000 | mutex_init(&btv->reslock); | ||
4001 | spin_lock_init(&btv->s_lock); | 4635 | spin_lock_init(&btv->s_lock); |
4002 | spin_lock_init(&btv->gpio_lock); | 4636 | spin_lock_init(&btv->gpio_lock); |
4003 | init_waitqueue_head(&btv->gpioq); | 4637 | init_waitqueue_head(&btv->gpioq); |
@@ -4095,7 +4729,6 @@ static int __devinit bttv_probe(struct pci_dev *dev, | |||
4095 | btv->init.fmt = format_by_palette(VIDEO_PALETTE_RGB24); | 4729 | btv->init.fmt = format_by_palette(VIDEO_PALETTE_RGB24); |
4096 | btv->init.width = 320; | 4730 | btv->init.width = 320; |
4097 | btv->init.height = 240; | 4731 | btv->init.height = 240; |
4098 | btv->init.lines = 16; | ||
4099 | btv->input = 0; | 4732 | btv->input = 0; |
4100 | 4733 | ||
4101 | /* initialize hardware */ | 4734 | /* initialize hardware */ |
@@ -4130,6 +4763,10 @@ static int __devinit bttv_probe(struct pci_dev *dev, | |||
4130 | bt848_sat(btv,32768); | 4763 | bt848_sat(btv,32768); |
4131 | audio_mute(btv, 1); | 4764 | audio_mute(btv, 1); |
4132 | set_input(btv,0); | 4765 | set_input(btv,0); |
4766 | bttv_crop_reset(&btv->crop[0], btv->tvnorm); | ||
4767 | btv->crop[1] = btv->crop[0]; /* current = default */ | ||
4768 | disclaim_vbi_lines(btv); | ||
4769 | disclaim_video_lines(btv); | ||
4133 | } | 4770 | } |
4134 | 4771 | ||
4135 | /* add subdevices */ | 4772 | /* add subdevices */ |
diff --git a/drivers/media/video/bt8xx/bttv-input.c b/drivers/media/video/bt8xx/bttv-input.c index cbc012f71f52..6f74c8042bc3 100644 --- a/drivers/media/video/bt8xx/bttv-input.c +++ b/drivers/media/video/bt8xx/bttv-input.c | |||
@@ -36,13 +36,18 @@ module_param(repeat_delay, int, 0644); | |||
36 | static int repeat_period = 33; | 36 | static int repeat_period = 33; |
37 | module_param(repeat_period, int, 0644); | 37 | module_param(repeat_period, int, 0644); |
38 | 38 | ||
39 | static int ir_rc5_remote_gap = 885; | ||
40 | module_param(ir_rc5_remote_gap, int, 0644); | ||
41 | static int ir_rc5_key_timeout = 200; | ||
42 | module_param(ir_rc5_key_timeout, int, 0644); | ||
43 | |||
39 | #define DEVNAME "bttv-input" | 44 | #define DEVNAME "bttv-input" |
40 | 45 | ||
41 | /* ---------------------------------------------------------------------- */ | 46 | /* ---------------------------------------------------------------------- */ |
42 | 47 | ||
43 | static void ir_handle_key(struct bttv *btv) | 48 | static void ir_handle_key(struct bttv *btv) |
44 | { | 49 | { |
45 | struct bttv_ir *ir = btv->remote; | 50 | struct card_ir *ir = btv->remote; |
46 | u32 gpio,data; | 51 | u32 gpio,data; |
47 | 52 | ||
48 | /* read gpio value */ | 53 | /* read gpio value */ |
@@ -72,7 +77,7 @@ static void ir_handle_key(struct bttv *btv) | |||
72 | 77 | ||
73 | void bttv_input_irq(struct bttv *btv) | 78 | void bttv_input_irq(struct bttv *btv) |
74 | { | 79 | { |
75 | struct bttv_ir *ir = btv->remote; | 80 | struct card_ir *ir = btv->remote; |
76 | 81 | ||
77 | if (!ir->polling) | 82 | if (!ir->polling) |
78 | ir_handle_key(btv); | 83 | ir_handle_key(btv); |
@@ -81,65 +86,21 @@ void bttv_input_irq(struct bttv *btv) | |||
81 | static void bttv_input_timer(unsigned long data) | 86 | static void bttv_input_timer(unsigned long data) |
82 | { | 87 | { |
83 | struct bttv *btv = (struct bttv*)data; | 88 | struct bttv *btv = (struct bttv*)data; |
84 | struct bttv_ir *ir = btv->remote; | 89 | struct card_ir *ir = btv->remote; |
85 | unsigned long timeout; | ||
86 | 90 | ||
87 | ir_handle_key(btv); | 91 | ir_handle_key(btv); |
88 | timeout = jiffies + (ir->polling * HZ / 1000); | 92 | mod_timer(&ir->timer, jiffies + msecs_to_jiffies(ir->polling)); |
89 | mod_timer(&ir->timer, timeout); | ||
90 | } | 93 | } |
91 | 94 | ||
92 | /* ---------------------------------------------------------------*/ | 95 | /* ---------------------------------------------------------------*/ |
93 | 96 | ||
94 | static int rc5_remote_gap = 885; | ||
95 | module_param(rc5_remote_gap, int, 0644); | ||
96 | static int rc5_key_timeout = 200; | ||
97 | module_param(rc5_key_timeout, int, 0644); | ||
98 | |||
99 | #define RC5_START(x) (((x)>>12)&3) | ||
100 | #define RC5_TOGGLE(x) (((x)>>11)&1) | ||
101 | #define RC5_ADDR(x) (((x)>>6)&31) | ||
102 | #define RC5_INSTR(x) ((x)&63) | ||
103 | |||
104 | /* decode raw bit pattern to RC5 code */ | ||
105 | static u32 rc5_decode(unsigned int code) | ||
106 | { | ||
107 | unsigned int org_code = code; | ||
108 | unsigned int pair; | ||
109 | unsigned int rc5 = 0; | ||
110 | int i; | ||
111 | |||
112 | code = (code << 1) | 1; | ||
113 | for (i = 0; i < 14; ++i) { | ||
114 | pair = code & 0x3; | ||
115 | code >>= 2; | ||
116 | |||
117 | rc5 <<= 1; | ||
118 | switch (pair) { | ||
119 | case 0: | ||
120 | case 2: | ||
121 | break; | ||
122 | case 1: | ||
123 | rc5 |= 1; | ||
124 | break; | ||
125 | case 3: | ||
126 | dprintk(KERN_WARNING "bad code: %x\n", org_code); | ||
127 | return 0; | ||
128 | } | ||
129 | } | ||
130 | dprintk(KERN_WARNING "code=%x, rc5=%x, start=%x, toggle=%x, address=%x, " | ||
131 | "instr=%x\n", rc5, org_code, RC5_START(rc5), | ||
132 | RC5_TOGGLE(rc5), RC5_ADDR(rc5), RC5_INSTR(rc5)); | ||
133 | return rc5; | ||
134 | } | ||
135 | |||
136 | static int bttv_rc5_irq(struct bttv *btv) | 97 | static int bttv_rc5_irq(struct bttv *btv) |
137 | { | 98 | { |
138 | struct bttv_ir *ir = btv->remote; | 99 | struct card_ir *ir = btv->remote; |
139 | struct timeval tv; | 100 | struct timeval tv; |
140 | u32 gpio; | 101 | u32 gpio; |
141 | u32 gap; | 102 | u32 gap; |
142 | unsigned long current_jiffies, timeout; | 103 | unsigned long current_jiffies; |
143 | 104 | ||
144 | /* read gpio port */ | 105 | /* read gpio port */ |
145 | gpio = bttv_gpio_read(&btv->c); | 106 | gpio = bttv_gpio_read(&btv->c); |
@@ -165,8 +126,8 @@ static int bttv_rc5_irq(struct bttv *btv) | |||
165 | /* only if in the code (otherwise spurious IRQ or timer | 126 | /* only if in the code (otherwise spurious IRQ or timer |
166 | late) */ | 127 | late) */ |
167 | if (ir->last_bit < 28) { | 128 | if (ir->last_bit < 28) { |
168 | ir->last_bit = (gap - rc5_remote_gap / 2) / | 129 | ir->last_bit = (gap - ir_rc5_remote_gap / 2) / |
169 | rc5_remote_gap; | 130 | ir_rc5_remote_gap; |
170 | ir->code |= 1 << ir->last_bit; | 131 | ir->code |= 1 << ir->last_bit; |
171 | } | 132 | } |
172 | /* starting new code */ | 133 | /* starting new code */ |
@@ -176,8 +137,8 @@ static int bttv_rc5_irq(struct bttv *btv) | |||
176 | ir->base_time = tv; | 137 | ir->base_time = tv; |
177 | ir->last_bit = 0; | 138 | ir->last_bit = 0; |
178 | 139 | ||
179 | timeout = current_jiffies + (500 + 30 * HZ) / 1000; | 140 | mod_timer(&ir->timer_end, |
180 | mod_timer(&ir->timer_end, timeout); | 141 | current_jiffies + msecs_to_jiffies(30)); |
181 | } | 142 | } |
182 | 143 | ||
183 | /* toggle GPIO pin 4 to reset the irq */ | 144 | /* toggle GPIO pin 4 to reset the irq */ |
@@ -186,96 +147,28 @@ static int bttv_rc5_irq(struct bttv *btv) | |||
186 | return 1; | 147 | return 1; |
187 | } | 148 | } |
188 | 149 | ||
189 | |||
190 | static void bttv_rc5_timer_end(unsigned long data) | ||
191 | { | ||
192 | struct bttv_ir *ir = (struct bttv_ir *)data; | ||
193 | struct timeval tv; | ||
194 | unsigned long current_jiffies, timeout; | ||
195 | u32 gap; | ||
196 | |||
197 | /* get time */ | ||
198 | current_jiffies = jiffies; | ||
199 | do_gettimeofday(&tv); | ||
200 | |||
201 | /* avoid overflow with gap >1s */ | ||
202 | if (tv.tv_sec - ir->base_time.tv_sec > 1) { | ||
203 | gap = 200000; | ||
204 | } else { | ||
205 | gap = 1000000 * (tv.tv_sec - ir->base_time.tv_sec) + | ||
206 | tv.tv_usec - ir->base_time.tv_usec; | ||
207 | } | ||
208 | |||
209 | /* Allow some timmer jitter (RC5 is ~24ms anyway so this is ok) */ | ||
210 | if (gap < 28000) { | ||
211 | dprintk(KERN_WARNING "spurious timer_end\n"); | ||
212 | return; | ||
213 | } | ||
214 | |||
215 | ir->active = 0; | ||
216 | if (ir->last_bit < 20) { | ||
217 | /* ignore spurious codes (caused by light/other remotes) */ | ||
218 | dprintk(KERN_WARNING "short code: %x\n", ir->code); | ||
219 | } else { | ||
220 | u32 rc5 = rc5_decode(ir->code); | ||
221 | |||
222 | /* two start bits? */ | ||
223 | if (RC5_START(rc5) != 3) { | ||
224 | dprintk(KERN_WARNING "rc5 start bits invalid: %u\n", RC5_START(rc5)); | ||
225 | |||
226 | /* right address? */ | ||
227 | } else if (RC5_ADDR(rc5) == 0x0) { | ||
228 | u32 toggle = RC5_TOGGLE(rc5); | ||
229 | u32 instr = RC5_INSTR(rc5); | ||
230 | |||
231 | /* Good code, decide if repeat/repress */ | ||
232 | if (toggle != RC5_TOGGLE(ir->last_rc5) || | ||
233 | instr != RC5_INSTR(ir->last_rc5)) { | ||
234 | dprintk(KERN_WARNING "instruction %x, toggle %x\n", instr, | ||
235 | toggle); | ||
236 | ir_input_nokey(ir->dev, &ir->ir); | ||
237 | ir_input_keydown(ir->dev, &ir->ir, instr, | ||
238 | instr); | ||
239 | } | ||
240 | |||
241 | /* Set/reset key-up timer */ | ||
242 | timeout = current_jiffies + (500 + rc5_key_timeout | ||
243 | * HZ) / 1000; | ||
244 | mod_timer(&ir->timer_keyup, timeout); | ||
245 | |||
246 | /* Save code for repeat test */ | ||
247 | ir->last_rc5 = rc5; | ||
248 | } | ||
249 | } | ||
250 | } | ||
251 | |||
252 | static void bttv_rc5_timer_keyup(unsigned long data) | ||
253 | { | ||
254 | struct bttv_ir *ir = (struct bttv_ir *)data; | ||
255 | |||
256 | dprintk(KERN_DEBUG "key released\n"); | ||
257 | ir_input_nokey(ir->dev, &ir->ir); | ||
258 | } | ||
259 | |||
260 | /* ---------------------------------------------------------------------- */ | 150 | /* ---------------------------------------------------------------------- */ |
261 | 151 | ||
262 | static void bttv_ir_start(struct bttv *btv, struct bttv_ir *ir) | 152 | static void bttv_ir_start(struct bttv *btv, struct card_ir *ir) |
263 | { | 153 | { |
264 | if (ir->polling) { | 154 | if (ir->polling) { |
265 | init_timer(&ir->timer); | 155 | setup_timer(&ir->timer, bttv_input_timer, (unsigned long)btv); |
266 | ir->timer.function = bttv_input_timer; | ||
267 | ir->timer.data = (unsigned long)btv; | ||
268 | ir->timer.expires = jiffies + HZ; | 156 | ir->timer.expires = jiffies + HZ; |
269 | add_timer(&ir->timer); | 157 | add_timer(&ir->timer); |
270 | } else if (ir->rc5_gpio) { | 158 | } else if (ir->rc5_gpio) { |
271 | /* set timer_end for code completion */ | 159 | /* set timer_end for code completion */ |
272 | init_timer(&ir->timer_end); | 160 | init_timer(&ir->timer_end); |
273 | ir->timer_end.function = bttv_rc5_timer_end; | 161 | ir->timer_end.function = ir_rc5_timer_end; |
274 | ir->timer_end.data = (unsigned long)ir; | 162 | ir->timer_end.data = (unsigned long)ir; |
275 | 163 | ||
276 | init_timer(&ir->timer_keyup); | 164 | init_timer(&ir->timer_keyup); |
277 | ir->timer_keyup.function = bttv_rc5_timer_keyup; | 165 | ir->timer_keyup.function = ir_rc5_timer_keyup; |
278 | ir->timer_keyup.data = (unsigned long)ir; | 166 | ir->timer_keyup.data = (unsigned long)ir; |
167 | ir->shift_by = 1; | ||
168 | ir->start = 3; | ||
169 | ir->addr = 0x0; | ||
170 | ir->rc5_key_timeout = ir_rc5_key_timeout; | ||
171 | ir->rc5_remote_gap = ir_rc5_remote_gap; | ||
279 | } | 172 | } |
280 | } | 173 | } |
281 | 174 | ||
@@ -299,7 +192,7 @@ static void bttv_ir_stop(struct bttv *btv) | |||
299 | 192 | ||
300 | int bttv_input_init(struct bttv *btv) | 193 | int bttv_input_init(struct bttv *btv) |
301 | { | 194 | { |
302 | struct bttv_ir *ir; | 195 | struct card_ir *ir; |
303 | IR_KEYTAB_TYPE *ir_codes = NULL; | 196 | IR_KEYTAB_TYPE *ir_codes = NULL; |
304 | struct input_dev *input_dev; | 197 | struct input_dev *input_dev; |
305 | int ir_type = IR_TYPE_OTHER; | 198 | int ir_type = IR_TYPE_OTHER; |
diff --git a/drivers/media/video/bt8xx/bttv-risc.c b/drivers/media/video/bt8xx/bttv-risc.c index afcfe71e3792..e7104d9cb4bd 100644 --- a/drivers/media/video/bt8xx/bttv-risc.c +++ b/drivers/media/video/bt8xx/bttv-risc.c | |||
@@ -43,7 +43,8 @@ int | |||
43 | bttv_risc_packed(struct bttv *btv, struct btcx_riscmem *risc, | 43 | bttv_risc_packed(struct bttv *btv, struct btcx_riscmem *risc, |
44 | struct scatterlist *sglist, | 44 | struct scatterlist *sglist, |
45 | unsigned int offset, unsigned int bpl, | 45 | unsigned int offset, unsigned int bpl, |
46 | unsigned int padding, unsigned int lines) | 46 | unsigned int padding, unsigned int skip_lines, |
47 | unsigned int store_lines) | ||
47 | { | 48 | { |
48 | u32 instructions,line,todo; | 49 | u32 instructions,line,todo; |
49 | struct scatterlist *sg; | 50 | struct scatterlist *sg; |
@@ -54,9 +55,11 @@ bttv_risc_packed(struct bttv *btv, struct btcx_riscmem *risc, | |||
54 | one write per scan line + sync + jump (all 2 dwords). padding | 55 | one write per scan line + sync + jump (all 2 dwords). padding |
55 | can cause next bpl to start close to a page border. First DMA | 56 | can cause next bpl to start close to a page border. First DMA |
56 | region may be smaller than PAGE_SIZE */ | 57 | region may be smaller than PAGE_SIZE */ |
57 | instructions = 1 + ((bpl + padding) * lines) / PAGE_SIZE + lines; | 58 | instructions = skip_lines * 4; |
58 | instructions += 2; | 59 | instructions += (1 + ((bpl + padding) * store_lines) |
59 | if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,instructions*8)) < 0) | 60 | / PAGE_SIZE + store_lines) * 8; |
61 | instructions += 2 * 8; | ||
62 | if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,instructions)) < 0) | ||
60 | return rc; | 63 | return rc; |
61 | 64 | ||
62 | /* sync instruction */ | 65 | /* sync instruction */ |
@@ -64,11 +67,16 @@ bttv_risc_packed(struct bttv *btv, struct btcx_riscmem *risc, | |||
64 | *(rp++) = cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1); | 67 | *(rp++) = cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1); |
65 | *(rp++) = cpu_to_le32(0); | 68 | *(rp++) = cpu_to_le32(0); |
66 | 69 | ||
70 | while (skip_lines-- > 0) { | ||
71 | *(rp++) = cpu_to_le32(BT848_RISC_SKIP | BT848_RISC_SOL | | ||
72 | BT848_RISC_EOL | bpl); | ||
73 | } | ||
74 | |||
67 | /* scan lines */ | 75 | /* scan lines */ |
68 | sg = sglist; | 76 | sg = sglist; |
69 | for (line = 0; line < lines; line++) { | 77 | for (line = 0; line < store_lines; line++) { |
70 | if ((btv->opt_vcr_hack) && | 78 | if ((btv->opt_vcr_hack) && |
71 | (line >= (lines - VCR_HACK_LINES))) | 79 | (line >= (store_lines - VCR_HACK_LINES))) |
72 | continue; | 80 | continue; |
73 | while (offset && offset >= sg_dma_len(sg)) { | 81 | while (offset && offset >= sg_dma_len(sg)) { |
74 | offset -= sg_dma_len(sg); | 82 | offset -= sg_dma_len(sg); |
@@ -130,7 +138,8 @@ bttv_risc_planar(struct bttv *btv, struct btcx_riscmem *risc, | |||
130 | /* estimate risc mem: worst case is one write per page border + | 138 | /* estimate risc mem: worst case is one write per page border + |
131 | one write per scan line (5 dwords) | 139 | one write per scan line (5 dwords) |
132 | plus sync + jump (2 dwords) */ | 140 | plus sync + jump (2 dwords) */ |
133 | instructions = (ybpl * ylines * 2) / PAGE_SIZE + ylines; | 141 | instructions = ((3 + (ybpl + ypadding) * ylines * 2) |
142 | / PAGE_SIZE) + ylines; | ||
134 | instructions += 2; | 143 | instructions += 2; |
135 | if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,instructions*4*5)) < 0) | 144 | if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,instructions*4*5)) < 0) |
136 | return rc; | 145 | return rc; |
@@ -317,10 +326,10 @@ bttv_risc_overlay(struct bttv *btv, struct btcx_riscmem *risc, | |||
317 | /* ---------------------------------------------------------- */ | 326 | /* ---------------------------------------------------------- */ |
318 | 327 | ||
319 | static void | 328 | static void |
320 | bttv_calc_geo(struct bttv *btv, struct bttv_geometry *geo, | 329 | bttv_calc_geo_old(struct bttv *btv, struct bttv_geometry *geo, |
321 | int width, int height, int interleaved, int norm) | 330 | int width, int height, int interleaved, |
331 | const struct bttv_tvnorm *tvnorm) | ||
322 | { | 332 | { |
323 | const struct bttv_tvnorm *tvnorm = &bttv_tvnorms[norm]; | ||
324 | u32 xsf, sr; | 333 | u32 xsf, sr; |
325 | int vdelay; | 334 | int vdelay; |
326 | 335 | ||
@@ -361,6 +370,62 @@ bttv_calc_geo(struct bttv *btv, struct bttv_geometry *geo, | |||
361 | } | 370 | } |
362 | 371 | ||
363 | static void | 372 | static void |
373 | bttv_calc_geo (struct bttv * btv, | ||
374 | struct bttv_geometry * geo, | ||
375 | unsigned int width, | ||
376 | unsigned int height, | ||
377 | int both_fields, | ||
378 | const struct bttv_tvnorm * tvnorm, | ||
379 | const struct v4l2_rect * crop) | ||
380 | { | ||
381 | unsigned int c_width; | ||
382 | unsigned int c_height; | ||
383 | u32 sr; | ||
384 | |||
385 | if ((crop->left == tvnorm->cropcap.defrect.left | ||
386 | && crop->top == tvnorm->cropcap.defrect.top | ||
387 | && crop->width == tvnorm->cropcap.defrect.width | ||
388 | && crop->height == tvnorm->cropcap.defrect.height | ||
389 | && width <= tvnorm->swidth /* see PAL-Nc et al */) | ||
390 | || bttv_tvcards[btv->c.type].muxsel[btv->input] < 0) { | ||
391 | bttv_calc_geo_old(btv, geo, width, height, | ||
392 | both_fields, tvnorm); | ||
393 | return; | ||
394 | } | ||
395 | |||
396 | /* For bug compatibility the image size checks permit scale | ||
397 | factors > 16. See bttv_crop_calc_limits(). */ | ||
398 | c_width = min((unsigned int) crop->width, width * 16); | ||
399 | c_height = min((unsigned int) crop->height, height * 16); | ||
400 | |||
401 | geo->width = width; | ||
402 | geo->hscale = (c_width * 4096U + (width >> 1)) / width - 4096; | ||
403 | /* Even to store Cb first, odd for Cr. */ | ||
404 | geo->hdelay = ((crop->left * width + c_width) / c_width) & ~1; | ||
405 | |||
406 | geo->sheight = c_height; | ||
407 | geo->vdelay = crop->top - tvnorm->cropcap.bounds.top + MIN_VDELAY; | ||
408 | sr = c_height >> !both_fields; | ||
409 | sr = (sr * 512U + (height >> 1)) / height - 512; | ||
410 | geo->vscale = (0x10000UL - sr) & 0x1fff; | ||
411 | geo->vscale |= both_fields ? (BT848_VSCALE_INT << 8) : 0; | ||
412 | geo->vtotal = tvnorm->vtotal; | ||
413 | |||
414 | geo->crop = (((geo->width >> 8) & 0x03) | | ||
415 | ((geo->hdelay >> 6) & 0x0c) | | ||
416 | ((geo->sheight >> 4) & 0x30) | | ||
417 | ((geo->vdelay >> 2) & 0xc0)); | ||
418 | |||
419 | if (btv->opt_combfilter) { | ||
420 | geo->vtc = (width < 193) ? 2 : ((width < 385) ? 1 : 0); | ||
421 | geo->comb = (width < 769) ? 1 : 0; | ||
422 | } else { | ||
423 | geo->vtc = 0; | ||
424 | geo->comb = 0; | ||
425 | } | ||
426 | } | ||
427 | |||
428 | static void | ||
364 | bttv_apply_geo(struct bttv *btv, struct bttv_geometry *geo, int odd) | 429 | bttv_apply_geo(struct bttv *btv, struct bttv_geometry *geo, int odd) |
365 | { | 430 | { |
366 | int off = odd ? 0x80 : 0x00; | 431 | int off = odd ? 0x80 : 0x00; |
@@ -522,16 +587,51 @@ int | |||
522 | bttv_buffer_activate_vbi(struct bttv *btv, | 587 | bttv_buffer_activate_vbi(struct bttv *btv, |
523 | struct bttv_buffer *vbi) | 588 | struct bttv_buffer *vbi) |
524 | { | 589 | { |
525 | /* vbi capture */ | 590 | struct btcx_riscmem *top; |
591 | struct btcx_riscmem *bottom; | ||
592 | int top_irq_flags; | ||
593 | int bottom_irq_flags; | ||
594 | |||
595 | top = NULL; | ||
596 | bottom = NULL; | ||
597 | top_irq_flags = 0; | ||
598 | bottom_irq_flags = 0; | ||
599 | |||
526 | if (vbi) { | 600 | if (vbi) { |
601 | unsigned int crop, vdelay; | ||
602 | |||
527 | vbi->vb.state = STATE_ACTIVE; | 603 | vbi->vb.state = STATE_ACTIVE; |
528 | list_del(&vbi->vb.queue); | 604 | list_del(&vbi->vb.queue); |
529 | bttv_risc_hook(btv, RISC_SLOT_O_VBI, &vbi->top, 0); | 605 | |
530 | bttv_risc_hook(btv, RISC_SLOT_E_VBI, &vbi->bottom, 4); | 606 | /* VDELAY is start of video, end of VBI capturing. */ |
531 | } else { | 607 | crop = btread(BT848_E_CROP); |
532 | bttv_risc_hook(btv, RISC_SLOT_O_VBI, NULL, 0); | 608 | vdelay = btread(BT848_E_VDELAY_LO) + ((crop & 0xc0) << 2); |
533 | bttv_risc_hook(btv, RISC_SLOT_E_VBI, NULL, 0); | 609 | |
610 | if (vbi->geo.vdelay > vdelay) { | ||
611 | vdelay = vbi->geo.vdelay & 0xfe; | ||
612 | crop = (crop & 0x3f) | ((vbi->geo.vdelay >> 2) & 0xc0); | ||
613 | |||
614 | btwrite(vdelay, BT848_E_VDELAY_LO); | ||
615 | btwrite(crop, BT848_E_CROP); | ||
616 | btwrite(vdelay, BT848_O_VDELAY_LO); | ||
617 | btwrite(crop, BT848_O_CROP); | ||
618 | } | ||
619 | |||
620 | if (vbi->vbi_count[0] > 0) { | ||
621 | top = &vbi->top; | ||
622 | top_irq_flags = 4; | ||
623 | } | ||
624 | |||
625 | if (vbi->vbi_count[1] > 0) { | ||
626 | top_irq_flags = 0; | ||
627 | bottom = &vbi->bottom; | ||
628 | bottom_irq_flags = 4; | ||
629 | } | ||
534 | } | 630 | } |
631 | |||
632 | bttv_risc_hook(btv, RISC_SLOT_O_VBI, top, top_irq_flags); | ||
633 | bttv_risc_hook(btv, RISC_SLOT_E_VBI, bottom, bottom_irq_flags); | ||
634 | |||
535 | return 0; | 635 | return 0; |
536 | } | 636 | } |
537 | 637 | ||
@@ -611,28 +711,31 @@ bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf) | |||
611 | int bpf = bpl * (buf->vb.height >> 1); | 711 | int bpf = bpl * (buf->vb.height >> 1); |
612 | 712 | ||
613 | bttv_calc_geo(btv,&buf->geo,buf->vb.width,buf->vb.height, | 713 | bttv_calc_geo(btv,&buf->geo,buf->vb.width,buf->vb.height, |
614 | V4L2_FIELD_HAS_BOTH(buf->vb.field),buf->tvnorm); | 714 | V4L2_FIELD_HAS_BOTH(buf->vb.field), |
715 | tvnorm,&buf->crop); | ||
615 | 716 | ||
616 | switch (buf->vb.field) { | 717 | switch (buf->vb.field) { |
617 | case V4L2_FIELD_TOP: | 718 | case V4L2_FIELD_TOP: |
618 | bttv_risc_packed(btv,&buf->top,buf->vb.dma.sglist, | 719 | bttv_risc_packed(btv,&buf->top,buf->vb.dma.sglist, |
619 | 0,bpl,0,buf->vb.height); | 720 | /* offset */ 0,bpl, |
721 | /* padding */ 0,/* skip_lines */ 0, | ||
722 | buf->vb.height); | ||
620 | break; | 723 | break; |
621 | case V4L2_FIELD_BOTTOM: | 724 | case V4L2_FIELD_BOTTOM: |
622 | bttv_risc_packed(btv,&buf->bottom,buf->vb.dma.sglist, | 725 | bttv_risc_packed(btv,&buf->bottom,buf->vb.dma.sglist, |
623 | 0,bpl,0,buf->vb.height); | 726 | 0,bpl,0,0,buf->vb.height); |
624 | break; | 727 | break; |
625 | case V4L2_FIELD_INTERLACED: | 728 | case V4L2_FIELD_INTERLACED: |
626 | bttv_risc_packed(btv,&buf->top,buf->vb.dma.sglist, | 729 | bttv_risc_packed(btv,&buf->top,buf->vb.dma.sglist, |
627 | 0,bpl,bpl,buf->vb.height >> 1); | 730 | 0,bpl,bpl,0,buf->vb.height >> 1); |
628 | bttv_risc_packed(btv,&buf->bottom,buf->vb.dma.sglist, | 731 | bttv_risc_packed(btv,&buf->bottom,buf->vb.dma.sglist, |
629 | bpl,bpl,bpl,buf->vb.height >> 1); | 732 | bpl,bpl,bpl,0,buf->vb.height >> 1); |
630 | break; | 733 | break; |
631 | case V4L2_FIELD_SEQ_TB: | 734 | case V4L2_FIELD_SEQ_TB: |
632 | bttv_risc_packed(btv,&buf->top,buf->vb.dma.sglist, | 735 | bttv_risc_packed(btv,&buf->top,buf->vb.dma.sglist, |
633 | 0,bpl,0,buf->vb.height >> 1); | 736 | 0,bpl,0,0,buf->vb.height >> 1); |
634 | bttv_risc_packed(btv,&buf->bottom,buf->vb.dma.sglist, | 737 | bttv_risc_packed(btv,&buf->bottom,buf->vb.dma.sglist, |
635 | bpf,bpl,0,buf->vb.height >> 1); | 738 | bpf,bpl,0,0,buf->vb.height >> 1); |
636 | break; | 739 | break; |
637 | default: | 740 | default: |
638 | BUG(); | 741 | BUG(); |
@@ -662,7 +765,8 @@ bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf) | |||
662 | switch (buf->vb.field) { | 765 | switch (buf->vb.field) { |
663 | case V4L2_FIELD_TOP: | 766 | case V4L2_FIELD_TOP: |
664 | bttv_calc_geo(btv,&buf->geo,buf->vb.width, | 767 | bttv_calc_geo(btv,&buf->geo,buf->vb.width, |
665 | buf->vb.height,0,buf->tvnorm); | 768 | buf->vb.height,/* both_fields */ 0, |
769 | tvnorm,&buf->crop); | ||
666 | bttv_risc_planar(btv, &buf->top, buf->vb.dma.sglist, | 770 | bttv_risc_planar(btv, &buf->top, buf->vb.dma.sglist, |
667 | 0,buf->vb.width,0,buf->vb.height, | 771 | 0,buf->vb.width,0,buf->vb.height, |
668 | uoffset,voffset,buf->fmt->hshift, | 772 | uoffset,voffset,buf->fmt->hshift, |
@@ -670,7 +774,8 @@ bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf) | |||
670 | break; | 774 | break; |
671 | case V4L2_FIELD_BOTTOM: | 775 | case V4L2_FIELD_BOTTOM: |
672 | bttv_calc_geo(btv,&buf->geo,buf->vb.width, | 776 | bttv_calc_geo(btv,&buf->geo,buf->vb.width, |
673 | buf->vb.height,0,buf->tvnorm); | 777 | buf->vb.height,0, |
778 | tvnorm,&buf->crop); | ||
674 | bttv_risc_planar(btv, &buf->bottom, buf->vb.dma.sglist, | 779 | bttv_risc_planar(btv, &buf->bottom, buf->vb.dma.sglist, |
675 | 0,buf->vb.width,0,buf->vb.height, | 780 | 0,buf->vb.width,0,buf->vb.height, |
676 | uoffset,voffset,buf->fmt->hshift, | 781 | uoffset,voffset,buf->fmt->hshift, |
@@ -678,7 +783,8 @@ bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf) | |||
678 | break; | 783 | break; |
679 | case V4L2_FIELD_INTERLACED: | 784 | case V4L2_FIELD_INTERLACED: |
680 | bttv_calc_geo(btv,&buf->geo,buf->vb.width, | 785 | bttv_calc_geo(btv,&buf->geo,buf->vb.width, |
681 | buf->vb.height,1,buf->tvnorm); | 786 | buf->vb.height,1, |
787 | tvnorm,&buf->crop); | ||
682 | lines = buf->vb.height >> 1; | 788 | lines = buf->vb.height >> 1; |
683 | ypadding = buf->vb.width; | 789 | ypadding = buf->vb.width; |
684 | cpadding = buf->vb.width >> buf->fmt->hshift; | 790 | cpadding = buf->vb.width >> buf->fmt->hshift; |
@@ -700,7 +806,8 @@ bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf) | |||
700 | break; | 806 | break; |
701 | case V4L2_FIELD_SEQ_TB: | 807 | case V4L2_FIELD_SEQ_TB: |
702 | bttv_calc_geo(btv,&buf->geo,buf->vb.width, | 808 | bttv_calc_geo(btv,&buf->geo,buf->vb.width, |
703 | buf->vb.height,1,buf->tvnorm); | 809 | buf->vb.height,1, |
810 | tvnorm,&buf->crop); | ||
704 | lines = buf->vb.height >> 1; | 811 | lines = buf->vb.height >> 1; |
705 | ypadding = buf->vb.width; | 812 | ypadding = buf->vb.width; |
706 | cpadding = buf->vb.width >> buf->fmt->hshift; | 813 | cpadding = buf->vb.width >> buf->fmt->hshift; |
@@ -731,11 +838,12 @@ bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf) | |||
731 | /* build risc code */ | 838 | /* build risc code */ |
732 | buf->vb.field = V4L2_FIELD_SEQ_TB; | 839 | buf->vb.field = V4L2_FIELD_SEQ_TB; |
733 | bttv_calc_geo(btv,&buf->geo,tvnorm->swidth,tvnorm->sheight, | 840 | bttv_calc_geo(btv,&buf->geo,tvnorm->swidth,tvnorm->sheight, |
734 | 1,buf->tvnorm); | 841 | 1,tvnorm,&buf->crop); |
735 | bttv_risc_packed(btv, &buf->top, buf->vb.dma.sglist, | 842 | bttv_risc_packed(btv, &buf->top, buf->vb.dma.sglist, |
736 | 0, RAW_BPL, 0, RAW_LINES); | 843 | /* offset */ 0, RAW_BPL, /* padding */ 0, |
844 | /* skip_lines */ 0, RAW_LINES); | ||
737 | bttv_risc_packed(btv, &buf->bottom, buf->vb.dma.sglist, | 845 | bttv_risc_packed(btv, &buf->bottom, buf->vb.dma.sglist, |
738 | buf->vb.size/2 , RAW_BPL, 0, RAW_LINES); | 846 | buf->vb.size/2 , RAW_BPL, 0, 0, RAW_LINES); |
739 | } | 847 | } |
740 | 848 | ||
741 | /* copy format info */ | 849 | /* copy format info */ |
@@ -761,7 +869,8 @@ bttv_overlay_risc(struct bttv *btv, | |||
761 | 869 | ||
762 | /* calculate geometry */ | 870 | /* calculate geometry */ |
763 | bttv_calc_geo(btv,&buf->geo,ov->w.width,ov->w.height, | 871 | bttv_calc_geo(btv,&buf->geo,ov->w.width,ov->w.height, |
764 | V4L2_FIELD_HAS_BOTH(ov->field), ov->tvnorm); | 872 | V4L2_FIELD_HAS_BOTH(ov->field), |
873 | &bttv_tvnorms[ov->tvnorm],&buf->crop); | ||
765 | 874 | ||
766 | /* build risc code */ | 875 | /* build risc code */ |
767 | switch (ov->field) { | 876 | switch (ov->field) { |
diff --git a/drivers/media/video/bt8xx/bttv-vbi.c b/drivers/media/video/bt8xx/bttv-vbi.c index 6fc6b0260056..93e35de5a181 100644 --- a/drivers/media/video/bt8xx/bttv-vbi.c +++ b/drivers/media/video/bt8xx/bttv-vbi.c | |||
@@ -5,6 +5,9 @@ | |||
5 | 5 | ||
6 | (c) 2002 Gerd Knorr <kraxel@bytesex.org> | 6 | (c) 2002 Gerd Knorr <kraxel@bytesex.org> |
7 | 7 | ||
8 | Copyright (C) 2005, 2006 Michael H. Schimek <mschimek@gmx.at> | ||
9 | Sponsored by OPQ Systems AB | ||
10 | |||
8 | This program is free software; you can redistribute it and/or modify | 11 | This program is free software; you can redistribute it and/or modify |
9 | it under the terms of the GNU General Public License as published by | 12 | it under the terms of the GNU General Public License as published by |
10 | the Free Software Foundation; either version 2 of the License, or | 13 | the Free Software Foundation; either version 2 of the License, or |
@@ -41,8 +44,15 @@ | |||
41 | to be about 244. */ | 44 | to be about 244. */ |
42 | #define VBI_OFFSET 244 | 45 | #define VBI_OFFSET 244 |
43 | 46 | ||
47 | /* 2048 for compatibility with earlier driver versions. The driver | ||
48 | really stores 1024 + tvnorm->vbipack * 4 samples per line in the | ||
49 | buffer. Note tvnorm->vbipack is <= 0xFF (limit of VBIPACK_LO + HI | ||
50 | is 0x1FF DWORDs) and VBI read()s store a frame counter in the last | ||
51 | four bytes of the VBI image. */ | ||
52 | #define VBI_BPL 2048 | ||
53 | |||
54 | /* Compatibility. */ | ||
44 | #define VBI_DEFLINES 16 | 55 | #define VBI_DEFLINES 16 |
45 | #define VBI_MAXLINES 32 | ||
46 | 56 | ||
47 | static unsigned int vbibufs = 4; | 57 | static unsigned int vbibufs = 4; |
48 | static unsigned int vbi_debug = 0; | 58 | static unsigned int vbi_debug = 0; |
@@ -58,21 +68,12 @@ MODULE_PARM_DESC(vbi_debug,"vbi code debug messages, default is 0 (no)"); | |||
58 | #define dprintk(fmt, arg...) if (vbi_debug) \ | 68 | #define dprintk(fmt, arg...) if (vbi_debug) \ |
59 | printk(KERN_DEBUG "bttv%d/vbi: " fmt, btv->c.nr , ## arg) | 69 | printk(KERN_DEBUG "bttv%d/vbi: " fmt, btv->c.nr , ## arg) |
60 | 70 | ||
71 | #define IMAGE_SIZE(fmt) \ | ||
72 | (((fmt)->count[0] + (fmt)->count[1]) * (fmt)->samples_per_line) | ||
73 | |||
61 | /* ----------------------------------------------------------------------- */ | 74 | /* ----------------------------------------------------------------------- */ |
62 | /* vbi risc code + mm */ | 75 | /* vbi risc code + mm */ |
63 | 76 | ||
64 | static int | ||
65 | vbi_buffer_risc(struct bttv *btv, struct bttv_buffer *buf, int lines) | ||
66 | { | ||
67 | int bpl = 2048; | ||
68 | |||
69 | bttv_risc_packed(btv, &buf->top, buf->vb.dma.sglist, | ||
70 | 0, bpl-4, 4, lines); | ||
71 | bttv_risc_packed(btv, &buf->bottom, buf->vb.dma.sglist, | ||
72 | lines * bpl, bpl-4, 4, lines); | ||
73 | return 0; | ||
74 | } | ||
75 | |||
76 | static int vbi_buffer_setup(struct videobuf_queue *q, | 77 | static int vbi_buffer_setup(struct videobuf_queue *q, |
77 | unsigned int *count, unsigned int *size) | 78 | unsigned int *count, unsigned int *size) |
78 | { | 79 | { |
@@ -81,8 +82,16 @@ static int vbi_buffer_setup(struct videobuf_queue *q, | |||
81 | 82 | ||
82 | if (0 == *count) | 83 | if (0 == *count) |
83 | *count = vbibufs; | 84 | *count = vbibufs; |
84 | *size = fh->lines * 2 * 2048; | 85 | |
85 | dprintk("setup: lines=%d\n",fh->lines); | 86 | *size = IMAGE_SIZE(&fh->vbi_fmt.fmt); |
87 | |||
88 | dprintk("setup: samples=%u start=%d,%d count=%u,%u\n", | ||
89 | fh->vbi_fmt.fmt.samples_per_line, | ||
90 | fh->vbi_fmt.fmt.start[0], | ||
91 | fh->vbi_fmt.fmt.start[1], | ||
92 | fh->vbi_fmt.fmt.count[0], | ||
93 | fh->vbi_fmt.fmt.count[1]); | ||
94 | |||
86 | return 0; | 95 | return 0; |
87 | } | 96 | } |
88 | 97 | ||
@@ -93,18 +102,93 @@ static int vbi_buffer_prepare(struct videobuf_queue *q, | |||
93 | struct bttv_fh *fh = q->priv_data; | 102 | struct bttv_fh *fh = q->priv_data; |
94 | struct bttv *btv = fh->btv; | 103 | struct bttv *btv = fh->btv; |
95 | struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb); | 104 | struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb); |
105 | const struct bttv_tvnorm *tvnorm; | ||
106 | unsigned int skip_lines0, skip_lines1, min_vdelay; | ||
107 | int redo_dma_risc; | ||
96 | int rc; | 108 | int rc; |
97 | 109 | ||
98 | buf->vb.size = fh->lines * 2 * 2048; | 110 | buf->vb.size = IMAGE_SIZE(&fh->vbi_fmt.fmt); |
99 | if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) | 111 | if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) |
100 | return -EINVAL; | 112 | return -EINVAL; |
101 | 113 | ||
114 | tvnorm = fh->vbi_fmt.tvnorm; | ||
115 | |||
116 | /* There's no VBI_VDELAY register, RISC must skip the lines | ||
117 | we don't want. With default parameters we skip zero lines | ||
118 | as earlier driver versions did. The driver permits video | ||
119 | standard changes while capturing, so we use vbi_fmt.tvnorm | ||
120 | instead of btv->tvnorm to skip zero lines after video | ||
121 | standard changes as well. */ | ||
122 | |||
123 | skip_lines0 = 0; | ||
124 | skip_lines1 = 0; | ||
125 | |||
126 | if (fh->vbi_fmt.fmt.count[0] > 0) | ||
127 | skip_lines0 = max(0, (fh->vbi_fmt.fmt.start[0] | ||
128 | - tvnorm->vbistart[0])); | ||
129 | if (fh->vbi_fmt.fmt.count[1] > 0) | ||
130 | skip_lines1 = max(0, (fh->vbi_fmt.fmt.start[1] | ||
131 | - tvnorm->vbistart[1])); | ||
132 | |||
133 | redo_dma_risc = 0; | ||
134 | |||
135 | if (buf->vbi_skip[0] != skip_lines0 || | ||
136 | buf->vbi_skip[1] != skip_lines1 || | ||
137 | buf->vbi_count[0] != fh->vbi_fmt.fmt.count[0] || | ||
138 | buf->vbi_count[1] != fh->vbi_fmt.fmt.count[1]) { | ||
139 | buf->vbi_skip[0] = skip_lines0; | ||
140 | buf->vbi_skip[1] = skip_lines1; | ||
141 | buf->vbi_count[0] = fh->vbi_fmt.fmt.count[0]; | ||
142 | buf->vbi_count[1] = fh->vbi_fmt.fmt.count[1]; | ||
143 | redo_dma_risc = 1; | ||
144 | } | ||
145 | |||
102 | if (STATE_NEEDS_INIT == buf->vb.state) { | 146 | if (STATE_NEEDS_INIT == buf->vb.state) { |
147 | redo_dma_risc = 1; | ||
103 | if (0 != (rc = videobuf_iolock(q, &buf->vb, NULL))) | 148 | if (0 != (rc = videobuf_iolock(q, &buf->vb, NULL))) |
104 | goto fail; | 149 | goto fail; |
105 | if (0 != (rc = vbi_buffer_risc(btv,buf,fh->lines))) | ||
106 | goto fail; | ||
107 | } | 150 | } |
151 | |||
152 | if (redo_dma_risc) { | ||
153 | unsigned int bpl, padding, offset; | ||
154 | |||
155 | bpl = 2044; /* max. vbipack */ | ||
156 | padding = VBI_BPL - bpl; | ||
157 | |||
158 | if (fh->vbi_fmt.fmt.count[0] > 0) { | ||
159 | rc = bttv_risc_packed(btv, &buf->top, | ||
160 | buf->vb.dma.sglist, | ||
161 | /* offset */ 0, bpl, | ||
162 | padding, skip_lines0, | ||
163 | fh->vbi_fmt.fmt.count[0]); | ||
164 | if (0 != rc) | ||
165 | goto fail; | ||
166 | } | ||
167 | |||
168 | if (fh->vbi_fmt.fmt.count[1] > 0) { | ||
169 | offset = fh->vbi_fmt.fmt.count[0] * VBI_BPL; | ||
170 | |||
171 | rc = bttv_risc_packed(btv, &buf->bottom, | ||
172 | buf->vb.dma.sglist, | ||
173 | offset, bpl, | ||
174 | padding, skip_lines1, | ||
175 | fh->vbi_fmt.fmt.count[1]); | ||
176 | if (0 != rc) | ||
177 | goto fail; | ||
178 | } | ||
179 | } | ||
180 | |||
181 | /* VBI capturing ends at VDELAY, start of video capturing, | ||
182 | no matter where the RISC program ends. VDELAY minimum is 2, | ||
183 | bounds.top is the corresponding first field line number | ||
184 | times two. VDELAY counts half field lines. */ | ||
185 | min_vdelay = MIN_VDELAY; | ||
186 | if (fh->vbi_fmt.end >= tvnorm->cropcap.bounds.top) | ||
187 | min_vdelay += fh->vbi_fmt.end - tvnorm->cropcap.bounds.top; | ||
188 | |||
189 | /* For bttv_buffer_activate_vbi(). */ | ||
190 | buf->geo.vdelay = min_vdelay; | ||
191 | |||
108 | buf->vb.state = STATE_PREPARED; | 192 | buf->vb.state = STATE_PREPARED; |
109 | buf->vb.field = field; | 193 | buf->vb.field = field; |
110 | dprintk("buf prepare %p: top=%p bottom=%p field=%s\n", | 194 | dprintk("buf prepare %p: top=%p bottom=%p field=%s\n", |
@@ -140,7 +224,7 @@ static void vbi_buffer_release(struct videobuf_queue *q, struct videobuf_buffer | |||
140 | struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb); | 224 | struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb); |
141 | 225 | ||
142 | dprintk("free %p\n",vb); | 226 | dprintk("free %p\n",vb); |
143 | bttv_dma_free(&fh->cap,fh->btv,buf); | 227 | bttv_dma_free(q,fh->btv,buf); |
144 | } | 228 | } |
145 | 229 | ||
146 | struct videobuf_queue_ops bttv_vbi_qops = { | 230 | struct videobuf_queue_ops bttv_vbi_qops = { |
@@ -152,69 +236,215 @@ struct videobuf_queue_ops bttv_vbi_qops = { | |||
152 | 236 | ||
153 | /* ----------------------------------------------------------------------- */ | 237 | /* ----------------------------------------------------------------------- */ |
154 | 238 | ||
155 | void bttv_vbi_setlines(struct bttv_fh *fh, struct bttv *btv, int lines) | 239 | static int |
240 | try_fmt (struct v4l2_vbi_format * f, | ||
241 | const struct bttv_tvnorm * tvnorm, | ||
242 | __s32 crop_start) | ||
156 | { | 243 | { |
157 | int vdelay; | 244 | __s32 min_start, max_start, max_end, f2_offset; |
158 | 245 | unsigned int i; | |
159 | if (lines < 1) | 246 | |
160 | lines = 1; | 247 | /* For compatibility with earlier driver versions we must pretend |
161 | if (lines > VBI_MAXLINES) | 248 | the VBI and video capture window may overlap. In reality RISC |
162 | lines = VBI_MAXLINES; | 249 | magic aborts VBI capturing at the first line of video capturing, |
163 | fh->lines = lines; | 250 | leaving the rest of the buffer unchanged, usually all zero. |
164 | 251 | VBI capturing must always start before video capturing. >> 1 | |
165 | vdelay = btread(BT848_E_VDELAY_LO); | 252 | because cropping counts field lines times two. */ |
166 | if (vdelay < lines*2) { | 253 | min_start = tvnorm->vbistart[0]; |
167 | vdelay = lines*2; | 254 | max_start = (crop_start >> 1) - 1; |
168 | btwrite(vdelay,BT848_E_VDELAY_LO); | 255 | max_end = (tvnorm->cropcap.bounds.top |
169 | btwrite(vdelay,BT848_O_VDELAY_LO); | 256 | + tvnorm->cropcap.bounds.height) >> 1; |
257 | |||
258 | if (min_start > max_start) | ||
259 | return -EBUSY; | ||
260 | |||
261 | BUG_ON(max_start >= max_end); | ||
262 | |||
263 | f->sampling_rate = tvnorm->Fsc; | ||
264 | f->samples_per_line = VBI_BPL; | ||
265 | f->sample_format = V4L2_PIX_FMT_GREY; | ||
266 | f->offset = VBI_OFFSET; | ||
267 | |||
268 | f2_offset = tvnorm->vbistart[1] - tvnorm->vbistart[0]; | ||
269 | |||
270 | for (i = 0; i < 2; ++i) { | ||
271 | if (0 == f->count[i]) { | ||
272 | /* No data from this field. We leave f->start[i] | ||
273 | alone because VIDIOCSVBIFMT is w/o and EINVALs | ||
274 | when a driver does not support exactly the | ||
275 | requested parameters. */ | ||
276 | } else { | ||
277 | s64 start, count; | ||
278 | |||
279 | start = clamp(f->start[i], min_start, max_start); | ||
280 | /* s64 to prevent overflow. */ | ||
281 | count = (s64) f->start[i] + f->count[i] - start; | ||
282 | f->start[i] = start; | ||
283 | f->count[i] = clamp(count, (s64) 1, | ||
284 | max_end - start); | ||
285 | } | ||
286 | |||
287 | min_start += f2_offset; | ||
288 | max_start += f2_offset; | ||
289 | max_end += f2_offset; | ||
170 | } | 290 | } |
291 | |||
292 | if (0 == (f->count[0] | f->count[1])) { | ||
293 | /* As in earlier driver versions. */ | ||
294 | f->start[0] = tvnorm->vbistart[0]; | ||
295 | f->start[1] = tvnorm->vbistart[1]; | ||
296 | f->count[0] = 1; | ||
297 | f->count[1] = 1; | ||
298 | } | ||
299 | |||
300 | f->flags = 0; | ||
301 | |||
302 | f->reserved[0] = 0; | ||
303 | f->reserved[1] = 0; | ||
304 | |||
305 | return 0; | ||
171 | } | 306 | } |
172 | 307 | ||
173 | void bttv_vbi_try_fmt(struct bttv_fh *fh, struct v4l2_format *f) | 308 | int |
309 | bttv_vbi_try_fmt (struct bttv_fh * fh, | ||
310 | struct v4l2_vbi_format * f) | ||
174 | { | 311 | { |
312 | struct bttv *btv = fh->btv; | ||
175 | const struct bttv_tvnorm *tvnorm; | 313 | const struct bttv_tvnorm *tvnorm; |
176 | s64 count0,count1,count; | 314 | __s32 crop_start; |
177 | 315 | ||
178 | tvnorm = &bttv_tvnorms[fh->btv->tvnorm]; | 316 | mutex_lock(&btv->lock); |
179 | f->type = V4L2_BUF_TYPE_VBI_CAPTURE; | 317 | |
180 | f->fmt.vbi.sampling_rate = tvnorm->Fsc; | 318 | tvnorm = &bttv_tvnorms[btv->tvnorm]; |
181 | f->fmt.vbi.samples_per_line = 2048; | 319 | crop_start = btv->crop_start; |
182 | f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY; | 320 | |
183 | f->fmt.vbi.offset = VBI_OFFSET; | 321 | mutex_unlock(&btv->lock); |
184 | f->fmt.vbi.flags = 0; | 322 | |
185 | 323 | return try_fmt(f, tvnorm, crop_start); | |
186 | /* s64 to prevent overflow. */ | ||
187 | count0 = (s64) f->fmt.vbi.start[0] + f->fmt.vbi.count[0] | ||
188 | - tvnorm->vbistart[0]; | ||
189 | count1 = (s64) f->fmt.vbi.start[1] + f->fmt.vbi.count[1] | ||
190 | - tvnorm->vbistart[1]; | ||
191 | count = clamp (max (count0, count1), (s64) 1, (s64) VBI_MAXLINES); | ||
192 | |||
193 | f->fmt.vbi.start[0] = tvnorm->vbistart[0]; | ||
194 | f->fmt.vbi.start[1] = tvnorm->vbistart[1]; | ||
195 | f->fmt.vbi.count[0] = count; | ||
196 | f->fmt.vbi.count[1] = count; | ||
197 | |||
198 | f->fmt.vbi.reserved[0] = 0; | ||
199 | f->fmt.vbi.reserved[1] = 0; | ||
200 | } | 324 | } |
201 | 325 | ||
202 | void bttv_vbi_get_fmt(struct bttv_fh *fh, struct v4l2_format *f) | 326 | int |
327 | bttv_vbi_set_fmt (struct bttv_fh * fh, | ||
328 | struct v4l2_vbi_format * f) | ||
203 | { | 329 | { |
330 | struct bttv *btv = fh->btv; | ||
204 | const struct bttv_tvnorm *tvnorm; | 331 | const struct bttv_tvnorm *tvnorm; |
332 | __s32 start1, end; | ||
333 | int rc; | ||
334 | |||
335 | mutex_lock(&btv->lock); | ||
336 | |||
337 | rc = -EBUSY; | ||
338 | if (fh->resources & RESOURCE_VBI) | ||
339 | goto fail; | ||
340 | |||
341 | tvnorm = &bttv_tvnorms[btv->tvnorm]; | ||
342 | |||
343 | rc = try_fmt(f, tvnorm, btv->crop_start); | ||
344 | if (0 != rc) | ||
345 | goto fail; | ||
346 | |||
347 | start1 = f->start[1] - tvnorm->vbistart[1] + tvnorm->vbistart[0]; | ||
348 | |||
349 | /* First possible line of video capturing. Should be | ||
350 | max(f->start[0] + f->count[0], start1 + f->count[1]) * 2 | ||
351 | when capturing both fields. But for compatibility we must | ||
352 | pretend the VBI and video capture window may overlap, | ||
353 | so end = start + 1, the lowest possible value, times two | ||
354 | because vbi_fmt.end counts field lines times two. */ | ||
355 | end = max(f->start[0], start1) * 2 + 2; | ||
356 | |||
357 | mutex_lock(&fh->vbi.lock); | ||
358 | |||
359 | fh->vbi_fmt.fmt = *f; | ||
360 | fh->vbi_fmt.tvnorm = tvnorm; | ||
361 | fh->vbi_fmt.end = end; | ||
362 | |||
363 | mutex_unlock(&fh->vbi.lock); | ||
364 | |||
365 | rc = 0; | ||
366 | |||
367 | fail: | ||
368 | mutex_unlock(&btv->lock); | ||
369 | |||
370 | return rc; | ||
371 | } | ||
372 | |||
373 | void | ||
374 | bttv_vbi_get_fmt (struct bttv_fh * fh, | ||
375 | struct v4l2_vbi_format * f) | ||
376 | { | ||
377 | const struct bttv_tvnorm *tvnorm; | ||
378 | |||
379 | *f = fh->vbi_fmt.fmt; | ||
205 | 380 | ||
206 | tvnorm = &bttv_tvnorms[fh->btv->tvnorm]; | 381 | tvnorm = &bttv_tvnorms[fh->btv->tvnorm]; |
207 | memset(f,0,sizeof(*f)); | 382 | |
208 | f->type = V4L2_BUF_TYPE_VBI_CAPTURE; | 383 | if (tvnorm != fh->vbi_fmt.tvnorm) { |
209 | f->fmt.vbi.sampling_rate = tvnorm->Fsc; | 384 | __s32 max_end; |
210 | f->fmt.vbi.samples_per_line = 2048; | 385 | unsigned int i; |
211 | f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY; | 386 | |
212 | f->fmt.vbi.offset = VBI_OFFSET; | 387 | /* As in vbi_buffer_prepare() this imitates the |
213 | f->fmt.vbi.start[0] = tvnorm->vbistart[0]; | 388 | behaviour of earlier driver versions after video |
214 | f->fmt.vbi.start[1] = tvnorm->vbistart[1]; | 389 | standard changes, with default parameters anyway. */ |
215 | f->fmt.vbi.count[0] = fh->lines; | 390 | |
216 | f->fmt.vbi.count[1] = fh->lines; | 391 | max_end = (tvnorm->cropcap.bounds.top |
217 | f->fmt.vbi.flags = 0; | 392 | + tvnorm->cropcap.bounds.height) >> 1; |
393 | |||
394 | f->sampling_rate = tvnorm->Fsc; | ||
395 | |||
396 | for (i = 0; i < 2; ++i) { | ||
397 | __s32 new_start; | ||
398 | |||
399 | new_start = f->start[i] | ||
400 | + tvnorm->vbistart[i] | ||
401 | - fh->vbi_fmt.tvnorm->vbistart[i]; | ||
402 | |||
403 | f->start[i] = min(new_start, max_end - 1); | ||
404 | f->count[i] = min((__s32) f->count[i], | ||
405 | max_end - f->start[i]); | ||
406 | |||
407 | max_end += tvnorm->vbistart[1] | ||
408 | - tvnorm->vbistart[0]; | ||
409 | } | ||
410 | } | ||
411 | } | ||
412 | |||
413 | void | ||
414 | bttv_vbi_fmt_reset (struct bttv_vbi_fmt * f, | ||
415 | int norm) | ||
416 | { | ||
417 | const struct bttv_tvnorm *tvnorm; | ||
418 | unsigned int real_samples_per_line; | ||
419 | unsigned int real_count; | ||
420 | |||
421 | tvnorm = &bttv_tvnorms[norm]; | ||
422 | |||
423 | f->fmt.sampling_rate = tvnorm->Fsc; | ||
424 | f->fmt.samples_per_line = VBI_BPL; | ||
425 | f->fmt.sample_format = V4L2_PIX_FMT_GREY; | ||
426 | f->fmt.offset = VBI_OFFSET; | ||
427 | f->fmt.start[0] = tvnorm->vbistart[0]; | ||
428 | f->fmt.start[1] = tvnorm->vbistart[1]; | ||
429 | f->fmt.count[0] = VBI_DEFLINES; | ||
430 | f->fmt.count[1] = VBI_DEFLINES; | ||
431 | f->fmt.flags = 0; | ||
432 | f->fmt.reserved[0] = 0; | ||
433 | f->fmt.reserved[1] = 0; | ||
434 | |||
435 | /* For compatibility the buffer size must be 2 * VBI_DEFLINES * | ||
436 | VBI_BPL regardless of the current video standard. */ | ||
437 | real_samples_per_line = 1024 + tvnorm->vbipack * 4; | ||
438 | real_count = ((tvnorm->cropcap.defrect.top >> 1) | ||
439 | - tvnorm->vbistart[0]); | ||
440 | |||
441 | BUG_ON(real_samples_per_line > VBI_BPL); | ||
442 | BUG_ON(real_count > VBI_DEFLINES); | ||
443 | |||
444 | f->tvnorm = tvnorm; | ||
445 | |||
446 | /* See bttv_vbi_fmt_set(). */ | ||
447 | f->end = tvnorm->vbistart[0] * 2 + 2; | ||
218 | } | 448 | } |
219 | 449 | ||
220 | /* ----------------------------------------------------------------------- */ | 450 | /* ----------------------------------------------------------------------- */ |
diff --git a/drivers/media/video/bt8xx/bttv.h b/drivers/media/video/bt8xx/bttv.h index f9c9e3c4d111..5491acbdaf63 100644 --- a/drivers/media/video/bt8xx/bttv.h +++ b/drivers/media/video/bt8xx/bttv.h | |||
@@ -197,33 +197,6 @@ struct bttv_core { | |||
197 | struct bttv; | 197 | struct bttv; |
198 | 198 | ||
199 | 199 | ||
200 | struct bttv_ir { | ||
201 | struct input_dev *dev; | ||
202 | struct ir_input_state ir; | ||
203 | char name[32]; | ||
204 | char phys[32]; | ||
205 | |||
206 | /* Usual gpio signalling */ | ||
207 | |||
208 | u32 mask_keycode; | ||
209 | u32 mask_keydown; | ||
210 | u32 mask_keyup; | ||
211 | u32 polling; | ||
212 | u32 last_gpio; | ||
213 | struct work_struct work; | ||
214 | struct timer_list timer; | ||
215 | |||
216 | /* RC5 gpio */ | ||
217 | u32 rc5_gpio; | ||
218 | struct timer_list timer_end; /* timer_end for code completion */ | ||
219 | struct timer_list timer_keyup; /* timer_end for key release */ | ||
220 | u32 last_rc5; /* last good rc5 code */ | ||
221 | u32 last_bit; /* last raw bit seen */ | ||
222 | u32 code; /* raw code under construction */ | ||
223 | struct timeval base_time; /* time of last seen code */ | ||
224 | int active; /* building raw code */ | ||
225 | }; | ||
226 | |||
227 | struct tvcard | 200 | struct tvcard |
228 | { | 201 | { |
229 | char *name; | 202 | char *name; |
diff --git a/drivers/media/video/bt8xx/bttvp.h b/drivers/media/video/bt8xx/bttvp.h index 311c4c541e01..ad79b8d53430 100644 --- a/drivers/media/video/bt8xx/bttvp.h +++ b/drivers/media/video/bt8xx/bttvp.h | |||
@@ -26,7 +26,7 @@ | |||
26 | #define _BTTVP_H_ | 26 | #define _BTTVP_H_ |
27 | 27 | ||
28 | #include <linux/version.h> | 28 | #include <linux/version.h> |
29 | #define BTTV_VERSION_CODE KERNEL_VERSION(0,9,16) | 29 | #define BTTV_VERSION_CODE KERNEL_VERSION(0,9,17) |
30 | 30 | ||
31 | #include <linux/types.h> | 31 | #include <linux/types.h> |
32 | #include <linux/wait.h> | 32 | #include <linux/wait.h> |
@@ -66,14 +66,22 @@ | |||
66 | #define RISC_SLOT_LOOP 14 | 66 | #define RISC_SLOT_LOOP 14 |
67 | 67 | ||
68 | #define RESOURCE_OVERLAY 1 | 68 | #define RESOURCE_OVERLAY 1 |
69 | #define RESOURCE_VIDEO 2 | 69 | #define RESOURCE_VIDEO_STREAM 2 |
70 | #define RESOURCE_VBI 4 | 70 | #define RESOURCE_VBI 4 |
71 | #define RESOURCE_VIDEO_READ 8 | ||
71 | 72 | ||
72 | #define RAW_LINES 640 | 73 | #define RAW_LINES 640 |
73 | #define RAW_BPL 1024 | 74 | #define RAW_BPL 1024 |
74 | 75 | ||
75 | #define UNSET (-1U) | 76 | #define UNSET (-1U) |
76 | 77 | ||
78 | /* Min. value in VDELAY register. */ | ||
79 | #define MIN_VDELAY 2 | ||
80 | /* Even to get Cb first, odd for Cr. */ | ||
81 | #define MAX_HDELAY (0x3FF & -2) | ||
82 | /* Limits scaled width, which must be a multiple of 4. */ | ||
83 | #define MAX_HACTIVE (0x3FF & -4) | ||
84 | |||
77 | #define clamp(x, low, high) min (max (low, x), high) | 85 | #define clamp(x, low, high) min (max (low, x), high) |
78 | 86 | ||
79 | /* ---------------------------------------------------------- */ | 87 | /* ---------------------------------------------------------- */ |
@@ -92,8 +100,13 @@ struct bttv_tvnorm { | |||
92 | u16 vtotal; | 100 | u16 vtotal; |
93 | int sram; | 101 | int sram; |
94 | /* ITU-R frame line number of the first VBI line we can | 102 | /* ITU-R frame line number of the first VBI line we can |
95 | capture, of the first and second field. */ | 103 | capture, of the first and second field. The last possible line |
104 | is determined by cropcap.bounds. */ | ||
96 | u16 vbistart[2]; | 105 | u16 vbistart[2]; |
106 | /* Horizontally this counts fCLKx1 samples following the leading | ||
107 | edge of the horizontal sync pulse, vertically ITU-R frame line | ||
108 | numbers of the first field times two (2, 4, 6, ... 524 or 624). */ | ||
109 | struct v4l2_cropcap cropcap; | ||
97 | }; | 110 | }; |
98 | extern const struct bttv_tvnorm bttv_tvnorms[]; | 111 | extern const struct bttv_tvnorm bttv_tvnorms[]; |
99 | 112 | ||
@@ -128,6 +141,9 @@ struct bttv_buffer { | |||
128 | struct bttv_geometry geo; | 141 | struct bttv_geometry geo; |
129 | struct btcx_riscmem top; | 142 | struct btcx_riscmem top; |
130 | struct btcx_riscmem bottom; | 143 | struct btcx_riscmem bottom; |
144 | struct v4l2_rect crop; | ||
145 | unsigned int vbi_skip[2]; | ||
146 | unsigned int vbi_count[2]; | ||
131 | }; | 147 | }; |
132 | 148 | ||
133 | struct bttv_buffer_set { | 149 | struct bttv_buffer_set { |
@@ -146,6 +162,34 @@ struct bttv_overlay { | |||
146 | int setup_ok; | 162 | int setup_ok; |
147 | }; | 163 | }; |
148 | 164 | ||
165 | struct bttv_vbi_fmt { | ||
166 | struct v4l2_vbi_format fmt; | ||
167 | |||
168 | /* fmt.start[] and count[] refer to this video standard. */ | ||
169 | const struct bttv_tvnorm *tvnorm; | ||
170 | |||
171 | /* Earliest possible start of video capturing with this | ||
172 | v4l2_vbi_format, in struct bttv_crop.rect units. */ | ||
173 | __s32 end; | ||
174 | }; | ||
175 | |||
176 | /* bttv-vbi.c */ | ||
177 | void bttv_vbi_fmt_reset(struct bttv_vbi_fmt *f, int norm); | ||
178 | |||
179 | struct bttv_crop { | ||
180 | /* A cropping rectangle in struct bttv_tvnorm.cropcap units. */ | ||
181 | struct v4l2_rect rect; | ||
182 | |||
183 | /* Scaled image size limits with this crop rect. Divide | ||
184 | max_height, but not min_height, by two when capturing | ||
185 | single fields. See also bttv_crop_reset() and | ||
186 | bttv_crop_adjust() in bttv-driver.c. */ | ||
187 | __s32 min_scaled_width; | ||
188 | __s32 min_scaled_height; | ||
189 | __s32 max_scaled_width; | ||
190 | __s32 max_scaled_height; | ||
191 | }; | ||
192 | |||
149 | struct bttv_fh { | 193 | struct bttv_fh { |
150 | struct bttv *btv; | 194 | struct bttv *btv; |
151 | int resources; | 195 | int resources; |
@@ -160,13 +204,19 @@ struct bttv_fh { | |||
160 | int width; | 204 | int width; |
161 | int height; | 205 | int height; |
162 | 206 | ||
163 | /* current settings */ | 207 | /* video overlay */ |
164 | const struct bttv_format *ovfmt; | 208 | const struct bttv_format *ovfmt; |
165 | struct bttv_overlay ov; | 209 | struct bttv_overlay ov; |
166 | 210 | ||
167 | /* video overlay */ | 211 | /* Application called VIDIOC_S_CROP. */ |
212 | int do_crop; | ||
213 | |||
214 | /* vbi capture */ | ||
168 | struct videobuf_queue vbi; | 215 | struct videobuf_queue vbi; |
169 | int lines; | 216 | /* Current VBI capture window as seen through this fh (cannot |
217 | be global for compatibility with earlier drivers). Protected | ||
218 | by struct bttv.lock and struct bttv_fh.vbi.lock. */ | ||
219 | struct bttv_vbi_fmt vbi_fmt; | ||
170 | }; | 220 | }; |
171 | 221 | ||
172 | /* ---------------------------------------------------------- */ | 222 | /* ---------------------------------------------------------- */ |
@@ -176,7 +226,8 @@ struct bttv_fh { | |||
176 | int bttv_risc_packed(struct bttv *btv, struct btcx_riscmem *risc, | 226 | int bttv_risc_packed(struct bttv *btv, struct btcx_riscmem *risc, |
177 | struct scatterlist *sglist, | 227 | struct scatterlist *sglist, |
178 | unsigned int offset, unsigned int bpl, | 228 | unsigned int offset, unsigned int bpl, |
179 | unsigned int pitch, unsigned int lines); | 229 | unsigned int pitch, unsigned int skip_lines, |
230 | unsigned int store_lines); | ||
180 | 231 | ||
181 | /* control dma register + risc main loop */ | 232 | /* control dma register + risc main loop */ |
182 | void bttv_set_dma(struct bttv *btv, int override); | 233 | void bttv_set_dma(struct bttv *btv, int override); |
@@ -202,9 +253,9 @@ int bttv_overlay_risc(struct bttv *btv, struct bttv_overlay *ov, | |||
202 | /* ---------------------------------------------------------- */ | 253 | /* ---------------------------------------------------------- */ |
203 | /* bttv-vbi.c */ | 254 | /* bttv-vbi.c */ |
204 | 255 | ||
205 | void bttv_vbi_try_fmt(struct bttv_fh *fh, struct v4l2_format *f); | 256 | int bttv_vbi_try_fmt(struct bttv_fh *fh, struct v4l2_vbi_format *f); |
206 | void bttv_vbi_get_fmt(struct bttv_fh *fh, struct v4l2_format *f); | 257 | void bttv_vbi_get_fmt(struct bttv_fh *fh, struct v4l2_vbi_format *f); |
207 | void bttv_vbi_setlines(struct bttv_fh *fh, struct bttv *btv, int lines); | 258 | int bttv_vbi_set_fmt(struct bttv_fh *fh, struct v4l2_vbi_format *f); |
208 | 259 | ||
209 | extern struct videobuf_queue_ops bttv_vbi_qops; | 260 | extern struct videobuf_queue_ops bttv_vbi_qops; |
210 | 261 | ||
@@ -233,7 +284,6 @@ extern int fini_bttv_i2c(struct bttv *btv); | |||
233 | #define d2printk if (bttv_debug >= 2) printk | 284 | #define d2printk if (bttv_debug >= 2) printk |
234 | 285 | ||
235 | #define BTTV_MAX_FBUF 0x208000 | 286 | #define BTTV_MAX_FBUF 0x208000 |
236 | #define VBIBUF_SIZE (2048*VBI_MAXLINES*2) | ||
237 | #define BTTV_TIMEOUT (HZ/2) /* 0.5 seconds */ | 287 | #define BTTV_TIMEOUT (HZ/2) /* 0.5 seconds */ |
238 | #define BTTV_FREE_IDLE (HZ) /* one second */ | 288 | #define BTTV_FREE_IDLE (HZ) /* one second */ |
239 | 289 | ||
@@ -308,13 +358,12 @@ struct bttv { | |||
308 | 358 | ||
309 | /* infrared remote */ | 359 | /* infrared remote */ |
310 | int has_remote; | 360 | int has_remote; |
311 | struct bttv_ir *remote; | 361 | struct card_ir *remote; |
312 | 362 | ||
313 | /* locking */ | 363 | /* locking */ |
314 | spinlock_t s_lock; | 364 | spinlock_t s_lock; |
315 | struct mutex lock; | 365 | struct mutex lock; |
316 | int resources; | 366 | int resources; |
317 | struct mutex reslock; | ||
318 | #ifdef VIDIOC_G_PRIORITY | 367 | #ifdef VIDIOC_G_PRIORITY |
319 | struct v4l2_prio_state prio; | 368 | struct v4l2_prio_state prio; |
320 | #endif | 369 | #endif |
@@ -384,6 +433,21 @@ struct bttv { | |||
384 | 433 | ||
385 | unsigned int users; | 434 | unsigned int users; |
386 | struct bttv_fh init; | 435 | struct bttv_fh init; |
436 | |||
437 | /* Default (0) and current (1) video capturing and overlay | ||
438 | cropping parameters in bttv_tvnorm.cropcap units. Protected | ||
439 | by bttv.lock. */ | ||
440 | struct bttv_crop crop[2]; | ||
441 | |||
442 | /* Earliest possible start of video capturing in | ||
443 | bttv_tvnorm.cropcap line units. Set by check_alloc_btres() | ||
444 | and free_btres(). Protected by bttv.lock. */ | ||
445 | __s32 vbi_end; | ||
446 | |||
447 | /* Latest possible end of VBI capturing (= crop[x].rect.top when | ||
448 | VIDEO_RESOURCES are locked). Set by check_alloc_btres() | ||
449 | and free_btres(). Protected by bttv.lock. */ | ||
450 | __s32 crop_start; | ||
387 | }; | 451 | }; |
388 | 452 | ||
389 | /* our devices */ | 453 | /* our devices */ |
diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c index 4dae8925667f..682dc7ce48d9 100644 --- a/drivers/media/video/cafe_ccic.c +++ b/drivers/media/video/cafe_ccic.c | |||
@@ -1195,7 +1195,7 @@ static int cafe_vidioc_reqbufs(struct file *filp, void *priv, | |||
1195 | struct v4l2_requestbuffers *req) | 1195 | struct v4l2_requestbuffers *req) |
1196 | { | 1196 | { |
1197 | struct cafe_camera *cam = filp->private_data; | 1197 | struct cafe_camera *cam = filp->private_data; |
1198 | int ret; | 1198 | int ret = 0; /* Silence warning */ |
1199 | 1199 | ||
1200 | /* | 1200 | /* |
1201 | * Make sure it's something we can do. User pointers could be | 1201 | * Make sure it's something we can do. User pointers could be |
diff --git a/drivers/media/video/cpia.c b/drivers/media/video/cpia.c index 7e8d5ef58b61..78c9699eafbb 100644 --- a/drivers/media/video/cpia.c +++ b/drivers/media/video/cpia.c | |||
@@ -1350,13 +1350,13 @@ out: | |||
1350 | 1350 | ||
1351 | static void create_proc_cpia_cam(struct cam_data *cam) | 1351 | static void create_proc_cpia_cam(struct cam_data *cam) |
1352 | { | 1352 | { |
1353 | char name[7]; | 1353 | char name[5 + 1 + 10 + 1]; |
1354 | struct proc_dir_entry *ent; | 1354 | struct proc_dir_entry *ent; |
1355 | 1355 | ||
1356 | if (!cpia_proc_root || !cam) | 1356 | if (!cpia_proc_root || !cam) |
1357 | return; | 1357 | return; |
1358 | 1358 | ||
1359 | sprintf(name, "video%d", cam->vdev.minor); | 1359 | snprintf(name, sizeof(name), "video%d", cam->vdev.minor); |
1360 | 1360 | ||
1361 | ent = create_proc_entry(name, S_IFREG|S_IRUGO|S_IWUSR, cpia_proc_root); | 1361 | ent = create_proc_entry(name, S_IFREG|S_IRUGO|S_IWUSR, cpia_proc_root); |
1362 | if (!ent) | 1362 | if (!ent) |
@@ -1376,12 +1376,12 @@ static void create_proc_cpia_cam(struct cam_data *cam) | |||
1376 | 1376 | ||
1377 | static void destroy_proc_cpia_cam(struct cam_data *cam) | 1377 | static void destroy_proc_cpia_cam(struct cam_data *cam) |
1378 | { | 1378 | { |
1379 | char name[7]; | 1379 | char name[5 + 1 + 10 + 1]; |
1380 | 1380 | ||
1381 | if (!cam || !cam->proc_entry) | 1381 | if (!cam || !cam->proc_entry) |
1382 | return; | 1382 | return; |
1383 | 1383 | ||
1384 | sprintf(name, "video%d", cam->vdev.minor); | 1384 | snprintf(name, sizeof(name), "video%d", cam->vdev.minor); |
1385 | remove_proc_entry(name, cpia_proc_root); | 1385 | remove_proc_entry(name, cpia_proc_root); |
1386 | cam->proc_entry = NULL; | 1386 | cam->proc_entry = NULL; |
1387 | } | 1387 | } |
@@ -3153,8 +3153,7 @@ static int reset_camera(struct cam_data *cam) | |||
3153 | 3153 | ||
3154 | static void put_cam(struct cpia_camera_ops* ops) | 3154 | static void put_cam(struct cpia_camera_ops* ops) |
3155 | { | 3155 | { |
3156 | if (ops->owner) | 3156 | module_put(ops->owner); |
3157 | module_put(ops->owner); | ||
3158 | } | 3157 | } |
3159 | 3158 | ||
3160 | /* ------------------------- V4L interface --------------------- */ | 3159 | /* ------------------------- V4L interface --------------------- */ |
diff --git a/drivers/media/video/cx2341x.c b/drivers/media/video/cx2341x.c index 2f5ca71e0261..d60cd5ecf821 100644 --- a/drivers/media/video/cx2341x.c +++ b/drivers/media/video/cx2341x.c | |||
@@ -56,7 +56,6 @@ const u32 cx2341x_mpeg_ctrls[] = { | |||
56 | V4L2_CID_MPEG_VIDEO_B_FRAMES, | 56 | V4L2_CID_MPEG_VIDEO_B_FRAMES, |
57 | V4L2_CID_MPEG_VIDEO_GOP_SIZE, | 57 | V4L2_CID_MPEG_VIDEO_GOP_SIZE, |
58 | V4L2_CID_MPEG_VIDEO_GOP_CLOSURE, | 58 | V4L2_CID_MPEG_VIDEO_GOP_CLOSURE, |
59 | V4L2_CID_MPEG_VIDEO_PULLDOWN, | ||
60 | V4L2_CID_MPEG_VIDEO_BITRATE_MODE, | 59 | V4L2_CID_MPEG_VIDEO_BITRATE_MODE, |
61 | V4L2_CID_MPEG_VIDEO_BITRATE, | 60 | V4L2_CID_MPEG_VIDEO_BITRATE, |
62 | V4L2_CID_MPEG_VIDEO_BITRATE_PEAK, | 61 | V4L2_CID_MPEG_VIDEO_BITRATE_PEAK, |
@@ -118,9 +117,6 @@ static int cx2341x_get_ctrl(struct cx2341x_mpeg_params *params, | |||
118 | case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE: | 117 | case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE: |
119 | ctrl->value = params->video_gop_closure; | 118 | ctrl->value = params->video_gop_closure; |
120 | break; | 119 | break; |
121 | case V4L2_CID_MPEG_VIDEO_PULLDOWN: | ||
122 | ctrl->value = params->video_pulldown; | ||
123 | break; | ||
124 | case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: | 120 | case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: |
125 | ctrl->value = params->video_bitrate_mode; | 121 | ctrl->value = params->video_bitrate_mode; |
126 | break; | 122 | break; |
@@ -231,9 +227,6 @@ static int cx2341x_set_ctrl(struct cx2341x_mpeg_params *params, | |||
231 | case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE: | 227 | case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE: |
232 | params->video_gop_closure = ctrl->value; | 228 | params->video_gop_closure = ctrl->value; |
233 | break; | 229 | break; |
234 | case V4L2_CID_MPEG_VIDEO_PULLDOWN: | ||
235 | params->video_pulldown = ctrl->value; | ||
236 | break; | ||
237 | case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: | 230 | case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: |
238 | /* MPEG-1 only allows CBR */ | 231 | /* MPEG-1 only allows CBR */ |
239 | if (params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1 && | 232 | if (params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1 && |
@@ -679,7 +672,6 @@ void cx2341x_fill_defaults(struct cx2341x_mpeg_params *p) | |||
679 | .video_b_frames = 2, | 672 | .video_b_frames = 2, |
680 | .video_gop_size = 12, | 673 | .video_gop_size = 12, |
681 | .video_gop_closure = 1, | 674 | .video_gop_closure = 1, |
682 | .video_pulldown = 0, | ||
683 | .video_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR, | 675 | .video_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR, |
684 | .video_bitrate = 6000000, | 676 | .video_bitrate = 6000000, |
685 | .video_bitrate_peak = 8000000, | 677 | .video_bitrate_peak = 8000000, |
@@ -783,10 +775,6 @@ int cx2341x_update(void *priv, cx2341x_mbox_func func, | |||
783 | err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_CLOSURE, 1, new->video_gop_closure); | 775 | err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_CLOSURE, 1, new->video_gop_closure); |
784 | if (err) return err; | 776 | if (err) return err; |
785 | } | 777 | } |
786 | if (old == NULL || old->video_pulldown != new->video_pulldown) { | ||
787 | err = cx2341x_api(priv, func, CX2341X_ENC_SET_3_2_PULLDOWN, 1, new->video_pulldown); | ||
788 | if (err) return err; | ||
789 | } | ||
790 | if (old == NULL || old->audio_properties != new->audio_properties) { | 778 | if (old == NULL || old->audio_properties != new->audio_properties) { |
791 | err = cx2341x_api(priv, func, CX2341X_ENC_SET_AUDIO_PROPERTIES, 1, new->audio_properties); | 779 | err = cx2341x_api(priv, func, CX2341X_ENC_SET_AUDIO_PROPERTIES, 1, new->audio_properties); |
792 | if (err) return err; | 780 | if (err) return err; |
@@ -888,11 +876,10 @@ void cx2341x_log_status(struct cx2341x_mpeg_params *p, const char *prefix) | |||
888 | printk(", Peak %d", p->video_bitrate_peak); | 876 | printk(", Peak %d", p->video_bitrate_peak); |
889 | } | 877 | } |
890 | printk("\n"); | 878 | printk("\n"); |
891 | printk(KERN_INFO "%s: Video: GOP Size %d, %d B-Frames, %sGOP Closure, %s3:2 Pulldown\n", | 879 | printk(KERN_INFO "%s: Video: GOP Size %d, %d B-Frames, %sGOP Closure\n", |
892 | prefix, | 880 | prefix, |
893 | p->video_gop_size, p->video_b_frames, | 881 | p->video_gop_size, p->video_b_frames, |
894 | p->video_gop_closure ? "" : "No ", | 882 | p->video_gop_closure ? "" : "No "); |
895 | p->video_pulldown ? "" : "No "); | ||
896 | if (p->video_temporal_decimation) { | 883 | if (p->video_temporal_decimation) { |
897 | printk(KERN_INFO "%s: Video: Temporal Decimation %d\n", | 884 | printk(KERN_INFO "%s: Video: Temporal Decimation %d\n", |
898 | prefix, p->video_temporal_decimation); | 885 | prefix, p->video_temporal_decimation); |
diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index 7bb7589a07c3..cc535ca713d2 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c | |||
@@ -628,17 +628,8 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, | |||
628 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 628 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
629 | /* ioctls to allow direct access to the | 629 | /* ioctls to allow direct access to the |
630 | * cx25840 registers for testing */ | 630 | * cx25840 registers for testing */ |
631 | case VIDIOC_INT_G_REGISTER: | 631 | case VIDIOC_DBG_G_REGISTER: |
632 | { | 632 | case VIDIOC_DBG_S_REGISTER: |
633 | struct v4l2_register *reg = arg; | ||
634 | |||
635 | if (reg->i2c_id != I2C_DRIVERID_CX25840) | ||
636 | return -EINVAL; | ||
637 | reg->val = cx25840_read(client, reg->reg & 0x0fff); | ||
638 | break; | ||
639 | } | ||
640 | |||
641 | case VIDIOC_INT_S_REGISTER: | ||
642 | { | 633 | { |
643 | struct v4l2_register *reg = arg; | 634 | struct v4l2_register *reg = arg; |
644 | 635 | ||
@@ -646,7 +637,10 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, | |||
646 | return -EINVAL; | 637 | return -EINVAL; |
647 | if (!capable(CAP_SYS_ADMIN)) | 638 | if (!capable(CAP_SYS_ADMIN)) |
648 | return -EPERM; | 639 | return -EPERM; |
649 | cx25840_write(client, reg->reg & 0x0fff, reg->val & 0xff); | 640 | if (cmd == VIDIOC_DBG_G_REGISTER) |
641 | reg->val = cx25840_read(client, reg->reg & 0x0fff); | ||
642 | else | ||
643 | cx25840_write(client, reg->reg & 0x0fff, reg->val & 0xff); | ||
650 | break; | 644 | break; |
651 | } | 645 | } |
652 | #endif | 646 | #endif |
@@ -893,9 +887,11 @@ static int cx25840_detect_client(struct i2c_adapter *adapter, int address, | |||
893 | return 0; | 887 | return 0; |
894 | } | 888 | } |
895 | 889 | ||
890 | /* Note: revision '(device_id & 0x0f) == 2' was never built. The | ||
891 | marking skips from 0x1 == 22 to 0x3 == 23. */ | ||
896 | v4l_info(client, "cx25%3x-2%x found @ 0x%x (%s)\n", | 892 | v4l_info(client, "cx25%3x-2%x found @ 0x%x (%s)\n", |
897 | (device_id & 0xfff0) >> 4, | 893 | (device_id & 0xfff0) >> 4, |
898 | (device_id & 0x0f) < 3 ? (device_id & 0x0f) + 1 : 3, | 894 | (device_id & 0x0f) < 3 ? (device_id & 0x0f) + 1 : (device_id & 0x0f), |
899 | address << 1, adapter->name); | 895 | address << 1, adapter->name); |
900 | 896 | ||
901 | i2c_set_clientdata(client, state); | 897 | i2c_set_clientdata(client, state); |
diff --git a/drivers/media/video/cx88/Makefile b/drivers/media/video/cx88/Makefile index 639c3b659d0e..532cee35eb3c 100644 --- a/drivers/media/video/cx88/Makefile +++ b/drivers/media/video/cx88/Makefile | |||
@@ -12,8 +12,3 @@ obj-$(CONFIG_VIDEO_CX88_VP3054) += cx88-vp3054-i2c.o | |||
12 | EXTRA_CFLAGS += -Idrivers/media/video | 12 | EXTRA_CFLAGS += -Idrivers/media/video |
13 | EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core | 13 | EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core |
14 | EXTRA_CFLAGS += -Idrivers/media/dvb/frontends | 14 | EXTRA_CFLAGS += -Idrivers/media/dvb/frontends |
15 | |||
16 | extra-cflags-$(CONFIG_VIDEO_BUF_DVB) += -DHAVE_VIDEO_BUF_DVB=1 | ||
17 | extra-cflags-$(CONFIG_VIDEO_CX88_VP3054)+= -DHAVE_VP3054_I2C=1 | ||
18 | |||
19 | EXTRA_CFLAGS += $(extra-cflags-y) $(extra-cflags-m) | ||
diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c index 9a7a2996f20f..a1be1e279df4 100644 --- a/drivers/media/video/cx88/cx88-blackbird.c +++ b/drivers/media/video/cx88/cx88-blackbird.c | |||
@@ -6,6 +6,9 @@ | |||
6 | * (c) 2004 Jelle Foks <jelle@foks.8m.com> | 6 | * (c) 2004 Jelle Foks <jelle@foks.8m.com> |
7 | * (c) 2004 Gerd Knorr <kraxel@bytesex.org> | 7 | * (c) 2004 Gerd Knorr <kraxel@bytesex.org> |
8 | * | 8 | * |
9 | * (c) 2005-2006 Mauro Carvalho Chehab <mchehab@infradead.org> | ||
10 | * - video_ioctl2 conversion | ||
11 | * | ||
9 | * Includes parts from the ivtv driver( http://ivtv.sourceforge.net/), | 12 | * Includes parts from the ivtv driver( http://ivtv.sourceforge.net/), |
10 | * | 13 | * |
11 | * This program is free software; you can redistribute it and/or modify | 14 | * This program is free software; you can redistribute it and/or modify |
@@ -520,7 +523,7 @@ static void blackbird_codec_settings(struct cx8802_dev *dev) | |||
520 | 523 | ||
521 | dev->params.width = dev->width; | 524 | dev->params.width = dev->width; |
522 | dev->params.height = dev->height; | 525 | dev->params.height = dev->height; |
523 | dev->params.is_50hz = (dev->core->tvnorm->id & V4L2_STD_625_50) != 0; | 526 | dev->params.is_50hz = (dev->core->tvnorm & V4L2_STD_625_50) != 0; |
524 | 527 | ||
525 | cx2341x_update(dev, blackbird_mbox_func, NULL, &dev->params); | 528 | cx2341x_update(dev, blackbird_mbox_func, NULL, &dev->params); |
526 | } | 529 | } |
@@ -710,8 +713,13 @@ static int blackbird_queryctrl(struct cx8802_dev *dev, struct v4l2_queryctrl *qc | |||
710 | return 0; | 713 | return 0; |
711 | } | 714 | } |
712 | 715 | ||
713 | static int blackbird_querymenu(struct cx8802_dev *dev, struct v4l2_querymenu *qmenu) | 716 | /* ------------------------------------------------------------------ */ |
717 | /* IOCTL Handlers */ | ||
718 | |||
719 | static int vidioc_querymenu (struct file *file, void *priv, | ||
720 | struct v4l2_querymenu *qmenu) | ||
714 | { | 721 | { |
722 | struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev; | ||
715 | struct v4l2_queryctrl qctrl; | 723 | struct v4l2_queryctrl qctrl; |
716 | 724 | ||
717 | qctrl.id = qmenu->id; | 725 | qctrl.id = qmenu->id; |
@@ -719,221 +727,347 @@ static int blackbird_querymenu(struct cx8802_dev *dev, struct v4l2_querymenu *qm | |||
719 | return v4l2_ctrl_query_menu(qmenu, &qctrl, cx2341x_ctrl_get_menu(qmenu->id)); | 727 | return v4l2_ctrl_query_menu(qmenu, &qctrl, cx2341x_ctrl_get_menu(qmenu->id)); |
720 | } | 728 | } |
721 | 729 | ||
722 | /* ------------------------------------------------------------------ */ | 730 | static int vidioc_querycap (struct file *file, void *priv, |
731 | struct v4l2_capability *cap) | ||
732 | { | ||
733 | struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev; | ||
734 | struct cx88_core *core = dev->core; | ||
723 | 735 | ||
724 | static int mpeg_do_ioctl(struct inode *inode, struct file *file, | 736 | strcpy(cap->driver, "cx88_blackbird"); |
725 | unsigned int cmd, void *arg) | 737 | strlcpy(cap->card, cx88_boards[core->board].name,sizeof(cap->card)); |
738 | sprintf(cap->bus_info,"PCI:%s",pci_name(dev->pci)); | ||
739 | cap->version = CX88_VERSION_CODE; | ||
740 | cap->capabilities = | ||
741 | V4L2_CAP_VIDEO_CAPTURE | | ||
742 | V4L2_CAP_READWRITE | | ||
743 | V4L2_CAP_STREAMING; | ||
744 | if (UNSET != core->tuner_type) | ||
745 | cap->capabilities |= V4L2_CAP_TUNER; | ||
746 | return 0; | ||
747 | } | ||
748 | |||
749 | static int vidioc_enum_fmt_cap (struct file *file, void *priv, | ||
750 | struct v4l2_fmtdesc *f) | ||
726 | { | 751 | { |
727 | struct cx8802_fh *fh = file->private_data; | 752 | if (f->index != 0) |
728 | struct cx8802_dev *dev = fh->dev; | 753 | return -EINVAL; |
754 | |||
755 | strlcpy(f->description, "MPEG", sizeof(f->description)); | ||
756 | f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
757 | f->pixelformat = V4L2_PIX_FMT_MPEG; | ||
758 | return 0; | ||
759 | } | ||
760 | |||
761 | static int vidioc_g_fmt_cap (struct file *file, void *priv, | ||
762 | struct v4l2_format *f) | ||
763 | { | ||
764 | struct cx8802_fh *fh = priv; | ||
765 | struct cx8802_dev *dev = fh->dev; | ||
766 | |||
767 | f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
768 | f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; | ||
769 | f->fmt.pix.bytesperline = 0; | ||
770 | f->fmt.pix.sizeimage = dev->ts_packet_size * dev->ts_packet_count; /* 188 * 4 * 1024; */ | ||
771 | f->fmt.pix.colorspace = 0; | ||
772 | f->fmt.pix.width = dev->width; | ||
773 | f->fmt.pix.height = dev->height; | ||
774 | f->fmt.pix.field = fh->mpegq.field; | ||
775 | dprintk(0,"VIDIOC_G_FMT: w: %d, h: %d, f: %d\n", | ||
776 | dev->width, dev->height, fh->mpegq.field ); | ||
777 | return 0; | ||
778 | } | ||
779 | |||
780 | static int vidioc_try_fmt_cap (struct file *file, void *priv, | ||
781 | struct v4l2_format *f) | ||
782 | { | ||
783 | struct cx8802_fh *fh = priv; | ||
784 | struct cx8802_dev *dev = fh->dev; | ||
785 | |||
786 | f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
787 | f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; | ||
788 | f->fmt.pix.bytesperline = 0; | ||
789 | f->fmt.pix.sizeimage = dev->ts_packet_size * dev->ts_packet_count; /* 188 * 4 * 1024; */; | ||
790 | f->fmt.pix.colorspace = 0; | ||
791 | dprintk(0,"VIDIOC_TRY_FMT: w: %d, h: %d, f: %d\n", | ||
792 | dev->width, dev->height, fh->mpegq.field ); | ||
793 | return 0; | ||
794 | } | ||
795 | |||
796 | static int vidioc_s_fmt_cap (struct file *file, void *priv, | ||
797 | struct v4l2_format *f) | ||
798 | { | ||
799 | struct cx8802_fh *fh = priv; | ||
800 | struct cx8802_dev *dev = fh->dev; | ||
729 | struct cx88_core *core = dev->core; | 801 | struct cx88_core *core = dev->core; |
730 | 802 | ||
731 | if (debug > 1) | 803 | f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
732 | v4l_print_ioctl(core->name,cmd); | 804 | f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; |
733 | 805 | f->fmt.pix.bytesperline = 0; | |
734 | switch (cmd) { | 806 | f->fmt.pix.sizeimage = dev->ts_packet_size * dev->ts_packet_count; /* 188 * 4 * 1024; */; |
735 | 807 | f->fmt.pix.colorspace = 0; | |
736 | /* --- capabilities ------------------------------------------ */ | 808 | dev->width = f->fmt.pix.width; |
737 | case VIDIOC_QUERYCAP: | 809 | dev->height = f->fmt.pix.height; |
738 | { | 810 | fh->mpegq.field = f->fmt.pix.field; |
739 | struct v4l2_capability *cap = arg; | 811 | cx88_set_scale(core, f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field); |
740 | 812 | blackbird_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0, | |
741 | memset(cap,0,sizeof(*cap)); | 813 | f->fmt.pix.height, f->fmt.pix.width); |
742 | strcpy(cap->driver, "cx88_blackbird"); | 814 | dprintk(0,"VIDIOC_S_FMT: w: %d, h: %d, f: %d\n", |
743 | strlcpy(cap->card, cx88_boards[core->board].name,sizeof(cap->card)); | 815 | f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field ); |
744 | sprintf(cap->bus_info,"PCI:%s",pci_name(dev->pci)); | 816 | return 0; |
745 | cap->version = CX88_VERSION_CODE; | 817 | } |
746 | cap->capabilities = | ||
747 | V4L2_CAP_VIDEO_CAPTURE | | ||
748 | V4L2_CAP_READWRITE | | ||
749 | V4L2_CAP_STREAMING | | ||
750 | 0; | ||
751 | if (UNSET != core->tuner_type) | ||
752 | cap->capabilities |= V4L2_CAP_TUNER; | ||
753 | 818 | ||
754 | return 0; | 819 | static int vidioc_reqbufs (struct file *file, void *priv, struct v4l2_requestbuffers *p) |
755 | } | 820 | { |
821 | struct cx8802_fh *fh = priv; | ||
822 | return (videobuf_reqbufs(&fh->mpegq, p)); | ||
823 | } | ||
756 | 824 | ||
757 | /* --- capture ioctls ---------------------------------------- */ | 825 | static int vidioc_querybuf (struct file *file, void *priv, struct v4l2_buffer *p) |
758 | case VIDIOC_ENUM_FMT: | 826 | { |
759 | { | 827 | struct cx8802_fh *fh = priv; |
760 | struct v4l2_fmtdesc *f = arg; | 828 | return (videobuf_querybuf(&fh->mpegq, p)); |
761 | int index; | 829 | } |
762 | |||
763 | index = f->index; | ||
764 | if (index != 0) | ||
765 | return -EINVAL; | ||
766 | |||
767 | memset(f,0,sizeof(*f)); | ||
768 | f->index = index; | ||
769 | strlcpy(f->description, "MPEG", sizeof(f->description)); | ||
770 | f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
771 | f->pixelformat = V4L2_PIX_FMT_MPEG; | ||
772 | return 0; | ||
773 | } | ||
774 | case VIDIOC_G_FMT: | ||
775 | { | ||
776 | struct v4l2_format *f = arg; | ||
777 | |||
778 | memset(f,0,sizeof(*f)); | ||
779 | f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
780 | f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; | ||
781 | f->fmt.pix.bytesperline = 0; | ||
782 | f->fmt.pix.sizeimage = dev->ts_packet_size * dev->ts_packet_count; /* 188 * 4 * 1024; */ | ||
783 | f->fmt.pix.colorspace = 0; | ||
784 | f->fmt.pix.width = dev->width; | ||
785 | f->fmt.pix.height = dev->height; | ||
786 | f->fmt.pix.field = fh->mpegq.field; | ||
787 | dprintk(0,"VIDIOC_G_FMT: w: %d, h: %d, f: %d\n", | ||
788 | dev->width, dev->height, fh->mpegq.field ); | ||
789 | return 0; | ||
790 | } | ||
791 | case VIDIOC_TRY_FMT: | ||
792 | { | ||
793 | struct v4l2_format *f = arg; | ||
794 | |||
795 | f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
796 | f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; | ||
797 | f->fmt.pix.bytesperline = 0; | ||
798 | f->fmt.pix.sizeimage = dev->ts_packet_size * dev->ts_packet_count; /* 188 * 4 * 1024; */; | ||
799 | f->fmt.pix.colorspace = 0; | ||
800 | dprintk(0,"VIDIOC_TRY_FMT: w: %d, h: %d, f: %d\n", | ||
801 | dev->width, dev->height, fh->mpegq.field ); | ||
802 | return 0; | ||
803 | } | ||
804 | case VIDIOC_S_FMT: | ||
805 | { | ||
806 | struct v4l2_format *f = arg; | ||
807 | |||
808 | f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
809 | f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; | ||
810 | f->fmt.pix.bytesperline = 0; | ||
811 | f->fmt.pix.sizeimage = dev->ts_packet_size * dev->ts_packet_count; /* 188 * 4 * 1024; */; | ||
812 | f->fmt.pix.colorspace = 0; | ||
813 | dprintk(0,"VIDIOC_S_FMT: w: %d, h: %d, f: %d\n", | ||
814 | f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field ); | ||
815 | return 0; | ||
816 | } | ||
817 | 830 | ||
818 | /* --- streaming capture ------------------------------------- */ | 831 | static int vidioc_qbuf (struct file *file, void *priv, struct v4l2_buffer *p) |
819 | case VIDIOC_REQBUFS: | 832 | { |
820 | return videobuf_reqbufs(&fh->mpegq, arg); | 833 | struct cx8802_fh *fh = priv; |
834 | return (videobuf_qbuf(&fh->mpegq, p)); | ||
835 | } | ||
821 | 836 | ||
822 | case VIDIOC_QUERYBUF: | 837 | static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *p) |
823 | return videobuf_querybuf(&fh->mpegq, arg); | 838 | { |
839 | struct cx8802_fh *fh = priv; | ||
840 | return (videobuf_dqbuf(&fh->mpegq, p, | ||
841 | file->f_flags & O_NONBLOCK)); | ||
842 | } | ||
824 | 843 | ||
825 | case VIDIOC_QBUF: | 844 | static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) |
826 | return videobuf_qbuf(&fh->mpegq, arg); | 845 | { |
846 | struct cx8802_fh *fh = priv; | ||
847 | return videobuf_streamon(&fh->mpegq); | ||
848 | } | ||
827 | 849 | ||
828 | case VIDIOC_DQBUF: | 850 | static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) |
829 | return videobuf_dqbuf(&fh->mpegq, arg, | 851 | { |
830 | file->f_flags & O_NONBLOCK); | 852 | struct cx8802_fh *fh = priv; |
853 | return videobuf_streamoff(&fh->mpegq); | ||
854 | } | ||
831 | 855 | ||
832 | case VIDIOC_STREAMON: | 856 | static int vidioc_g_mpegcomp (struct file *file, void *fh, |
833 | return videobuf_streamon(&fh->mpegq); | 857 | struct v4l2_mpeg_compression *f) |
858 | { | ||
859 | printk(KERN_WARNING "VIDIOC_G_MPEGCOMP is obsolete. " | ||
860 | "Replace with VIDIOC_G_EXT_CTRLS!"); | ||
861 | memcpy(f,&default_mpeg_params,sizeof(*f)); | ||
862 | return 0; | ||
863 | } | ||
834 | 864 | ||
835 | case VIDIOC_STREAMOFF: | 865 | static int vidioc_s_mpegcomp (struct file *file, void *fh, |
836 | return videobuf_streamoff(&fh->mpegq); | 866 | struct v4l2_mpeg_compression *f) |
867 | { | ||
868 | printk(KERN_WARNING "VIDIOC_S_MPEGCOMP is obsolete. " | ||
869 | "Replace with VIDIOC_S_EXT_CTRLS!"); | ||
870 | return 0; | ||
871 | } | ||
837 | 872 | ||
838 | /* --- mpeg compression -------------------------------------- */ | 873 | static int vidioc_g_ext_ctrls (struct file *file, void *priv, |
839 | case VIDIOC_G_MPEGCOMP: | 874 | struct v4l2_ext_controls *f) |
840 | { | 875 | { |
841 | struct v4l2_mpeg_compression *f = arg; | 876 | struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev; |
842 | 877 | ||
843 | printk(KERN_WARNING "VIDIOC_G_MPEGCOMP is obsolete. " | 878 | if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG) |
844 | "Replace with VIDIOC_G_EXT_CTRLS!"); | 879 | return -EINVAL; |
845 | memcpy(f,&default_mpeg_params,sizeof(*f)); | 880 | return cx2341x_ext_ctrls(&dev->params, f, VIDIOC_G_EXT_CTRLS); |
846 | return 0; | 881 | } |
847 | } | ||
848 | case VIDIOC_S_MPEGCOMP: | ||
849 | printk(KERN_WARNING "VIDIOC_S_MPEGCOMP is obsolete. " | ||
850 | "Replace with VIDIOC_S_EXT_CTRLS!"); | ||
851 | return 0; | ||
852 | case VIDIOC_G_EXT_CTRLS: | ||
853 | { | ||
854 | struct v4l2_ext_controls *f = arg; | ||
855 | 882 | ||
856 | if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG) | 883 | static int vidioc_s_ext_ctrls (struct file *file, void *priv, |
857 | return -EINVAL; | 884 | struct v4l2_ext_controls *f) |
858 | return cx2341x_ext_ctrls(&dev->params, f, cmd); | 885 | { |
859 | } | 886 | struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev; |
860 | case VIDIOC_S_EXT_CTRLS: | 887 | struct cx2341x_mpeg_params p; |
861 | case VIDIOC_TRY_EXT_CTRLS: | 888 | int err; |
862 | { | 889 | |
863 | struct v4l2_ext_controls *f = arg; | 890 | if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG) |
864 | struct cx2341x_mpeg_params p; | 891 | return -EINVAL; |
865 | int err; | 892 | p = dev->params; |
866 | 893 | err = cx2341x_ext_ctrls(&p, f, VIDIOC_S_EXT_CTRLS); | |
867 | if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG) | 894 | if (!err) { |
868 | return -EINVAL; | 895 | err = cx2341x_update(dev, blackbird_mbox_func, &dev->params, &p); |
869 | p = dev->params; | 896 | dev->params = p; |
870 | err = cx2341x_ext_ctrls(&p, f, cmd); | ||
871 | if (err == 0 && cmd == VIDIOC_S_EXT_CTRLS) { | ||
872 | err = cx2341x_update(dev, blackbird_mbox_func, &dev->params, &p); | ||
873 | dev->params = p; | ||
874 | } | ||
875 | return err; | ||
876 | } | ||
877 | case VIDIOC_S_FREQUENCY: | ||
878 | { | ||
879 | blackbird_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0, | ||
880 | BLACKBIRD_END_NOW, | ||
881 | BLACKBIRD_MPEG_CAPTURE, | ||
882 | BLACKBIRD_RAW_BITS_NONE); | ||
883 | |||
884 | cx88_do_ioctl(inode, file, 0, dev->core, cmd, arg, cx88_ioctl_hook); | ||
885 | |||
886 | blackbird_initialize_codec(dev); | ||
887 | cx88_set_scale(dev->core, dev->width, dev->height, | ||
888 | fh->mpegq.field); | ||
889 | return 0; | ||
890 | } | 897 | } |
891 | case VIDIOC_LOG_STATUS: | 898 | return err; |
892 | { | 899 | } |
893 | char name[32 + 2]; | 900 | |
894 | 901 | static int vidioc_try_ext_ctrls (struct file *file, void *priv, | |
895 | snprintf(name, sizeof(name), "%s/2", core->name); | 902 | struct v4l2_ext_controls *f) |
896 | printk("%s/2: ============ START LOG STATUS ============\n", | 903 | { |
897 | core->name); | 904 | struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev; |
898 | cx88_call_i2c_clients(core, VIDIOC_LOG_STATUS, NULL); | 905 | struct cx2341x_mpeg_params p; |
899 | cx2341x_log_status(&dev->params, name); | 906 | int err; |
900 | printk("%s/2: ============= END LOG STATUS =============\n", | 907 | |
901 | core->name); | 908 | if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG) |
909 | return -EINVAL; | ||
910 | p = dev->params; | ||
911 | err = cx2341x_ext_ctrls(&p, f, VIDIOC_TRY_EXT_CTRLS); | ||
912 | |||
913 | return err; | ||
914 | } | ||
915 | |||
916 | static int vidioc_s_frequency (struct file *file, void *priv, | ||
917 | struct v4l2_frequency *f) | ||
918 | { | ||
919 | struct cx8802_fh *fh = priv; | ||
920 | struct cx8802_dev *dev = fh->dev; | ||
921 | struct cx88_core *core = dev->core; | ||
922 | |||
923 | blackbird_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0, | ||
924 | BLACKBIRD_END_NOW, | ||
925 | BLACKBIRD_MPEG_CAPTURE, | ||
926 | BLACKBIRD_RAW_BITS_NONE); | ||
927 | cx88_set_freq (core,f); | ||
928 | blackbird_initialize_codec(dev); | ||
929 | cx88_set_scale(dev->core, dev->width, dev->height, | ||
930 | fh->mpegq.field); | ||
931 | return 0; | ||
932 | } | ||
933 | |||
934 | static int vidioc_log_status (struct file *file, void *priv) | ||
935 | { | ||
936 | struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev; | ||
937 | struct cx88_core *core = dev->core; | ||
938 | char name[32 + 2]; | ||
939 | |||
940 | snprintf(name, sizeof(name), "%s/2", core->name); | ||
941 | printk("%s/2: ============ START LOG STATUS ============\n", | ||
942 | core->name); | ||
943 | cx88_call_i2c_clients(core, VIDIOC_LOG_STATUS, NULL); | ||
944 | cx2341x_log_status(&dev->params, name); | ||
945 | printk("%s/2: ============= END LOG STATUS =============\n", | ||
946 | core->name); | ||
947 | return 0; | ||
948 | } | ||
949 | |||
950 | static int vidioc_queryctrl (struct file *file, void *priv, | ||
951 | struct v4l2_queryctrl *qctrl) | ||
952 | { | ||
953 | struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev; | ||
954 | |||
955 | if (blackbird_queryctrl(dev, qctrl) == 0) | ||
902 | return 0; | 956 | return 0; |
903 | } | ||
904 | case VIDIOC_QUERYMENU: | ||
905 | return blackbird_querymenu(dev, arg); | ||
906 | case VIDIOC_QUERYCTRL: | ||
907 | { | ||
908 | struct v4l2_queryctrl *c = arg; | ||
909 | 957 | ||
910 | if (blackbird_queryctrl(dev, c) == 0) | 958 | qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id); |
911 | return 0; | 959 | if (unlikely(qctrl->id == 0)) |
912 | return cx88_do_ioctl(inode, file, 0, dev->core, cmd, arg, mpeg_do_ioctl); | 960 | return -EINVAL; |
913 | } | 961 | return cx8800_ctrl_query(qctrl); |
962 | } | ||
914 | 963 | ||
915 | default: | 964 | static int vidioc_enum_input (struct file *file, void *priv, |
916 | return cx88_do_ioctl(inode, file, 0, dev->core, cmd, arg, cx88_ioctl_hook); | 965 | struct v4l2_input *i) |
917 | } | 966 | { |
967 | struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core; | ||
968 | return cx88_enum_input (core,i); | ||
969 | } | ||
970 | |||
971 | static int vidioc_g_ctrl (struct file *file, void *priv, | ||
972 | struct v4l2_control *ctl) | ||
973 | { | ||
974 | struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core; | ||
975 | return | ||
976 | cx88_get_control(core,ctl); | ||
977 | } | ||
978 | |||
979 | static int vidioc_s_ctrl (struct file *file, void *priv, | ||
980 | struct v4l2_control *ctl) | ||
981 | { | ||
982 | struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core; | ||
983 | return | ||
984 | cx88_set_control(core,ctl); | ||
985 | } | ||
986 | |||
987 | static int vidioc_g_frequency (struct file *file, void *priv, | ||
988 | struct v4l2_frequency *f) | ||
989 | { | ||
990 | struct cx8802_fh *fh = priv; | ||
991 | struct cx88_core *core = fh->dev->core; | ||
992 | |||
993 | if (unlikely(UNSET == core->tuner_type)) | ||
994 | return -EINVAL; | ||
995 | |||
996 | f->type = V4L2_TUNER_ANALOG_TV; | ||
997 | f->frequency = core->freq; | ||
998 | cx88_call_i2c_clients(core,VIDIOC_G_FREQUENCY,f); | ||
999 | |||
1000 | return 0; | ||
1001 | } | ||
1002 | |||
1003 | static int vidioc_g_input (struct file *file, void *priv, unsigned int *i) | ||
1004 | { | ||
1005 | struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core; | ||
1006 | |||
1007 | *i = core->input; | ||
1008 | return 0; | ||
1009 | } | ||
1010 | |||
1011 | static int vidioc_s_input (struct file *file, void *priv, unsigned int i) | ||
1012 | { | ||
1013 | struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core; | ||
1014 | |||
1015 | if (i >= 4) | ||
1016 | return -EINVAL; | ||
1017 | |||
1018 | mutex_lock(&core->lock); | ||
1019 | cx88_newstation(core); | ||
1020 | cx88_video_mux(core,i); | ||
1021 | mutex_unlock(&core->lock); | ||
918 | return 0; | 1022 | return 0; |
919 | } | 1023 | } |
920 | 1024 | ||
921 | int (*cx88_ioctl_hook)(struct inode *inode, struct file *file, | 1025 | static int vidioc_g_tuner (struct file *file, void *priv, |
922 | unsigned int cmd, void *arg); | 1026 | struct v4l2_tuner *t) |
923 | unsigned int (*cx88_ioctl_translator)(unsigned int cmd); | 1027 | { |
1028 | struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core; | ||
1029 | u32 reg; | ||
1030 | |||
1031 | if (unlikely(UNSET == core->tuner_type)) | ||
1032 | return -EINVAL; | ||
1033 | |||
1034 | strcpy(t->name, "Television"); | ||
1035 | t->type = V4L2_TUNER_ANALOG_TV; | ||
1036 | t->capability = V4L2_TUNER_CAP_NORM; | ||
1037 | t->rangehigh = 0xffffffffUL; | ||
1038 | |||
1039 | cx88_get_stereo(core ,t); | ||
1040 | reg = cx_read(MO_DEVICE_STATUS); | ||
1041 | t->signal = (reg & (1<<5)) ? 0xffff : 0x0000; | ||
1042 | return 0; | ||
1043 | } | ||
924 | 1044 | ||
925 | static unsigned int mpeg_translate_ioctl(unsigned int cmd) | 1045 | static int vidioc_s_tuner (struct file *file, void *priv, |
1046 | struct v4l2_tuner *t) | ||
926 | { | 1047 | { |
927 | return cmd; | 1048 | struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core; |
1049 | |||
1050 | if (UNSET == core->tuner_type) | ||
1051 | return -EINVAL; | ||
1052 | if (0 != t->index) | ||
1053 | return -EINVAL; | ||
1054 | |||
1055 | cx88_set_stereo(core, t->audmode, 1); | ||
1056 | return 0; | ||
928 | } | 1057 | } |
929 | 1058 | ||
930 | static int mpeg_ioctl(struct inode *inode, struct file *file, | 1059 | static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *id) |
931 | unsigned int cmd, unsigned long arg) | ||
932 | { | 1060 | { |
933 | cmd = cx88_ioctl_translator( cmd ); | 1061 | struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core; |
934 | return video_usercopy(inode, file, cmd, arg, cx88_ioctl_hook); | 1062 | |
1063 | mutex_lock(&core->lock); | ||
1064 | cx88_set_tvnorm(core,*id); | ||
1065 | mutex_unlock(&core->lock); | ||
1066 | return 0; | ||
935 | } | 1067 | } |
936 | 1068 | ||
1069 | /* FIXME: cx88_ioctl_hook not implemented */ | ||
1070 | |||
937 | static int mpeg_open(struct inode *inode, struct file *file) | 1071 | static int mpeg_open(struct inode *inode, struct file *file) |
938 | { | 1072 | { |
939 | int minor = iminor(inode); | 1073 | int minor = iminor(inode); |
@@ -1059,17 +1193,47 @@ static const struct file_operations mpeg_fops = | |||
1059 | .read = mpeg_read, | 1193 | .read = mpeg_read, |
1060 | .poll = mpeg_poll, | 1194 | .poll = mpeg_poll, |
1061 | .mmap = mpeg_mmap, | 1195 | .mmap = mpeg_mmap, |
1062 | .ioctl = mpeg_ioctl, | 1196 | .ioctl = video_ioctl2, |
1063 | .llseek = no_llseek, | 1197 | .llseek = no_llseek, |
1064 | }; | 1198 | }; |
1065 | 1199 | ||
1066 | static struct video_device cx8802_mpeg_template = | 1200 | static struct video_device cx8802_mpeg_template = |
1067 | { | 1201 | { |
1068 | .name = "cx8802", | 1202 | .name = "cx8802", |
1069 | .type = VID_TYPE_CAPTURE|VID_TYPE_TUNER|VID_TYPE_SCALES|VID_TYPE_MPEG_ENCODER, | 1203 | .type = VID_TYPE_CAPTURE|VID_TYPE_TUNER|VID_TYPE_SCALES|VID_TYPE_MPEG_ENCODER, |
1070 | .hardware = 0, | 1204 | .fops = &mpeg_fops, |
1071 | .fops = &mpeg_fops, | 1205 | .minor = -1, |
1072 | .minor = -1, | 1206 | .vidioc_querymenu = vidioc_querymenu, |
1207 | .vidioc_querycap = vidioc_querycap, | ||
1208 | .vidioc_enum_fmt_cap = vidioc_enum_fmt_cap, | ||
1209 | .vidioc_g_fmt_cap = vidioc_g_fmt_cap, | ||
1210 | .vidioc_try_fmt_cap = vidioc_try_fmt_cap, | ||
1211 | .vidioc_s_fmt_cap = vidioc_s_fmt_cap, | ||
1212 | .vidioc_reqbufs = vidioc_reqbufs, | ||
1213 | .vidioc_querybuf = vidioc_querybuf, | ||
1214 | .vidioc_qbuf = vidioc_qbuf, | ||
1215 | .vidioc_dqbuf = vidioc_dqbuf, | ||
1216 | .vidioc_streamon = vidioc_streamon, | ||
1217 | .vidioc_streamoff = vidioc_streamoff, | ||
1218 | .vidioc_g_mpegcomp = vidioc_g_mpegcomp, | ||
1219 | .vidioc_s_mpegcomp = vidioc_s_mpegcomp, | ||
1220 | .vidioc_g_ext_ctrls = vidioc_g_ext_ctrls, | ||
1221 | .vidioc_s_ext_ctrls = vidioc_s_ext_ctrls, | ||
1222 | .vidioc_try_ext_ctrls = vidioc_try_ext_ctrls, | ||
1223 | .vidioc_s_frequency = vidioc_s_frequency, | ||
1224 | .vidioc_log_status = vidioc_log_status, | ||
1225 | .vidioc_queryctrl = vidioc_queryctrl, | ||
1226 | .vidioc_enum_input = vidioc_enum_input, | ||
1227 | .vidioc_g_ctrl = vidioc_g_ctrl, | ||
1228 | .vidioc_s_ctrl = vidioc_s_ctrl, | ||
1229 | .vidioc_g_frequency = vidioc_g_frequency, | ||
1230 | .vidioc_g_input = vidioc_g_input, | ||
1231 | .vidioc_s_input = vidioc_s_input, | ||
1232 | .vidioc_g_tuner = vidioc_g_tuner, | ||
1233 | .vidioc_s_tuner = vidioc_s_tuner, | ||
1234 | .vidioc_s_std = vidioc_s_std, | ||
1235 | .tvnorms = CX88_NORMS, | ||
1236 | .current_norm = V4L2_STD_NTSC_M, | ||
1073 | }; | 1237 | }; |
1074 | 1238 | ||
1075 | /* ------------------------------------------------------------------ */ | 1239 | /* ------------------------------------------------------------------ */ |
@@ -1164,7 +1328,9 @@ static int cx8802_blackbird_probe(struct cx8802_driver *drv) | |||
1164 | cx2341x_fill_defaults(&dev->params); | 1328 | cx2341x_fill_defaults(&dev->params); |
1165 | dev->params.port = CX2341X_PORT_STREAMING; | 1329 | dev->params.port = CX2341X_PORT_STREAMING; |
1166 | 1330 | ||
1167 | if (core->tvnorm->id & V4L2_STD_525_60) { | 1331 | cx8802_mpeg_template.current_norm = core->tvnorm; |
1332 | |||
1333 | if (core->tvnorm & V4L2_STD_525_60) { | ||
1168 | dev->height = 480; | 1334 | dev->height = 480; |
1169 | } else { | 1335 | } else { |
1170 | dev->height = 576; | 1336 | dev->height = 576; |
@@ -1178,6 +1344,11 @@ static int cx8802_blackbird_probe(struct cx8802_driver *drv) | |||
1178 | blackbird_register_video(dev); | 1344 | blackbird_register_video(dev); |
1179 | 1345 | ||
1180 | /* initial device configuration: needed ? */ | 1346 | /* initial device configuration: needed ? */ |
1347 | mutex_lock(&dev->core->lock); | ||
1348 | // init_controls(core); | ||
1349 | cx88_set_tvnorm(core,core->tvnorm); | ||
1350 | cx88_video_mux(core,0); | ||
1351 | mutex_unlock(&dev->core->lock); | ||
1181 | 1352 | ||
1182 | return 0; | 1353 | return 0; |
1183 | 1354 | ||
@@ -1212,8 +1383,6 @@ static int blackbird_init(void) | |||
1212 | printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n", | 1383 | printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n", |
1213 | SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100); | 1384 | SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100); |
1214 | #endif | 1385 | #endif |
1215 | cx88_ioctl_hook = mpeg_do_ioctl; | ||
1216 | cx88_ioctl_translator = mpeg_translate_ioctl; | ||
1217 | return cx8802_register_driver(&cx8802_blackbird_driver); | 1386 | return cx8802_register_driver(&cx8802_blackbird_driver); |
1218 | } | 1387 | } |
1219 | 1388 | ||
@@ -1225,8 +1394,8 @@ static void blackbird_fini(void) | |||
1225 | module_init(blackbird_init); | 1394 | module_init(blackbird_init); |
1226 | module_exit(blackbird_fini); | 1395 | module_exit(blackbird_fini); |
1227 | 1396 | ||
1228 | EXPORT_SYMBOL(cx88_ioctl_hook); | 1397 | module_param_named(video_debug,cx8802_mpeg_template.debug, int, 0644); |
1229 | EXPORT_SYMBOL(cx88_ioctl_translator); | 1398 | MODULE_PARM_DESC(debug,"enable debug messages [video]"); |
1230 | 1399 | ||
1231 | /* ----------------------------------------------------------- */ | 1400 | /* ----------------------------------------------------------- */ |
1232 | /* | 1401 | /* |
diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 434b78ab37d8..65e9d8096b74 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c | |||
@@ -764,6 +764,12 @@ struct cx88_board cx88_boards[] = { | |||
764 | .input = {{ | 764 | .input = {{ |
765 | .type = CX88_VMUX_DVB, | 765 | .type = CX88_VMUX_DVB, |
766 | .vmux = 0, | 766 | .vmux = 0, |
767 | },{ | ||
768 | .type = CX88_VMUX_COMPOSITE1, | ||
769 | .vmux = 2, | ||
770 | },{ | ||
771 | .type = CX88_VMUX_SVIDEO, | ||
772 | .vmux = 2, | ||
767 | }}, | 773 | }}, |
768 | .mpeg = CX88_MPEG_DVB, | 774 | .mpeg = CX88_MPEG_DVB, |
769 | }, | 775 | }, |
diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c index 18997361c75a..d86813be56de 100644 --- a/drivers/media/video/cx88/cx88-core.c +++ b/drivers/media/video/cx88/cx88-core.c | |||
@@ -5,6 +5,11 @@ | |||
5 | * | 5 | * |
6 | * (c) 2003 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs] | 6 | * (c) 2003 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs] |
7 | * | 7 | * |
8 | * (c) 2005-2006 Mauro Carvalho Chehab <mchehab@infradead.org> | ||
9 | * - Multituner support | ||
10 | * - video_ioctl2 conversion | ||
11 | * - PAL/M fixes | ||
12 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | 13 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License as published by | 14 | * it under the terms of the GNU General Public License as published by |
10 | * the Free Software Foundation; either version 2 of the License, or | 15 | * the Free Software Foundation; either version 2 of the License, or |
@@ -631,30 +636,30 @@ int cx88_reset(struct cx88_core *core) | |||
631 | 636 | ||
632 | /* ------------------------------------------------------------------ */ | 637 | /* ------------------------------------------------------------------ */ |
633 | 638 | ||
634 | static unsigned int inline norm_swidth(struct cx88_tvnorm *norm) | 639 | static unsigned int inline norm_swidth(v4l2_std_id norm) |
635 | { | 640 | { |
636 | return (norm->id & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 754 : 922; | 641 | return (norm & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 754 : 922; |
637 | } | 642 | } |
638 | 643 | ||
639 | static unsigned int inline norm_hdelay(struct cx88_tvnorm *norm) | 644 | static unsigned int inline norm_hdelay(v4l2_std_id norm) |
640 | { | 645 | { |
641 | return (norm->id & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 135 : 186; | 646 | return (norm & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 135 : 186; |
642 | } | 647 | } |
643 | 648 | ||
644 | static unsigned int inline norm_vdelay(struct cx88_tvnorm *norm) | 649 | static unsigned int inline norm_vdelay(v4l2_std_id norm) |
645 | { | 650 | { |
646 | return (norm->id & V4L2_STD_625_50) ? 0x24 : 0x18; | 651 | return (norm & V4L2_STD_625_50) ? 0x24 : 0x18; |
647 | } | 652 | } |
648 | 653 | ||
649 | static unsigned int inline norm_fsc8(struct cx88_tvnorm *norm) | 654 | static unsigned int inline norm_fsc8(v4l2_std_id norm) |
650 | { | 655 | { |
651 | if (norm->id & V4L2_STD_PAL_M) | 656 | if (norm & V4L2_STD_PAL_M) |
652 | return 28604892; // 3.575611 MHz | 657 | return 28604892; // 3.575611 MHz |
653 | 658 | ||
654 | if (norm->id & (V4L2_STD_PAL_Nc)) | 659 | if (norm & (V4L2_STD_PAL_Nc)) |
655 | return 28656448; // 3.582056 MHz | 660 | return 28656448; // 3.582056 MHz |
656 | 661 | ||
657 | if (norm->id & V4L2_STD_NTSC) // All NTSC/M and variants | 662 | if (norm & V4L2_STD_NTSC) // All NTSC/M and variants |
658 | return 28636360; // 3.57954545 MHz +/- 10 Hz | 663 | return 28636360; // 3.57954545 MHz +/- 10 Hz |
659 | 664 | ||
660 | /* SECAM have also different sub carrier for chroma, | 665 | /* SECAM have also different sub carrier for chroma, |
@@ -666,20 +671,20 @@ static unsigned int inline norm_fsc8(struct cx88_tvnorm *norm) | |||
666 | return 35468950; // 4.43361875 MHz +/- 5 Hz | 671 | return 35468950; // 4.43361875 MHz +/- 5 Hz |
667 | } | 672 | } |
668 | 673 | ||
669 | static unsigned int inline norm_htotal(struct cx88_tvnorm *norm) | 674 | static unsigned int inline norm_htotal(v4l2_std_id norm) |
670 | { | 675 | { |
671 | 676 | ||
672 | unsigned int fsc4=norm_fsc8(norm)/2; | 677 | unsigned int fsc4=norm_fsc8(norm)/2; |
673 | 678 | ||
674 | /* returns 4*FSC / vtotal / frames per seconds */ | 679 | /* returns 4*FSC / vtotal / frames per seconds */ |
675 | return (norm->id & V4L2_STD_625_50) ? | 680 | return (norm & V4L2_STD_625_50) ? |
676 | ((fsc4+312)/625+12)/25 : | 681 | ((fsc4+312)/625+12)/25 : |
677 | ((fsc4+262)/525*1001+15000)/30000; | 682 | ((fsc4+262)/525*1001+15000)/30000; |
678 | } | 683 | } |
679 | 684 | ||
680 | static unsigned int inline norm_vbipack(struct cx88_tvnorm *norm) | 685 | static unsigned int inline norm_vbipack(v4l2_std_id norm) |
681 | { | 686 | { |
682 | return (norm->id & V4L2_STD_625_50) ? 511 : 400; | 687 | return (norm & V4L2_STD_625_50) ? 511 : 400; |
683 | } | 688 | } |
684 | 689 | ||
685 | int cx88_set_scale(struct cx88_core *core, unsigned int width, unsigned int height, | 690 | int cx88_set_scale(struct cx88_core *core, unsigned int width, unsigned int height, |
@@ -692,7 +697,7 @@ int cx88_set_scale(struct cx88_core *core, unsigned int width, unsigned int heig | |||
692 | dprintk(1,"set_scale: %dx%d [%s%s,%s]\n", width, height, | 697 | dprintk(1,"set_scale: %dx%d [%s%s,%s]\n", width, height, |
693 | V4L2_FIELD_HAS_TOP(field) ? "T" : "", | 698 | V4L2_FIELD_HAS_TOP(field) ? "T" : "", |
694 | V4L2_FIELD_HAS_BOTTOM(field) ? "B" : "", | 699 | V4L2_FIELD_HAS_BOTTOM(field) ? "B" : "", |
695 | core->tvnorm->name); | 700 | v4l2_norm_to_name(core->tvnorm)); |
696 | if (!V4L2_FIELD_HAS_BOTH(field)) | 701 | if (!V4L2_FIELD_HAS_BOTH(field)) |
697 | height *= 2; | 702 | height *= 2; |
698 | 703 | ||
@@ -729,7 +734,7 @@ int cx88_set_scale(struct cx88_core *core, unsigned int width, unsigned int heig | |||
729 | // setup filters | 734 | // setup filters |
730 | value = 0; | 735 | value = 0; |
731 | value |= (1 << 19); // CFILT (default) | 736 | value |= (1 << 19); // CFILT (default) |
732 | if (core->tvnorm->id & V4L2_STD_SECAM) { | 737 | if (core->tvnorm & V4L2_STD_SECAM) { |
733 | value |= (1 << 15); | 738 | value |= (1 << 15); |
734 | value |= (1 << 16); | 739 | value |= (1 << 16); |
735 | } | 740 | } |
@@ -826,36 +831,36 @@ int cx88_stop_audio_dma(struct cx88_core *core) | |||
826 | 831 | ||
827 | static int set_tvaudio(struct cx88_core *core) | 832 | static int set_tvaudio(struct cx88_core *core) |
828 | { | 833 | { |
829 | struct cx88_tvnorm *norm = core->tvnorm; | 834 | v4l2_std_id norm = core->tvnorm; |
830 | 835 | ||
831 | if (CX88_VMUX_TELEVISION != INPUT(core->input)->type) | 836 | if (CX88_VMUX_TELEVISION != INPUT(core->input)->type) |
832 | return 0; | 837 | return 0; |
833 | 838 | ||
834 | if (V4L2_STD_PAL_BG & norm->id) { | 839 | if (V4L2_STD_PAL_BG & norm) { |
835 | core->tvaudio = WW_BG; | 840 | core->tvaudio = WW_BG; |
836 | 841 | ||
837 | } else if (V4L2_STD_PAL_DK & norm->id) { | 842 | } else if (V4L2_STD_PAL_DK & norm) { |
838 | core->tvaudio = WW_DK; | 843 | core->tvaudio = WW_DK; |
839 | 844 | ||
840 | } else if (V4L2_STD_PAL_I & norm->id) { | 845 | } else if (V4L2_STD_PAL_I & norm) { |
841 | core->tvaudio = WW_I; | 846 | core->tvaudio = WW_I; |
842 | 847 | ||
843 | } else if (V4L2_STD_SECAM_L & norm->id) { | 848 | } else if (V4L2_STD_SECAM_L & norm) { |
844 | core->tvaudio = WW_L; | 849 | core->tvaudio = WW_L; |
845 | 850 | ||
846 | } else if (V4L2_STD_SECAM_DK & norm->id) { | 851 | } else if (V4L2_STD_SECAM_DK & norm) { |
847 | core->tvaudio = WW_DK; | 852 | core->tvaudio = WW_DK; |
848 | 853 | ||
849 | } else if ((V4L2_STD_NTSC_M & norm->id) || | 854 | } else if ((V4L2_STD_NTSC_M & norm) || |
850 | (V4L2_STD_PAL_M & norm->id)) { | 855 | (V4L2_STD_PAL_M & norm)) { |
851 | core->tvaudio = WW_BTSC; | 856 | core->tvaudio = WW_BTSC; |
852 | 857 | ||
853 | } else if (V4L2_STD_NTSC_M_JP & norm->id) { | 858 | } else if (V4L2_STD_NTSC_M_JP & norm) { |
854 | core->tvaudio = WW_EIAJ; | 859 | core->tvaudio = WW_EIAJ; |
855 | 860 | ||
856 | } else { | 861 | } else { |
857 | printk("%s/0: tvaudio support needs work for this tv norm [%s], sorry\n", | 862 | printk("%s/0: tvaudio support needs work for this tv norm [%s], sorry\n", |
858 | core->name, norm->name); | 863 | core->name, v4l2_norm_to_name(core->tvnorm)); |
859 | core->tvaudio = 0; | 864 | core->tvaudio = 0; |
860 | return 0; | 865 | return 0; |
861 | } | 866 | } |
@@ -874,7 +879,7 @@ static int set_tvaudio(struct cx88_core *core) | |||
874 | 879 | ||
875 | 880 | ||
876 | 881 | ||
877 | int cx88_set_tvnorm(struct cx88_core *core, struct cx88_tvnorm *norm) | 882 | int cx88_set_tvnorm(struct cx88_core *core, v4l2_std_id norm) |
878 | { | 883 | { |
879 | u32 fsc8; | 884 | u32 fsc8; |
880 | u32 adc_clock; | 885 | u32 adc_clock; |
@@ -882,6 +887,7 @@ int cx88_set_tvnorm(struct cx88_core *core, struct cx88_tvnorm *norm) | |||
882 | u32 step_db,step_dr; | 887 | u32 step_db,step_dr; |
883 | u64 tmp64; | 888 | u64 tmp64; |
884 | u32 bdelay,agcdelay,htotal; | 889 | u32 bdelay,agcdelay,htotal; |
890 | u32 cxiformat, cxoformat; | ||
885 | 891 | ||
886 | core->tvnorm = norm; | 892 | core->tvnorm = norm; |
887 | fsc8 = norm_fsc8(norm); | 893 | fsc8 = norm_fsc8(norm); |
@@ -890,23 +896,51 @@ int cx88_set_tvnorm(struct cx88_core *core, struct cx88_tvnorm *norm) | |||
890 | step_db = fsc8; | 896 | step_db = fsc8; |
891 | step_dr = fsc8; | 897 | step_dr = fsc8; |
892 | 898 | ||
893 | if (norm->id & V4L2_STD_SECAM) { | 899 | if (norm & V4L2_STD_NTSC_M_JP) { |
900 | cxiformat = VideoFormatNTSCJapan; | ||
901 | cxoformat = 0x181f0008; | ||
902 | } else if (norm & V4L2_STD_NTSC_443) { | ||
903 | cxiformat = VideoFormatNTSC443; | ||
904 | cxoformat = 0x181f0008; | ||
905 | } else if (norm & V4L2_STD_PAL_M) { | ||
906 | cxiformat = VideoFormatPALM; | ||
907 | cxoformat = 0x1c1f0008; | ||
908 | } else if (norm & V4L2_STD_PAL_N) { | ||
909 | cxiformat = VideoFormatPALN; | ||
910 | cxoformat = 0x1c1f0008; | ||
911 | } else if (norm & V4L2_STD_PAL_Nc) { | ||
912 | cxiformat = VideoFormatPALNC; | ||
913 | cxoformat = 0x1c1f0008; | ||
914 | } else if (norm & V4L2_STD_PAL_60) { | ||
915 | cxiformat = VideoFormatPAL60; | ||
916 | cxoformat = 0x181f0008; | ||
917 | } else if (norm & V4L2_STD_NTSC) { | ||
918 | cxiformat = VideoFormatNTSC; | ||
919 | cxoformat = 0x181f0008; | ||
920 | } else if (norm & V4L2_STD_SECAM) { | ||
894 | step_db = 4250000 * 8; | 921 | step_db = 4250000 * 8; |
895 | step_dr = 4406250 * 8; | 922 | step_dr = 4406250 * 8; |
923 | |||
924 | cxiformat = VideoFormatSECAM; | ||
925 | cxoformat = 0x181f0008; | ||
926 | } else { /* PAL */ | ||
927 | cxiformat = VideoFormatPAL; | ||
928 | cxoformat = 0x181f0008; | ||
896 | } | 929 | } |
897 | 930 | ||
898 | dprintk(1,"set_tvnorm: \"%s\" fsc8=%d adc=%d vdec=%d db/dr=%d/%d\n", | 931 | dprintk(1,"set_tvnorm: \"%s\" fsc8=%d adc=%d vdec=%d db/dr=%d/%d\n", |
899 | norm->name, fsc8, adc_clock, vdec_clock, step_db, step_dr); | 932 | v4l2_norm_to_name(core->tvnorm), fsc8, adc_clock, vdec_clock, |
933 | step_db, step_dr); | ||
900 | set_pll(core,2,vdec_clock); | 934 | set_pll(core,2,vdec_clock); |
901 | 935 | ||
902 | dprintk(1,"set_tvnorm: MO_INPUT_FORMAT 0x%08x [old=0x%08x]\n", | 936 | dprintk(1,"set_tvnorm: MO_INPUT_FORMAT 0x%08x [old=0x%08x]\n", |
903 | norm->cxiformat, cx_read(MO_INPUT_FORMAT) & 0x0f); | 937 | cxiformat, cx_read(MO_INPUT_FORMAT) & 0x0f); |
904 | cx_andor(MO_INPUT_FORMAT, 0xf, norm->cxiformat); | 938 | cx_andor(MO_INPUT_FORMAT, 0xf, cxiformat); |
905 | 939 | ||
906 | // FIXME: as-is from DScaler | 940 | // FIXME: as-is from DScaler |
907 | dprintk(1,"set_tvnorm: MO_OUTPUT_FORMAT 0x%08x [old=0x%08x]\n", | 941 | dprintk(1,"set_tvnorm: MO_OUTPUT_FORMAT 0x%08x [old=0x%08x]\n", |
908 | norm->cxoformat, cx_read(MO_OUTPUT_FORMAT)); | 942 | cxoformat, cx_read(MO_OUTPUT_FORMAT)); |
909 | cx_write(MO_OUTPUT_FORMAT, norm->cxoformat); | 943 | cx_write(MO_OUTPUT_FORMAT, cxoformat); |
910 | 944 | ||
911 | // MO_SCONV_REG = adc clock / video dec clock * 2^17 | 945 | // MO_SCONV_REG = adc clock / video dec clock * 2^17 |
912 | tmp64 = adc_clock * (u64)(1 << 17); | 946 | tmp64 = adc_clock * (u64)(1 << 17); |
@@ -955,7 +989,7 @@ int cx88_set_tvnorm(struct cx88_core *core, struct cx88_tvnorm *norm) | |||
955 | set_tvaudio(core); | 989 | set_tvaudio(core); |
956 | 990 | ||
957 | // tell i2c chips | 991 | // tell i2c chips |
958 | cx88_call_i2c_clients(core,VIDIOC_S_STD,&norm->id); | 992 | cx88_call_i2c_clients(core,VIDIOC_S_STD,&norm); |
959 | 993 | ||
960 | // done | 994 | // done |
961 | return 0; | 995 | return 0; |
diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 8b203354fccd..4f5560285770 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c | |||
@@ -35,7 +35,7 @@ | |||
35 | 35 | ||
36 | #include "mt352.h" | 36 | #include "mt352.h" |
37 | #include "mt352_priv.h" | 37 | #include "mt352_priv.h" |
38 | #ifdef HAVE_VP3054_I2C | 38 | #if defined(CONFIG_VIDEO_CX88_VP3054) || defined(CONFIG_VIDEO_CX88_VP3054_MODULE) |
39 | # include "cx88-vp3054-i2c.h" | 39 | # include "cx88-vp3054-i2c.h" |
40 | #endif | 40 | #endif |
41 | #include "zl10353.h" | 41 | #include "zl10353.h" |
@@ -200,7 +200,7 @@ static struct mt352_config dvico_fusionhdtv_dual = { | |||
200 | .demod_init = dvico_dual_demod_init, | 200 | .demod_init = dvico_dual_demod_init, |
201 | }; | 201 | }; |
202 | 202 | ||
203 | #ifdef HAVE_VP3054_I2C | 203 | #if defined(CONFIG_VIDEO_CX88_VP3054) || defined(CONFIG_VIDEO_CX88_VP3054_MODULE) |
204 | static int dntv_live_dvbt_pro_demod_init(struct dvb_frontend* fe) | 204 | static int dntv_live_dvbt_pro_demod_init(struct dvb_frontend* fe) |
205 | { | 205 | { |
206 | static u8 clock_config [] = { 0x89, 0x38, 0x38 }; | 206 | static u8 clock_config [] = { 0x89, 0x38, 0x38 }; |
@@ -543,7 +543,7 @@ static int dvb_register(struct cx8802_dev *dev) | |||
543 | } | 543 | } |
544 | break; | 544 | break; |
545 | case CX88_BOARD_DNTV_LIVE_DVB_T_PRO: | 545 | case CX88_BOARD_DNTV_LIVE_DVB_T_PRO: |
546 | #ifdef HAVE_VP3054_I2C | 546 | #if defined(CONFIG_VIDEO_CX88_VP3054) || defined(CONFIG_VIDEO_CX88_VP3054_MODULE) |
547 | dev->core->pll_addr = 0x61; | 547 | dev->core->pll_addr = 0x61; |
548 | dev->core->pll_desc = &dvb_pll_fmd1216me; | 548 | dev->core->pll_desc = &dvb_pll_fmd1216me; |
549 | dev->dvb.frontend = dvb_attach(mt352_attach, &dntv_live_dvbt_pro_config, | 549 | dev->dvb.frontend = dvb_attach(mt352_attach, &dntv_live_dvbt_pro_config, |
@@ -793,7 +793,7 @@ static int cx8802_dvb_probe(struct cx8802_driver *drv) | |||
793 | if (!(cx88_boards[core->board].mpeg & CX88_MPEG_DVB)) | 793 | if (!(cx88_boards[core->board].mpeg & CX88_MPEG_DVB)) |
794 | goto fail_core; | 794 | goto fail_core; |
795 | 795 | ||
796 | #ifdef HAVE_VP3054_I2C | 796 | #if defined(CONFIG_VIDEO_CX88_VP3054) || defined(CONFIG_VIDEO_CX88_VP3054_MODULE) |
797 | err = vp3054_i2c_probe(dev); | 797 | err = vp3054_i2c_probe(dev); |
798 | if (0 != err) | 798 | if (0 != err) |
799 | goto fail_core; | 799 | goto fail_core; |
@@ -822,7 +822,7 @@ static int cx8802_dvb_remove(struct cx8802_driver *drv) | |||
822 | /* dvb */ | 822 | /* dvb */ |
823 | videobuf_dvb_unregister(&dev->dvb); | 823 | videobuf_dvb_unregister(&dev->dvb); |
824 | 824 | ||
825 | #ifdef HAVE_VP3054_I2C | 825 | #if defined(CONFIG_VIDEO_CX88_VP3054) || defined(CONFIG_VIDEO_CX88_VP3054_MODULE) |
826 | vp3054_i2c_remove(dev); | 826 | vp3054_i2c_remove(dev); |
827 | #endif | 827 | #endif |
828 | 828 | ||
diff --git a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c index 88af23a93870..9830d5c43921 100644 --- a/drivers/media/video/cx88/cx88-i2c.c +++ b/drivers/media/video/cx88/cx88-i2c.c | |||
@@ -145,6 +145,7 @@ void cx88_call_i2c_clients(struct cx88_core *core, unsigned int cmd, void *arg) | |||
145 | if (0 != core->i2c_rc) | 145 | if (0 != core->i2c_rc) |
146 | return; | 146 | return; |
147 | 147 | ||
148 | #if defined(CONFIG_VIDEO_BUF_DVB) || defined(CONFIG_VIDEO_BUF_DVB_MODULE) | ||
148 | if ( (core->dvbdev) && (core->dvbdev->dvb.frontend) ) { | 149 | if ( (core->dvbdev) && (core->dvbdev->dvb.frontend) ) { |
149 | if (core->dvbdev->dvb.frontend->ops.i2c_gate_ctrl) | 150 | if (core->dvbdev->dvb.frontend->ops.i2c_gate_ctrl) |
150 | core->dvbdev->dvb.frontend->ops.i2c_gate_ctrl(core->dvbdev->dvb.frontend, 1); | 151 | core->dvbdev->dvb.frontend->ops.i2c_gate_ctrl(core->dvbdev->dvb.frontend, 1); |
@@ -154,6 +155,7 @@ void cx88_call_i2c_clients(struct cx88_core *core, unsigned int cmd, void *arg) | |||
154 | if (core->dvbdev->dvb.frontend->ops.i2c_gate_ctrl) | 155 | if (core->dvbdev->dvb.frontend->ops.i2c_gate_ctrl) |
155 | core->dvbdev->dvb.frontend->ops.i2c_gate_ctrl(core->dvbdev->dvb.frontend, 0); | 156 | core->dvbdev->dvb.frontend->ops.i2c_gate_ctrl(core->dvbdev->dvb.frontend, 0); |
156 | } else | 157 | } else |
158 | #endif | ||
157 | i2c_clients_command(&core->i2c_adap, cmd, arg); | 159 | i2c_clients_command(&core->i2c_adap, cmd, arg); |
158 | } | 160 | } |
159 | 161 | ||
diff --git a/drivers/media/video/cx88/cx88-tvaudio.c b/drivers/media/video/cx88/cx88-tvaudio.c index 063df03dcf2e..97ef421dd093 100644 --- a/drivers/media/video/cx88/cx88-tvaudio.c +++ b/drivers/media/video/cx88/cx88-tvaudio.c | |||
@@ -797,55 +797,6 @@ void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t) | |||
797 | Add some code here later. | 797 | Add some code here later. |
798 | */ | 798 | */ |
799 | 799 | ||
800 | # if 0 | ||
801 | t->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_SAP | | ||
802 | V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2; | ||
803 | t->rxsubchans = V4L2_TUNER_SUB_MONO; | ||
804 | t->audmode = V4L2_TUNER_MODE_MONO; | ||
805 | |||
806 | switch (core->tvaudio) { | ||
807 | case WW_BTSC: | ||
808 | t->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_SAP; | ||
809 | t->rxsubchans = V4L2_TUNER_SUB_STEREO; | ||
810 | if (1 == pilot) { | ||
811 | /* SAP */ | ||
812 | t->rxsubchans |= V4L2_TUNER_SUB_SAP; | ||
813 | } | ||
814 | break; | ||
815 | case WW_A2_BG: | ||
816 | case WW_A2_DK: | ||
817 | case WW_A2_M: | ||
818 | if (1 == pilot) { | ||
819 | /* stereo */ | ||
820 | t->rxsubchans = | ||
821 | V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; | ||
822 | if (0 == mode) | ||
823 | t->audmode = V4L2_TUNER_MODE_STEREO; | ||
824 | } | ||
825 | if (2 == pilot) { | ||
826 | /* dual language -- FIXME */ | ||
827 | t->rxsubchans = | ||
828 | V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; | ||
829 | t->audmode = V4L2_TUNER_MODE_LANG1; | ||
830 | } | ||
831 | break; | ||
832 | case WW_NICAM_BGDKL: | ||
833 | if (0 == mode) { | ||
834 | t->audmode = V4L2_TUNER_MODE_STEREO; | ||
835 | t->rxsubchans |= V4L2_TUNER_SUB_STEREO; | ||
836 | } | ||
837 | break; | ||
838 | case WW_SYSTEM_L_AM: | ||
839 | if (0x0 == mode && !(cx_read(AUD_INIT) & 0x04)) { | ||
840 | t->audmode = V4L2_TUNER_MODE_STEREO; | ||
841 | t->rxsubchans |= V4L2_TUNER_SUB_STEREO; | ||
842 | } | ||
843 | break; | ||
844 | default: | ||
845 | /* nothing */ | ||
846 | break; | ||
847 | } | ||
848 | # endif | ||
849 | return; | 800 | return; |
850 | } | 801 | } |
851 | 802 | ||
diff --git a/drivers/media/video/cx88/cx88-vbi.c b/drivers/media/video/cx88/cx88-vbi.c index aa2a69770098..86c1cf8334bc 100644 --- a/drivers/media/video/cx88/cx88-vbi.c +++ b/drivers/media/video/cx88/cx88-vbi.c | |||
@@ -21,9 +21,11 @@ MODULE_PARM_DESC(vbi_debug,"enable debug messages [vbi]"); | |||
21 | 21 | ||
22 | /* ------------------------------------------------------------------ */ | 22 | /* ------------------------------------------------------------------ */ |
23 | 23 | ||
24 | void cx8800_vbi_fmt(struct cx8800_dev *dev, struct v4l2_format *f) | 24 | int cx8800_vbi_fmt (struct file *file, void *priv, |
25 | struct v4l2_format *f) | ||
25 | { | 26 | { |
26 | memset(&f->fmt.vbi,0,sizeof(f->fmt.vbi)); | 27 | struct cx8800_fh *fh = priv; |
28 | struct cx8800_dev *dev = fh->dev; | ||
27 | 29 | ||
28 | f->fmt.vbi.samples_per_line = VBI_LINE_LENGTH; | 30 | f->fmt.vbi.samples_per_line = VBI_LINE_LENGTH; |
29 | f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY; | 31 | f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY; |
@@ -31,18 +33,19 @@ void cx8800_vbi_fmt(struct cx8800_dev *dev, struct v4l2_format *f) | |||
31 | f->fmt.vbi.count[0] = VBI_LINE_COUNT; | 33 | f->fmt.vbi.count[0] = VBI_LINE_COUNT; |
32 | f->fmt.vbi.count[1] = VBI_LINE_COUNT; | 34 | f->fmt.vbi.count[1] = VBI_LINE_COUNT; |
33 | 35 | ||
34 | if (dev->core->tvnorm->id & V4L2_STD_525_60) { | 36 | if (dev->core->tvnorm & V4L2_STD_525_60) { |
35 | /* ntsc */ | 37 | /* ntsc */ |
36 | f->fmt.vbi.sampling_rate = 28636363; | 38 | f->fmt.vbi.sampling_rate = 28636363; |
37 | f->fmt.vbi.start[0] = 10; | 39 | f->fmt.vbi.start[0] = 10; |
38 | f->fmt.vbi.start[1] = 273; | 40 | f->fmt.vbi.start[1] = 273; |
39 | 41 | ||
40 | } else if (dev->core->tvnorm->id & V4L2_STD_625_50) { | 42 | } else if (dev->core->tvnorm & V4L2_STD_625_50) { |
41 | /* pal */ | 43 | /* pal */ |
42 | f->fmt.vbi.sampling_rate = 35468950; | 44 | f->fmt.vbi.sampling_rate = 35468950; |
43 | f->fmt.vbi.start[0] = 7 -1; | 45 | f->fmt.vbi.start[0] = 7 -1; |
44 | f->fmt.vbi.start[1] = 319 -1; | 46 | f->fmt.vbi.start[1] = 319 -1; |
45 | } | 47 | } |
48 | return 0; | ||
46 | } | 49 | } |
47 | 50 | ||
48 | static int cx8800_start_vbi_dma(struct cx8800_dev *dev, | 51 | static int cx8800_start_vbi_dma(struct cx8800_dev *dev, |
diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index c86a7e06235b..a97be1bdc31d 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c | |||
@@ -1,3 +1,4 @@ | |||
1 | |||
1 | /* | 2 | /* |
2 | * | 3 | * |
3 | * device driver for Conexant 2388x based TV cards | 4 | * device driver for Conexant 2388x based TV cards |
@@ -5,6 +6,11 @@ | |||
5 | * | 6 | * |
6 | * (c) 2003-04 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs] | 7 | * (c) 2003-04 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs] |
7 | * | 8 | * |
9 | * (c) 2005-2006 Mauro Carvalho Chehab <mchehab@infradead.org> | ||
10 | * - Multituner support | ||
11 | * - video_ioctl2 conversion | ||
12 | * - PAL/M fixes | ||
13 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | 14 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License as published by | 15 | * it under the terms of the GNU General Public License as published by |
10 | * the Free Software Foundation; either version 2 of the License, or | 16 | * the Free Software Foundation; either version 2 of the License, or |
@@ -80,65 +86,6 @@ static LIST_HEAD(cx8800_devlist); | |||
80 | /* ------------------------------------------------------------------- */ | 86 | /* ------------------------------------------------------------------- */ |
81 | /* static data */ | 87 | /* static data */ |
82 | 88 | ||
83 | static struct cx88_tvnorm tvnorms[] = { | ||
84 | { | ||
85 | .name = "NTSC-M", | ||
86 | .id = V4L2_STD_NTSC_M, | ||
87 | .cxiformat = VideoFormatNTSC, | ||
88 | .cxoformat = 0x181f0008, | ||
89 | },{ | ||
90 | .name = "NTSC-JP", | ||
91 | .id = V4L2_STD_NTSC_M_JP, | ||
92 | .cxiformat = VideoFormatNTSCJapan, | ||
93 | .cxoformat = 0x181f0008, | ||
94 | },{ | ||
95 | .name = "PAL-BG", | ||
96 | .id = V4L2_STD_PAL_BG, | ||
97 | .cxiformat = VideoFormatPAL, | ||
98 | .cxoformat = 0x181f0008, | ||
99 | },{ | ||
100 | .name = "PAL-DK", | ||
101 | .id = V4L2_STD_PAL_DK, | ||
102 | .cxiformat = VideoFormatPAL, | ||
103 | .cxoformat = 0x181f0008, | ||
104 | },{ | ||
105 | .name = "PAL-I", | ||
106 | .id = V4L2_STD_PAL_I, | ||
107 | .cxiformat = VideoFormatPAL, | ||
108 | .cxoformat = 0x181f0008, | ||
109 | },{ | ||
110 | .name = "PAL-M", | ||
111 | .id = V4L2_STD_PAL_M, | ||
112 | .cxiformat = VideoFormatPALM, | ||
113 | .cxoformat = 0x1c1f0008, | ||
114 | },{ | ||
115 | .name = "PAL-N", | ||
116 | .id = V4L2_STD_PAL_N, | ||
117 | .cxiformat = VideoFormatPALN, | ||
118 | .cxoformat = 0x1c1f0008, | ||
119 | },{ | ||
120 | .name = "PAL-Nc", | ||
121 | .id = V4L2_STD_PAL_Nc, | ||
122 | .cxiformat = VideoFormatPALNC, | ||
123 | .cxoformat = 0x1c1f0008, | ||
124 | },{ | ||
125 | .name = "PAL-60", | ||
126 | .id = V4L2_STD_PAL_60, | ||
127 | .cxiformat = VideoFormatPAL60, | ||
128 | .cxoformat = 0x181f0008, | ||
129 | },{ | ||
130 | .name = "SECAM-L", | ||
131 | .id = V4L2_STD_SECAM_L, | ||
132 | .cxiformat = VideoFormatSECAM, | ||
133 | .cxoformat = 0x181f0008, | ||
134 | },{ | ||
135 | .name = "SECAM-DK", | ||
136 | .id = V4L2_STD_SECAM_DK, | ||
137 | .cxiformat = VideoFormatSECAM, | ||
138 | .cxoformat = 0x181f0008, | ||
139 | } | ||
140 | }; | ||
141 | |||
142 | static struct cx8800_fmt formats[] = { | 89 | static struct cx8800_fmt formats[] = { |
143 | { | 90 | { |
144 | .name = "8 bpp, gray", | 91 | .name = "8 bpp, gray", |
@@ -364,14 +311,6 @@ int cx8800_ctrl_query(struct v4l2_queryctrl *qctrl) | |||
364 | } | 311 | } |
365 | EXPORT_SYMBOL(cx8800_ctrl_query); | 312 | EXPORT_SYMBOL(cx8800_ctrl_query); |
366 | 313 | ||
367 | static int cx88_queryctrl(struct v4l2_queryctrl *qctrl) | ||
368 | { | ||
369 | qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id); | ||
370 | if (qctrl->id == 0) | ||
371 | return -EINVAL; | ||
372 | return cx8800_ctrl_query(qctrl); | ||
373 | } | ||
374 | |||
375 | /* ------------------------------------------------------------------- */ | 314 | /* ------------------------------------------------------------------- */ |
376 | /* resource management */ | 315 | /* resource management */ |
377 | 316 | ||
@@ -424,8 +363,7 @@ void res_free(struct cx8800_dev *dev, struct cx8800_fh *fh, unsigned int bits) | |||
424 | 363 | ||
425 | /* ------------------------------------------------------------------ */ | 364 | /* ------------------------------------------------------------------ */ |
426 | 365 | ||
427 | /* static int video_mux(struct cx8800_dev *dev, unsigned int input) */ | 366 | int cx88_video_mux(struct cx88_core *core, unsigned int input) |
428 | static int video_mux(struct cx88_core *core, unsigned int input) | ||
429 | { | 367 | { |
430 | /* struct cx88_core *core = dev->core; */ | 368 | /* struct cx88_core *core = dev->core; */ |
431 | 369 | ||
@@ -464,6 +402,7 @@ static int video_mux(struct cx88_core *core, unsigned int input) | |||
464 | } | 402 | } |
465 | return 0; | 403 | return 0; |
466 | } | 404 | } |
405 | EXPORT_SYMBOL(cx88_video_mux); | ||
467 | 406 | ||
468 | /* ------------------------------------------------------------------ */ | 407 | /* ------------------------------------------------------------------ */ |
469 | 408 | ||
@@ -944,19 +883,18 @@ video_mmap(struct file *file, struct vm_area_struct * vma) | |||
944 | } | 883 | } |
945 | 884 | ||
946 | /* ------------------------------------------------------------------ */ | 885 | /* ------------------------------------------------------------------ */ |
886 | /* VIDEO CTRL IOCTLS */ | ||
947 | 887 | ||
948 | /* static int get_control(struct cx8800_dev *dev, struct v4l2_control *ctl) */ | 888 | int cx88_get_control (struct cx88_core *core, struct v4l2_control *ctl) |
949 | static int get_control(struct cx88_core *core, struct v4l2_control *ctl) | ||
950 | { | 889 | { |
951 | /* struct cx88_core *core = dev->core; */ | 890 | struct cx88_ctrl *c = NULL; |
952 | struct cx88_ctrl *c = NULL; | ||
953 | u32 value; | 891 | u32 value; |
954 | int i; | 892 | int i; |
955 | 893 | ||
956 | for (i = 0; i < CX8800_CTLS; i++) | 894 | for (i = 0; i < CX8800_CTLS; i++) |
957 | if (cx8800_ctls[i].v.id == ctl->id) | 895 | if (cx8800_ctls[i].v.id == ctl->id) |
958 | c = &cx8800_ctls[i]; | 896 | c = &cx8800_ctls[i]; |
959 | if (NULL == c) | 897 | if (unlikely(NULL == c)) |
960 | return -EINVAL; | 898 | return -EINVAL; |
961 | 899 | ||
962 | value = c->sreg ? cx_sread(c->sreg) : cx_read(c->reg); | 900 | value = c->sreg ? cx_sread(c->sreg) : cx_read(c->reg); |
@@ -977,20 +915,20 @@ static int get_control(struct cx88_core *core, struct v4l2_control *ctl) | |||
977 | value,c->mask, c->sreg ? " [shadowed]" : ""); | 915 | value,c->mask, c->sreg ? " [shadowed]" : ""); |
978 | return 0; | 916 | return 0; |
979 | } | 917 | } |
918 | EXPORT_SYMBOL(cx88_get_control); | ||
980 | 919 | ||
981 | /* static int set_control(struct cx8800_dev *dev, struct v4l2_control *ctl) */ | 920 | int cx88_set_control(struct cx88_core *core, struct v4l2_control *ctl) |
982 | static int set_control(struct cx88_core *core, struct v4l2_control *ctl) | ||
983 | { | 921 | { |
984 | /* struct cx88_core *core = dev->core; */ | ||
985 | struct cx88_ctrl *c = NULL; | 922 | struct cx88_ctrl *c = NULL; |
986 | u32 value,mask; | 923 | u32 value,mask; |
987 | int i; | 924 | int i; |
925 | |||
988 | for (i = 0; i < CX8800_CTLS; i++) { | 926 | for (i = 0; i < CX8800_CTLS; i++) { |
989 | if (cx8800_ctls[i].v.id == ctl->id) { | 927 | if (cx8800_ctls[i].v.id == ctl->id) { |
990 | c = &cx8800_ctls[i]; | 928 | c = &cx8800_ctls[i]; |
991 | } | 929 | } |
992 | } | 930 | } |
993 | if (NULL == c) | 931 | if (unlikely(NULL == c)) |
994 | return -EINVAL; | 932 | return -EINVAL; |
995 | 933 | ||
996 | if (ctl->value < c->v.minimum) | 934 | if (ctl->value < c->v.minimum) |
@@ -1010,7 +948,7 @@ static int set_control(struct cx88_core *core, struct v4l2_control *ctl) | |||
1010 | 948 | ||
1011 | value = ((ctl->value - c->off) << c->shift) & c->mask; | 949 | value = ((ctl->value - c->off) << c->shift) & c->mask; |
1012 | 950 | ||
1013 | if (core->tvnorm->id & V4L2_STD_SECAM) { | 951 | if (core->tvnorm & V4L2_STD_SECAM) { |
1014 | /* For SECAM, both U and V sat should be equal */ | 952 | /* For SECAM, both U and V sat should be equal */ |
1015 | value=value<<8|value; | 953 | value=value<<8|value; |
1016 | } else { | 954 | } else { |
@@ -1033,6 +971,7 @@ static int set_control(struct cx88_core *core, struct v4l2_control *ctl) | |||
1033 | } | 971 | } |
1034 | return 0; | 972 | return 0; |
1035 | } | 973 | } |
974 | EXPORT_SYMBOL(cx88_set_control); | ||
1036 | 975 | ||
1037 | static void init_controls(struct cx88_core *core) | 976 | static void init_controls(struct cx88_core *core) |
1038 | { | 977 | { |
@@ -1042,648 +981,531 @@ static void init_controls(struct cx88_core *core) | |||
1042 | for (i = 0; i < CX8800_CTLS; i++) { | 981 | for (i = 0; i < CX8800_CTLS; i++) { |
1043 | ctrl.id=cx8800_ctls[i].v.id; | 982 | ctrl.id=cx8800_ctls[i].v.id; |
1044 | ctrl.value=cx8800_ctls[i].v.default_value; | 983 | ctrl.value=cx8800_ctls[i].v.default_value; |
1045 | set_control(core, &ctrl); | 984 | |
985 | cx88_set_control(core, &ctrl); | ||
1046 | } | 986 | } |
1047 | } | 987 | } |
1048 | 988 | ||
1049 | /* ------------------------------------------------------------------ */ | 989 | /* ------------------------------------------------------------------ */ |
990 | /* VIDEO IOCTLS */ | ||
1050 | 991 | ||
1051 | static int cx8800_g_fmt(struct cx8800_dev *dev, struct cx8800_fh *fh, | 992 | static int vidioc_g_fmt_cap (struct file *file, void *priv, |
993 | struct v4l2_format *f) | ||
994 | { | ||
995 | struct cx8800_fh *fh = priv; | ||
996 | |||
997 | f->fmt.pix.width = fh->width; | ||
998 | f->fmt.pix.height = fh->height; | ||
999 | f->fmt.pix.field = fh->vidq.field; | ||
1000 | f->fmt.pix.pixelformat = fh->fmt->fourcc; | ||
1001 | f->fmt.pix.bytesperline = | ||
1002 | (f->fmt.pix.width * fh->fmt->depth) >> 3; | ||
1003 | f->fmt.pix.sizeimage = | ||
1004 | f->fmt.pix.height * f->fmt.pix.bytesperline; | ||
1005 | return 0; | ||
1006 | } | ||
1007 | |||
1008 | static int vidioc_try_fmt_cap (struct file *file, void *priv, | ||
1052 | struct v4l2_format *f) | 1009 | struct v4l2_format *f) |
1053 | { | 1010 | { |
1054 | switch (f->type) { | 1011 | struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core; |
1055 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | 1012 | struct cx8800_fmt *fmt; |
1056 | memset(&f->fmt.pix,0,sizeof(f->fmt.pix)); | 1013 | enum v4l2_field field; |
1057 | f->fmt.pix.width = fh->width; | 1014 | unsigned int maxw, maxh; |
1058 | f->fmt.pix.height = fh->height; | 1015 | |
1059 | f->fmt.pix.field = fh->vidq.field; | 1016 | fmt = format_by_fourcc(f->fmt.pix.pixelformat); |
1060 | f->fmt.pix.pixelformat = fh->fmt->fourcc; | 1017 | if (NULL == fmt) |
1061 | f->fmt.pix.bytesperline = | 1018 | return -EINVAL; |
1062 | (f->fmt.pix.width * fh->fmt->depth) >> 3; | 1019 | |
1063 | f->fmt.pix.sizeimage = | 1020 | field = f->fmt.pix.field; |
1064 | f->fmt.pix.height * f->fmt.pix.bytesperline; | 1021 | maxw = norm_maxw(core->tvnorm); |
1065 | return 0; | 1022 | maxh = norm_maxh(core->tvnorm); |
1066 | case V4L2_BUF_TYPE_VBI_CAPTURE: | 1023 | |
1067 | cx8800_vbi_fmt(dev, f); | 1024 | if (V4L2_FIELD_ANY == field) { |
1068 | return 0; | 1025 | field = (f->fmt.pix.height > maxh/2) |
1026 | ? V4L2_FIELD_INTERLACED | ||
1027 | : V4L2_FIELD_BOTTOM; | ||
1028 | } | ||
1029 | |||
1030 | switch (field) { | ||
1031 | case V4L2_FIELD_TOP: | ||
1032 | case V4L2_FIELD_BOTTOM: | ||
1033 | maxh = maxh / 2; | ||
1034 | break; | ||
1035 | case V4L2_FIELD_INTERLACED: | ||
1036 | break; | ||
1069 | default: | 1037 | default: |
1070 | return -EINVAL; | 1038 | return -EINVAL; |
1071 | } | 1039 | } |
1040 | |||
1041 | f->fmt.pix.field = field; | ||
1042 | if (f->fmt.pix.height < 32) | ||
1043 | f->fmt.pix.height = 32; | ||
1044 | if (f->fmt.pix.height > maxh) | ||
1045 | f->fmt.pix.height = maxh; | ||
1046 | if (f->fmt.pix.width < 48) | ||
1047 | f->fmt.pix.width = 48; | ||
1048 | if (f->fmt.pix.width > maxw) | ||
1049 | f->fmt.pix.width = maxw; | ||
1050 | f->fmt.pix.width &= ~0x03; | ||
1051 | f->fmt.pix.bytesperline = | ||
1052 | (f->fmt.pix.width * fmt->depth) >> 3; | ||
1053 | f->fmt.pix.sizeimage = | ||
1054 | f->fmt.pix.height * f->fmt.pix.bytesperline; | ||
1055 | |||
1056 | return 0; | ||
1072 | } | 1057 | } |
1073 | 1058 | ||
1074 | static int cx8800_try_fmt(struct cx8800_dev *dev, struct cx8800_fh *fh, | 1059 | static int vidioc_s_fmt_cap (struct file *file, void *priv, |
1075 | struct v4l2_format *f) | 1060 | struct v4l2_format *f) |
1076 | { | 1061 | { |
1077 | struct cx88_core *core = dev->core; | 1062 | struct cx8800_fh *fh = priv; |
1063 | int err = vidioc_try_fmt_cap (file,priv,f); | ||
1078 | 1064 | ||
1079 | switch (f->type) { | 1065 | if (0 != err) |
1080 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | 1066 | return err; |
1081 | { | 1067 | fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); |
1082 | struct cx8800_fmt *fmt; | 1068 | fh->width = f->fmt.pix.width; |
1083 | enum v4l2_field field; | 1069 | fh->height = f->fmt.pix.height; |
1084 | unsigned int maxw, maxh; | 1070 | fh->vidq.field = f->fmt.pix.field; |
1085 | 1071 | return 0; | |
1086 | fmt = format_by_fourcc(f->fmt.pix.pixelformat); | 1072 | } |
1087 | if (NULL == fmt) | ||
1088 | return -EINVAL; | ||
1089 | |||
1090 | field = f->fmt.pix.field; | ||
1091 | maxw = norm_maxw(core->tvnorm); | ||
1092 | maxh = norm_maxh(core->tvnorm); | ||
1093 | |||
1094 | if (V4L2_FIELD_ANY == field) { | ||
1095 | field = (f->fmt.pix.height > maxh/2) | ||
1096 | ? V4L2_FIELD_INTERLACED | ||
1097 | : V4L2_FIELD_BOTTOM; | ||
1098 | } | ||
1099 | 1073 | ||
1100 | switch (field) { | 1074 | static int vidioc_querycap (struct file *file, void *priv, |
1101 | case V4L2_FIELD_TOP: | 1075 | struct v4l2_capability *cap) |
1102 | case V4L2_FIELD_BOTTOM: | 1076 | { |
1103 | maxh = maxh / 2; | 1077 | struct cx8800_dev *dev = ((struct cx8800_fh *)priv)->dev; |
1104 | break; | 1078 | struct cx88_core *core = dev->core; |
1105 | case V4L2_FIELD_INTERLACED: | ||
1106 | break; | ||
1107 | default: | ||
1108 | return -EINVAL; | ||
1109 | } | ||
1110 | 1079 | ||
1111 | f->fmt.pix.field = field; | 1080 | strcpy(cap->driver, "cx8800"); |
1112 | if (f->fmt.pix.height < 32) | 1081 | strlcpy(cap->card, cx88_boards[core->board].name, |
1113 | f->fmt.pix.height = 32; | 1082 | sizeof(cap->card)); |
1114 | if (f->fmt.pix.height > maxh) | 1083 | sprintf(cap->bus_info,"PCI:%s",pci_name(dev->pci)); |
1115 | f->fmt.pix.height = maxh; | 1084 | cap->version = CX88_VERSION_CODE; |
1116 | if (f->fmt.pix.width < 48) | 1085 | cap->capabilities = |
1117 | f->fmt.pix.width = 48; | 1086 | V4L2_CAP_VIDEO_CAPTURE | |
1118 | if (f->fmt.pix.width > maxw) | 1087 | V4L2_CAP_READWRITE | |
1119 | f->fmt.pix.width = maxw; | 1088 | V4L2_CAP_STREAMING | |
1120 | f->fmt.pix.width &= ~0x03; | 1089 | V4L2_CAP_VBI_CAPTURE; |
1121 | f->fmt.pix.bytesperline = | 1090 | if (UNSET != core->tuner_type) |
1122 | (f->fmt.pix.width * fmt->depth) >> 3; | 1091 | cap->capabilities |= V4L2_CAP_TUNER; |
1123 | f->fmt.pix.sizeimage = | 1092 | return 0; |
1124 | f->fmt.pix.height * f->fmt.pix.bytesperline; | 1093 | } |
1125 | 1094 | ||
1126 | return 0; | 1095 | static int vidioc_enum_fmt_cap (struct file *file, void *priv, |
1127 | } | 1096 | struct v4l2_fmtdesc *f) |
1128 | case V4L2_BUF_TYPE_VBI_CAPTURE: | 1097 | { |
1129 | cx8800_vbi_fmt(dev, f); | 1098 | if (unlikely(f->index >= ARRAY_SIZE(formats))) |
1130 | return 0; | ||
1131 | default: | ||
1132 | return -EINVAL; | 1099 | return -EINVAL; |
1133 | } | 1100 | |
1101 | strlcpy(f->description,formats[f->index].name,sizeof(f->description)); | ||
1102 | f->pixelformat = formats[f->index].fourcc; | ||
1103 | |||
1104 | return 0; | ||
1134 | } | 1105 | } |
1135 | 1106 | ||
1136 | static int cx8800_s_fmt(struct cx8800_dev *dev, struct cx8800_fh *fh, | 1107 | #ifdef CONFIG_VIDEO_V4L1_COMPAT |
1137 | struct v4l2_format *f) | 1108 | static int vidiocgmbuf (struct file *file, void *priv, struct video_mbuf *mbuf) |
1138 | { | 1109 | { |
1110 | struct cx8800_fh *fh = priv; | ||
1111 | struct videobuf_queue *q; | ||
1112 | struct v4l2_requestbuffers req; | ||
1113 | unsigned int i; | ||
1139 | int err; | 1114 | int err; |
1140 | 1115 | ||
1141 | switch (f->type) { | 1116 | q = get_queue(fh); |
1142 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | 1117 | memset(&req,0,sizeof(req)); |
1143 | err = cx8800_try_fmt(dev,fh,f); | 1118 | req.type = q->type; |
1144 | if (0 != err) | 1119 | req.count = 8; |
1145 | return err; | 1120 | req.memory = V4L2_MEMORY_MMAP; |
1121 | err = videobuf_reqbufs(q,&req); | ||
1122 | if (err < 0) | ||
1123 | return err; | ||
1146 | 1124 | ||
1147 | fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); | 1125 | mbuf->frames = req.count; |
1148 | fh->width = f->fmt.pix.width; | 1126 | mbuf->size = 0; |
1149 | fh->height = f->fmt.pix.height; | 1127 | for (i = 0; i < mbuf->frames; i++) { |
1150 | fh->vidq.field = f->fmt.pix.field; | 1128 | mbuf->offsets[i] = q->bufs[i]->boff; |
1151 | return 0; | 1129 | mbuf->size += q->bufs[i]->bsize; |
1152 | case V4L2_BUF_TYPE_VBI_CAPTURE: | ||
1153 | cx8800_vbi_fmt(dev, f); | ||
1154 | return 0; | ||
1155 | default: | ||
1156 | return -EINVAL; | ||
1157 | } | 1130 | } |
1131 | return 0; | ||
1158 | } | 1132 | } |
1133 | #endif | ||
1159 | 1134 | ||
1160 | /* | 1135 | static int vidioc_reqbufs (struct file *file, void *priv, struct v4l2_requestbuffers *p) |
1161 | * This function is _not_ called directly, but from | 1136 | { |
1162 | * video_generic_ioctl (and maybe others). userspace | 1137 | struct cx8800_fh *fh = priv; |
1163 | * copying is done already, arg is a kernel pointer. | 1138 | return (videobuf_reqbufs(get_queue(fh), p)); |
1164 | */ | 1139 | } |
1165 | static int video_do_ioctl(struct inode *inode, struct file *file, | 1140 | |
1166 | unsigned int cmd, void *arg) | 1141 | static int vidioc_querybuf (struct file *file, void *priv, struct v4l2_buffer *p) |
1142 | { | ||
1143 | struct cx8800_fh *fh = priv; | ||
1144 | return (videobuf_querybuf(get_queue(fh), p)); | ||
1145 | } | ||
1146 | |||
1147 | static int vidioc_qbuf (struct file *file, void *priv, struct v4l2_buffer *p) | ||
1148 | { | ||
1149 | struct cx8800_fh *fh = priv; | ||
1150 | return (videobuf_qbuf(get_queue(fh), p)); | ||
1151 | } | ||
1152 | |||
1153 | static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *p) | ||
1154 | { | ||
1155 | struct cx8800_fh *fh = priv; | ||
1156 | return (videobuf_dqbuf(get_queue(fh), p, | ||
1157 | file->f_flags & O_NONBLOCK)); | ||
1158 | } | ||
1159 | |||
1160 | static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) | ||
1167 | { | 1161 | { |
1168 | struct cx8800_fh *fh = file->private_data; | 1162 | struct cx8800_fh *fh = priv; |
1169 | struct cx8800_dev *dev = fh->dev; | 1163 | struct cx8800_dev *dev = fh->dev; |
1170 | struct cx88_core *core = dev->core; | ||
1171 | int err; | ||
1172 | 1164 | ||
1173 | if (video_debug > 1) | 1165 | if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) |
1174 | v4l_print_ioctl(core->name,cmd); | 1166 | return -EINVAL; |
1175 | switch (cmd) { | 1167 | if (unlikely(i != fh->type)) |
1168 | return -EINVAL; | ||
1176 | 1169 | ||
1177 | /* --- capabilities ------------------------------------------ */ | 1170 | if (unlikely(!res_get(dev,fh,get_ressource(fh)))) |
1178 | case VIDIOC_QUERYCAP: | 1171 | return -EBUSY; |
1179 | { | 1172 | return videobuf_streamon(get_queue(fh)); |
1180 | struct v4l2_capability *cap = arg; | 1173 | } |
1181 | |||
1182 | memset(cap,0,sizeof(*cap)); | ||
1183 | strcpy(cap->driver, "cx8800"); | ||
1184 | strlcpy(cap->card, cx88_boards[core->board].name, | ||
1185 | sizeof(cap->card)); | ||
1186 | sprintf(cap->bus_info,"PCI:%s",pci_name(dev->pci)); | ||
1187 | cap->version = CX88_VERSION_CODE; | ||
1188 | cap->capabilities = | ||
1189 | V4L2_CAP_VIDEO_CAPTURE | | ||
1190 | V4L2_CAP_READWRITE | | ||
1191 | V4L2_CAP_STREAMING | | ||
1192 | V4L2_CAP_VBI_CAPTURE | | ||
1193 | 0; | ||
1194 | if (UNSET != core->tuner_type) | ||
1195 | cap->capabilities |= V4L2_CAP_TUNER; | ||
1196 | return 0; | ||
1197 | } | ||
1198 | 1174 | ||
1199 | /* --- capture ioctls ---------------------------------------- */ | 1175 | static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) |
1200 | case VIDIOC_ENUM_FMT: | 1176 | { |
1201 | { | 1177 | struct cx8800_fh *fh = priv; |
1202 | struct v4l2_fmtdesc *f = arg; | 1178 | struct cx8800_dev *dev = fh->dev; |
1203 | enum v4l2_buf_type type; | 1179 | int err, res; |
1204 | unsigned int index; | ||
1205 | |||
1206 | index = f->index; | ||
1207 | type = f->type; | ||
1208 | switch (type) { | ||
1209 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
1210 | if (index >= ARRAY_SIZE(formats)) | ||
1211 | return -EINVAL; | ||
1212 | memset(f,0,sizeof(*f)); | ||
1213 | f->index = index; | ||
1214 | f->type = type; | ||
1215 | strlcpy(f->description,formats[index].name,sizeof(f->description)); | ||
1216 | f->pixelformat = formats[index].fourcc; | ||
1217 | break; | ||
1218 | default: | ||
1219 | return -EINVAL; | ||
1220 | } | ||
1221 | return 0; | ||
1222 | } | ||
1223 | case VIDIOC_G_FMT: | ||
1224 | { | ||
1225 | struct v4l2_format *f = arg; | ||
1226 | return cx8800_g_fmt(dev,fh,f); | ||
1227 | } | ||
1228 | case VIDIOC_S_FMT: | ||
1229 | { | ||
1230 | struct v4l2_format *f = arg; | ||
1231 | return cx8800_s_fmt(dev,fh,f); | ||
1232 | } | ||
1233 | case VIDIOC_TRY_FMT: | ||
1234 | { | ||
1235 | struct v4l2_format *f = arg; | ||
1236 | return cx8800_try_fmt(dev,fh,f); | ||
1237 | } | ||
1238 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | ||
1239 | /* --- streaming capture ------------------------------------- */ | ||
1240 | case VIDIOCGMBUF: | ||
1241 | { | ||
1242 | struct video_mbuf *mbuf = arg; | ||
1243 | struct videobuf_queue *q; | ||
1244 | struct v4l2_requestbuffers req; | ||
1245 | unsigned int i; | ||
1246 | |||
1247 | q = get_queue(fh); | ||
1248 | memset(&req,0,sizeof(req)); | ||
1249 | req.type = q->type; | ||
1250 | req.count = 8; | ||
1251 | req.memory = V4L2_MEMORY_MMAP; | ||
1252 | err = videobuf_reqbufs(q,&req); | ||
1253 | if (err < 0) | ||
1254 | return err; | ||
1255 | memset(mbuf,0,sizeof(*mbuf)); | ||
1256 | mbuf->frames = req.count; | ||
1257 | mbuf->size = 0; | ||
1258 | for (i = 0; i < mbuf->frames; i++) { | ||
1259 | mbuf->offsets[i] = q->bufs[i]->boff; | ||
1260 | mbuf->size += q->bufs[i]->bsize; | ||
1261 | } | ||
1262 | return 0; | ||
1263 | } | ||
1264 | #endif | ||
1265 | case VIDIOC_REQBUFS: | ||
1266 | return videobuf_reqbufs(get_queue(fh), arg); | ||
1267 | 1180 | ||
1268 | case VIDIOC_QUERYBUF: | 1181 | if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
1269 | return videobuf_querybuf(get_queue(fh), arg); | 1182 | return -EINVAL; |
1183 | if (i != fh->type) | ||
1184 | return -EINVAL; | ||
1270 | 1185 | ||
1271 | case VIDIOC_QBUF: | 1186 | res = get_ressource(fh); |
1272 | return videobuf_qbuf(get_queue(fh), arg); | 1187 | err = videobuf_streamoff(get_queue(fh)); |
1188 | if (err < 0) | ||
1189 | return err; | ||
1190 | res_free(dev,fh,res); | ||
1191 | return 0; | ||
1192 | } | ||
1273 | 1193 | ||
1274 | case VIDIOC_DQBUF: | 1194 | static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *tvnorms) |
1275 | return videobuf_dqbuf(get_queue(fh), arg, | 1195 | { |
1276 | file->f_flags & O_NONBLOCK); | 1196 | struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core; |
1277 | 1197 | ||
1278 | case VIDIOC_STREAMON: | 1198 | mutex_lock(&core->lock); |
1279 | { | 1199 | cx88_set_tvnorm(core,*tvnorms); |
1280 | int res = get_ressource(fh); | 1200 | mutex_unlock(&core->lock); |
1281 | 1201 | ||
1282 | if (!res_get(dev,fh,res)) | 1202 | return 0; |
1283 | return -EBUSY; | 1203 | } |
1284 | return videobuf_streamon(get_queue(fh)); | ||
1285 | } | ||
1286 | case VIDIOC_STREAMOFF: | ||
1287 | { | ||
1288 | int res = get_ressource(fh); | ||
1289 | 1204 | ||
1290 | err = videobuf_streamoff(get_queue(fh)); | 1205 | /* only one input in this sample driver */ |
1291 | if (err < 0) | 1206 | int cx88_enum_input (struct cx88_core *core,struct v4l2_input *i) |
1292 | return err; | 1207 | { |
1293 | res_free(dev,fh,res); | 1208 | static const char *iname[] = { |
1294 | return 0; | 1209 | [ CX88_VMUX_COMPOSITE1 ] = "Composite1", |
1295 | } | 1210 | [ CX88_VMUX_COMPOSITE2 ] = "Composite2", |
1296 | default: | 1211 | [ CX88_VMUX_COMPOSITE3 ] = "Composite3", |
1297 | return cx88_do_ioctl( inode, file, fh->radio, core, cmd, arg, video_do_ioctl ); | 1212 | [ CX88_VMUX_COMPOSITE4 ] = "Composite4", |
1298 | } | 1213 | [ CX88_VMUX_SVIDEO ] = "S-Video", |
1214 | [ CX88_VMUX_TELEVISION ] = "Television", | ||
1215 | [ CX88_VMUX_CABLE ] = "Cable TV", | ||
1216 | [ CX88_VMUX_DVB ] = "DVB", | ||
1217 | [ CX88_VMUX_DEBUG ] = "for debug only", | ||
1218 | }; | ||
1219 | unsigned int n; | ||
1220 | |||
1221 | n = i->index; | ||
1222 | if (n >= 4) | ||
1223 | return -EINVAL; | ||
1224 | if (0 == INPUT(n)->type) | ||
1225 | return -EINVAL; | ||
1226 | memset(i,0,sizeof(*i)); | ||
1227 | i->index = n; | ||
1228 | i->type = V4L2_INPUT_TYPE_CAMERA; | ||
1229 | strcpy(i->name,iname[INPUT(n)->type]); | ||
1230 | if ((CX88_VMUX_TELEVISION == INPUT(n)->type) || | ||
1231 | (CX88_VMUX_CABLE == INPUT(n)->type)) | ||
1232 | i->type = V4L2_INPUT_TYPE_TUNER; | ||
1233 | i->std = CX88_NORMS; | ||
1299 | return 0; | 1234 | return 0; |
1300 | } | 1235 | } |
1236 | EXPORT_SYMBOL(cx88_enum_input); | ||
1301 | 1237 | ||
1302 | int cx88_do_ioctl(struct inode *inode, struct file *file, int radio, | 1238 | static int vidioc_enum_input (struct file *file, void *priv, |
1303 | struct cx88_core *core, unsigned int cmd, void *arg, v4l2_kioctl driver_ioctl) | 1239 | struct v4l2_input *i) |
1304 | { | 1240 | { |
1305 | int err; | 1241 | struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core; |
1242 | return cx88_enum_input (core,i); | ||
1243 | } | ||
1306 | 1244 | ||
1307 | if (video_debug) { | 1245 | static int vidioc_g_input (struct file *file, void *priv, unsigned int *i) |
1308 | if (video_debug > 1) { | 1246 | { |
1309 | if (_IOC_DIR(cmd) & _IOC_WRITE) | 1247 | struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core; |
1310 | v4l_printk_ioctl_arg("cx88(w)",cmd, arg); | ||
1311 | else if (!_IOC_DIR(cmd) & _IOC_READ) { | ||
1312 | v4l_print_ioctl("cx88", cmd); | ||
1313 | } | ||
1314 | } else | ||
1315 | v4l_print_ioctl(core->name,cmd); | ||
1316 | |||
1317 | } | ||
1318 | |||
1319 | switch (cmd) { | ||
1320 | /* ---------- tv norms ---------- */ | ||
1321 | case VIDIOC_ENUMSTD: | ||
1322 | { | ||
1323 | struct v4l2_standard *e = arg; | ||
1324 | unsigned int i; | ||
1325 | |||
1326 | i = e->index; | ||
1327 | if (i >= ARRAY_SIZE(tvnorms)) | ||
1328 | return -EINVAL; | ||
1329 | err = v4l2_video_std_construct(e, tvnorms[e->index].id, | ||
1330 | tvnorms[e->index].name); | ||
1331 | e->index = i; | ||
1332 | if (err < 0) | ||
1333 | return err; | ||
1334 | return 0; | ||
1335 | } | ||
1336 | case VIDIOC_G_STD: | ||
1337 | { | ||
1338 | v4l2_std_id *id = arg; | ||
1339 | 1248 | ||
1340 | *id = core->tvnorm->id; | 1249 | *i = core->input; |
1341 | return 0; | 1250 | return 0; |
1342 | } | 1251 | } |
1343 | case VIDIOC_S_STD: | ||
1344 | { | ||
1345 | v4l2_std_id *id = arg; | ||
1346 | unsigned int i; | ||
1347 | 1252 | ||
1348 | for(i = 0; i < ARRAY_SIZE(tvnorms); i++) | 1253 | static int vidioc_s_input (struct file *file, void *priv, unsigned int i) |
1349 | if (*id & tvnorms[i].id) | 1254 | { |
1350 | break; | 1255 | struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core; |
1351 | if (i == ARRAY_SIZE(tvnorms)) | ||
1352 | return -EINVAL; | ||
1353 | 1256 | ||
1354 | mutex_lock(&core->lock); | 1257 | if (i >= 4) |
1355 | cx88_set_tvnorm(core,&tvnorms[i]); | 1258 | return -EINVAL; |
1356 | mutex_unlock(&core->lock); | ||
1357 | return 0; | ||
1358 | } | ||
1359 | 1259 | ||
1360 | /* ------ input switching ---------- */ | 1260 | mutex_lock(&core->lock); |
1361 | case VIDIOC_ENUMINPUT: | 1261 | cx88_newstation(core); |
1362 | { | 1262 | cx88_video_mux(core,i); |
1363 | static const char *iname[] = { | 1263 | mutex_unlock(&core->lock); |
1364 | [ CX88_VMUX_COMPOSITE1 ] = "Composite1", | 1264 | return 0; |
1365 | [ CX88_VMUX_COMPOSITE2 ] = "Composite2", | 1265 | } |
1366 | [ CX88_VMUX_COMPOSITE3 ] = "Composite3", | ||
1367 | [ CX88_VMUX_COMPOSITE4 ] = "Composite4", | ||
1368 | [ CX88_VMUX_SVIDEO ] = "S-Video", | ||
1369 | [ CX88_VMUX_TELEVISION ] = "Television", | ||
1370 | [ CX88_VMUX_CABLE ] = "Cable TV", | ||
1371 | [ CX88_VMUX_DVB ] = "DVB", | ||
1372 | [ CX88_VMUX_DEBUG ] = "for debug only", | ||
1373 | }; | ||
1374 | struct v4l2_input *i = arg; | ||
1375 | unsigned int n; | ||
1376 | |||
1377 | n = i->index; | ||
1378 | if (n >= 4) | ||
1379 | return -EINVAL; | ||
1380 | if (0 == INPUT(n)->type) | ||
1381 | return -EINVAL; | ||
1382 | memset(i,0,sizeof(*i)); | ||
1383 | i->index = n; | ||
1384 | i->type = V4L2_INPUT_TYPE_CAMERA; | ||
1385 | strcpy(i->name,iname[INPUT(n)->type]); | ||
1386 | if ((CX88_VMUX_TELEVISION == INPUT(n)->type) || | ||
1387 | (CX88_VMUX_CABLE == INPUT(n)->type)) | ||
1388 | i->type = V4L2_INPUT_TYPE_TUNER; | ||
1389 | for (n = 0; n < ARRAY_SIZE(tvnorms); n++) | ||
1390 | i->std |= tvnorms[n].id; | ||
1391 | return 0; | ||
1392 | } | ||
1393 | case VIDIOC_G_INPUT: | ||
1394 | { | ||
1395 | unsigned int *i = arg; | ||
1396 | 1266 | ||
1397 | *i = core->input; | ||
1398 | return 0; | ||
1399 | } | ||
1400 | case VIDIOC_S_INPUT: | ||
1401 | { | ||
1402 | unsigned int *i = arg; | ||
1403 | 1267 | ||
1404 | if (*i >= 4) | ||
1405 | return -EINVAL; | ||
1406 | mutex_lock(&core->lock); | ||
1407 | cx88_newstation(core); | ||
1408 | video_mux(core,*i); | ||
1409 | mutex_unlock(&core->lock); | ||
1410 | return 0; | ||
1411 | } | ||
1412 | 1268 | ||
1269 | static int vidioc_queryctrl (struct file *file, void *priv, | ||
1270 | struct v4l2_queryctrl *qctrl) | ||
1271 | { | ||
1272 | qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id); | ||
1273 | if (unlikely(qctrl->id == 0)) | ||
1274 | return -EINVAL; | ||
1275 | return cx8800_ctrl_query(qctrl); | ||
1276 | } | ||
1413 | 1277 | ||
1278 | static int vidioc_g_ctrl (struct file *file, void *priv, | ||
1279 | struct v4l2_control *ctl) | ||
1280 | { | ||
1281 | struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core; | ||
1282 | return | ||
1283 | cx88_get_control(core,ctl); | ||
1284 | } | ||
1414 | 1285 | ||
1415 | /* --- controls ---------------------------------------------- */ | 1286 | static int vidioc_s_ctrl (struct file *file, void *priv, |
1416 | case VIDIOC_QUERYCTRL: | 1287 | struct v4l2_control *ctl) |
1417 | { | 1288 | { |
1418 | struct v4l2_queryctrl *c = arg; | 1289 | struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core; |
1290 | return | ||
1291 | cx88_set_control(core,ctl); | ||
1292 | } | ||
1419 | 1293 | ||
1420 | return cx88_queryctrl(c); | 1294 | static int vidioc_g_tuner (struct file *file, void *priv, |
1421 | } | 1295 | struct v4l2_tuner *t) |
1422 | case VIDIOC_G_CTRL: | 1296 | { |
1423 | return get_control(core,arg); | 1297 | struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core; |
1424 | case VIDIOC_S_CTRL: | 1298 | u32 reg; |
1425 | return set_control(core,arg); | ||
1426 | 1299 | ||
1427 | /* --- tuner ioctls ------------------------------------------ */ | 1300 | if (unlikely(UNSET == core->tuner_type)) |
1428 | case VIDIOC_G_TUNER: | 1301 | return -EINVAL; |
1429 | { | 1302 | if (0 != t->index) |
1430 | struct v4l2_tuner *t = arg; | 1303 | return -EINVAL; |
1431 | u32 reg; | ||
1432 | |||
1433 | if (UNSET == core->tuner_type) | ||
1434 | return -EINVAL; | ||
1435 | if (0 != t->index) | ||
1436 | return -EINVAL; | ||
1437 | |||
1438 | memset(t,0,sizeof(*t)); | ||
1439 | strcpy(t->name, "Television"); | ||
1440 | t->type = V4L2_TUNER_ANALOG_TV; | ||
1441 | t->capability = V4L2_TUNER_CAP_NORM; | ||
1442 | t->rangehigh = 0xffffffffUL; | ||
1443 | |||
1444 | cx88_get_stereo(core ,t); | ||
1445 | reg = cx_read(MO_DEVICE_STATUS); | ||
1446 | t->signal = (reg & (1<<5)) ? 0xffff : 0x0000; | ||
1447 | return 0; | ||
1448 | } | ||
1449 | case VIDIOC_S_TUNER: | ||
1450 | { | ||
1451 | struct v4l2_tuner *t = arg; | ||
1452 | 1304 | ||
1453 | if (UNSET == core->tuner_type) | 1305 | strcpy(t->name, "Television"); |
1454 | return -EINVAL; | 1306 | t->type = V4L2_TUNER_ANALOG_TV; |
1455 | if (0 != t->index) | 1307 | t->capability = V4L2_TUNER_CAP_NORM; |
1456 | return -EINVAL; | 1308 | t->rangehigh = 0xffffffffUL; |
1457 | cx88_set_stereo(core, t->audmode, 1); | ||
1458 | return 0; | ||
1459 | } | ||
1460 | case VIDIOC_G_FREQUENCY: | ||
1461 | { | ||
1462 | struct v4l2_frequency *f = arg; | ||
1463 | 1309 | ||
1464 | memset(f,0,sizeof(*f)); | 1310 | cx88_get_stereo(core ,t); |
1311 | reg = cx_read(MO_DEVICE_STATUS); | ||
1312 | t->signal = (reg & (1<<5)) ? 0xffff : 0x0000; | ||
1313 | return 0; | ||
1314 | } | ||
1465 | 1315 | ||
1466 | if (UNSET == core->tuner_type) | 1316 | static int vidioc_s_tuner (struct file *file, void *priv, |
1467 | return -EINVAL; | 1317 | struct v4l2_tuner *t) |
1318 | { | ||
1319 | struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core; | ||
1468 | 1320 | ||
1469 | /* f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; */ | 1321 | if (UNSET == core->tuner_type) |
1470 | f->type = radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; | 1322 | return -EINVAL; |
1471 | f->frequency = core->freq; | 1323 | if (0 != t->index) |
1324 | return -EINVAL; | ||
1472 | 1325 | ||
1473 | cx88_call_i2c_clients(core,VIDIOC_G_FREQUENCY,f); | 1326 | cx88_set_stereo(core, t->audmode, 1); |
1327 | return 0; | ||
1328 | } | ||
1474 | 1329 | ||
1475 | return 0; | 1330 | static int vidioc_g_frequency (struct file *file, void *priv, |
1476 | } | 1331 | struct v4l2_frequency *f) |
1477 | case VIDIOC_S_FREQUENCY: | 1332 | { |
1478 | { | 1333 | struct cx8800_fh *fh = priv; |
1479 | struct v4l2_frequency *f = arg; | 1334 | struct cx88_core *core = fh->dev->core; |
1480 | |||
1481 | if (UNSET == core->tuner_type) | ||
1482 | return -EINVAL; | ||
1483 | if (f->tuner != 0) | ||
1484 | return -EINVAL; | ||
1485 | if (0 == radio && f->type != V4L2_TUNER_ANALOG_TV) | ||
1486 | return -EINVAL; | ||
1487 | if (1 == radio && f->type != V4L2_TUNER_RADIO) | ||
1488 | return -EINVAL; | ||
1489 | mutex_lock(&core->lock); | ||
1490 | core->freq = f->frequency; | ||
1491 | cx88_newstation(core); | ||
1492 | cx88_call_i2c_clients(core,VIDIOC_S_FREQUENCY,f); | ||
1493 | |||
1494 | /* When changing channels it is required to reset TVAUDIO */ | ||
1495 | msleep (10); | ||
1496 | cx88_set_tvaudio(core); | ||
1497 | 1335 | ||
1498 | mutex_unlock(&core->lock); | 1336 | if (unlikely(UNSET == core->tuner_type)) |
1499 | return 0; | 1337 | return -EINVAL; |
1500 | } | ||
1501 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
1502 | /* ioctls to allow direct acces to the cx2388x registers */ | ||
1503 | case VIDIOC_INT_G_REGISTER: | ||
1504 | { | ||
1505 | struct v4l2_register *reg = arg; | ||
1506 | 1338 | ||
1507 | if (reg->i2c_id != 0) | 1339 | /* f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; */ |
1508 | return -EINVAL; | 1340 | f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; |
1509 | /* cx2388x has a 24-bit register space */ | 1341 | f->frequency = core->freq; |
1510 | reg->val = cx_read(reg->reg&0xffffff); | ||
1511 | return 0; | ||
1512 | } | ||
1513 | case VIDIOC_INT_S_REGISTER: | ||
1514 | { | ||
1515 | struct v4l2_register *reg = arg; | ||
1516 | 1342 | ||
1517 | if (reg->i2c_id != 0) | 1343 | cx88_call_i2c_clients(core,VIDIOC_G_FREQUENCY,f); |
1518 | return -EINVAL; | ||
1519 | if (!capable(CAP_SYS_ADMIN)) | ||
1520 | return -EPERM; | ||
1521 | cx_write(reg->reg&0xffffff, reg->val); | ||
1522 | return 0; | ||
1523 | } | ||
1524 | #endif | ||
1525 | 1344 | ||
1526 | default: | ||
1527 | return v4l_compat_translate_ioctl(inode,file,cmd,arg, | ||
1528 | driver_ioctl); | ||
1529 | } | ||
1530 | return 0; | 1345 | return 0; |
1531 | } | 1346 | } |
1532 | 1347 | ||
1533 | static int video_ioctl(struct inode *inode, struct file *file, | 1348 | int cx88_set_freq (struct cx88_core *core, |
1534 | unsigned int cmd, unsigned long arg) | 1349 | struct v4l2_frequency *f) |
1535 | { | 1350 | { |
1536 | int retval; | 1351 | if (unlikely(UNSET == core->tuner_type)) |
1352 | return -EINVAL; | ||
1353 | if (unlikely(f->tuner != 0)) | ||
1354 | return -EINVAL; | ||
1537 | 1355 | ||
1538 | retval=video_usercopy(inode, file, cmd, arg, video_do_ioctl); | 1356 | mutex_lock(&core->lock); |
1357 | core->freq = f->frequency; | ||
1358 | cx88_newstation(core); | ||
1359 | cx88_call_i2c_clients(core,VIDIOC_S_FREQUENCY,f); | ||
1360 | |||
1361 | /* When changing channels it is required to reset TVAUDIO */ | ||
1362 | msleep (10); | ||
1363 | cx88_set_tvaudio(core); | ||
1539 | 1364 | ||
1540 | if (video_debug > 1) { | 1365 | mutex_unlock(&core->lock); |
1541 | if (retval < 0) { | 1366 | |
1542 | v4l_print_ioctl("cx88(err)", cmd); | 1367 | return 0; |
1543 | printk(KERN_DEBUG "cx88(err): errcode=%d\n",retval); | 1368 | } |
1544 | } else if (_IOC_DIR(cmd) & _IOC_READ) | 1369 | EXPORT_SYMBOL(cx88_set_freq); |
1545 | v4l_printk_ioctl_arg("cx88(r)",cmd, (void *)arg); | 1370 | |
1546 | } | 1371 | static int vidioc_s_frequency (struct file *file, void *priv, |
1372 | struct v4l2_frequency *f) | ||
1373 | { | ||
1374 | struct cx8800_fh *fh = priv; | ||
1375 | struct cx88_core *core = fh->dev->core; | ||
1547 | 1376 | ||
1548 | return retval; | 1377 | if (unlikely(0 == fh->radio && f->type != V4L2_TUNER_ANALOG_TV)) |
1378 | return -EINVAL; | ||
1379 | if (unlikely(1 == fh->radio && f->type != V4L2_TUNER_RADIO)) | ||
1380 | return -EINVAL; | ||
1381 | |||
1382 | return | ||
1383 | cx88_set_freq (core,f); | ||
1384 | } | ||
1385 | |||
1386 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
1387 | static int vidioc_g_register (struct file *file, void *fh, | ||
1388 | struct v4l2_register *reg) | ||
1389 | { | ||
1390 | struct cx88_core *core = ((struct cx8800_fh*)fh)->dev->core; | ||
1391 | |||
1392 | if (reg->i2c_id != 0) | ||
1393 | return -EINVAL; | ||
1394 | /* cx2388x has a 24-bit register space */ | ||
1395 | reg->val = cx_read(reg->reg&0xffffff); | ||
1396 | return 0; | ||
1549 | } | 1397 | } |
1550 | 1398 | ||
1399 | static int vidioc_s_register (struct file *file, void *fh, | ||
1400 | struct v4l2_register *reg) | ||
1401 | { | ||
1402 | struct cx88_core *core = ((struct cx8800_fh*)fh)->dev->core; | ||
1403 | |||
1404 | if (reg->i2c_id != 0) | ||
1405 | return -EINVAL; | ||
1406 | cx_write(reg->reg&0xffffff, reg->val); | ||
1407 | return 0; | ||
1408 | } | ||
1409 | #endif | ||
1410 | |||
1411 | /* ----------------------------------------------------------- */ | ||
1412 | /* RADIO ESPECIFIC IOCTLS */ | ||
1551 | /* ----------------------------------------------------------- */ | 1413 | /* ----------------------------------------------------------- */ |
1552 | 1414 | ||
1553 | static int radio_do_ioctl(struct inode *inode, struct file *file, | 1415 | static int radio_querycap (struct file *file, void *priv, |
1554 | unsigned int cmd, void *arg) | 1416 | struct v4l2_capability *cap) |
1555 | { | 1417 | { |
1556 | struct cx8800_fh *fh = file->private_data; | 1418 | struct cx8800_dev *dev = ((struct cx8800_fh *)priv)->dev; |
1557 | struct cx8800_dev *dev = fh->dev; | ||
1558 | struct cx88_core *core = dev->core; | 1419 | struct cx88_core *core = dev->core; |
1559 | 1420 | ||
1560 | if (video_debug > 1) | 1421 | strcpy(cap->driver, "cx8800"); |
1561 | v4l_print_ioctl(core->name,cmd); | 1422 | strlcpy(cap->card, cx88_boards[core->board].name, |
1562 | 1423 | sizeof(cap->card)); | |
1563 | switch (cmd) { | 1424 | sprintf(cap->bus_info,"PCI:%s", pci_name(dev->pci)); |
1564 | case VIDIOC_QUERYCAP: | 1425 | cap->version = CX88_VERSION_CODE; |
1565 | { | 1426 | cap->capabilities = V4L2_CAP_TUNER; |
1566 | struct v4l2_capability *cap = arg; | 1427 | return 0; |
1567 | 1428 | } | |
1568 | memset(cap,0,sizeof(*cap)); | ||
1569 | strcpy(cap->driver, "cx8800"); | ||
1570 | strlcpy(cap->card, cx88_boards[core->board].name, | ||
1571 | sizeof(cap->card)); | ||
1572 | sprintf(cap->bus_info,"PCI:%s", pci_name(dev->pci)); | ||
1573 | cap->version = CX88_VERSION_CODE; | ||
1574 | cap->capabilities = V4L2_CAP_TUNER; | ||
1575 | return 0; | ||
1576 | } | ||
1577 | case VIDIOC_G_TUNER: | ||
1578 | { | ||
1579 | struct v4l2_tuner *t = arg; | ||
1580 | 1429 | ||
1581 | if (t->index > 0) | 1430 | static int radio_g_tuner (struct file *file, void *priv, |
1582 | return -EINVAL; | 1431 | struct v4l2_tuner *t) |
1432 | { | ||
1433 | struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core; | ||
1583 | 1434 | ||
1584 | memset(t,0,sizeof(*t)); | 1435 | if (unlikely(t->index > 0)) |
1585 | strcpy(t->name, "Radio"); | 1436 | return -EINVAL; |
1586 | t->type = V4L2_TUNER_RADIO; | ||
1587 | 1437 | ||
1588 | cx88_call_i2c_clients(core,VIDIOC_G_TUNER,t); | 1438 | strcpy(t->name, "Radio"); |
1589 | return 0; | 1439 | t->type = V4L2_TUNER_RADIO; |
1590 | } | ||
1591 | case VIDIOC_ENUMINPUT: | ||
1592 | { | ||
1593 | struct v4l2_input *i = arg; | ||
1594 | 1440 | ||
1595 | if (i->index != 0) | 1441 | cx88_call_i2c_clients(core,VIDIOC_G_TUNER,t); |
1596 | return -EINVAL; | 1442 | return 0; |
1597 | strcpy(i->name,"Radio"); | 1443 | } |
1598 | i->type = V4L2_INPUT_TYPE_TUNER; | ||
1599 | return 0; | ||
1600 | } | ||
1601 | case VIDIOC_G_INPUT: | ||
1602 | { | ||
1603 | int *i = arg; | ||
1604 | *i = 0; | ||
1605 | return 0; | ||
1606 | } | ||
1607 | case VIDIOC_G_AUDIO: | ||
1608 | { | ||
1609 | struct v4l2_audio *a = arg; | ||
1610 | 1444 | ||
1611 | memset(a,0,sizeof(*a)); | 1445 | static int radio_enum_input (struct file *file, void *priv, |
1612 | strcpy(a->name,"Radio"); | 1446 | struct v4l2_input *i) |
1613 | return 0; | 1447 | { |
1614 | } | 1448 | if (i->index != 0) |
1615 | case VIDIOC_G_STD: | 1449 | return -EINVAL; |
1616 | { | 1450 | strcpy(i->name,"Radio"); |
1617 | v4l2_std_id *id = arg; | 1451 | i->type = V4L2_INPUT_TYPE_TUNER; |
1618 | *id = 0; | ||
1619 | return 0; | ||
1620 | } | ||
1621 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | ||
1622 | case VIDIOCSTUNER: | ||
1623 | { | ||
1624 | struct video_tuner *v = arg; | ||
1625 | 1452 | ||
1626 | if (v->tuner) /* Only tuner 0 */ | 1453 | return 0; |
1627 | return -EINVAL; | 1454 | } |
1628 | 1455 | ||
1629 | cx88_call_i2c_clients(core,VIDIOCSTUNER,v); | 1456 | static int radio_g_audio (struct file *file, void *priv, struct v4l2_audio *a) |
1630 | return 0; | 1457 | { |
1631 | } | 1458 | if (unlikely(a->index)) |
1632 | #endif | 1459 | return -EINVAL; |
1633 | case VIDIOC_S_TUNER: | ||
1634 | { | ||
1635 | struct v4l2_tuner *t = arg; | ||
1636 | 1460 | ||
1637 | if (0 != t->index) | 1461 | memset(a,0,sizeof(*a)); |
1638 | return -EINVAL; | 1462 | strcpy(a->name,"Radio"); |
1463 | return 0; | ||
1464 | } | ||
1639 | 1465 | ||
1640 | cx88_call_i2c_clients(core,VIDIOC_S_TUNER,t); | 1466 | /* FIXME: Should add a standard for radio */ |
1641 | 1467 | ||
1642 | return 0; | 1468 | static int radio_s_tuner (struct file *file, void *priv, |
1643 | } | 1469 | struct v4l2_tuner *t) |
1470 | { | ||
1471 | struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core; | ||
1644 | 1472 | ||
1645 | case VIDIOC_S_AUDIO: | 1473 | if (0 != t->index) |
1646 | case VIDIOC_S_INPUT: | 1474 | return -EINVAL; |
1647 | case VIDIOC_S_STD: | ||
1648 | return 0; | ||
1649 | 1475 | ||
1650 | case VIDIOC_QUERYCTRL: | 1476 | cx88_call_i2c_clients(core,VIDIOC_S_TUNER,t); |
1651 | { | ||
1652 | struct v4l2_queryctrl *c = arg; | ||
1653 | int i; | ||
1654 | |||
1655 | if (c->id < V4L2_CID_BASE || | ||
1656 | c->id >= V4L2_CID_LASTP1) | ||
1657 | return -EINVAL; | ||
1658 | if (c->id == V4L2_CID_AUDIO_MUTE) { | ||
1659 | for (i = 0; i < CX8800_CTLS; i++) | ||
1660 | if (cx8800_ctls[i].v.id == c->id) | ||
1661 | break; | ||
1662 | *c = cx8800_ctls[i].v; | ||
1663 | } else | ||
1664 | *c = no_ctl; | ||
1665 | return 0; | ||
1666 | } | ||
1667 | 1477 | ||
1478 | return 0; | ||
1479 | } | ||
1668 | 1480 | ||
1669 | case VIDIOC_G_CTRL: | 1481 | static int radio_s_audio (struct file *file, void *fh, |
1670 | case VIDIOC_S_CTRL: | 1482 | struct v4l2_audio *a) |
1671 | case VIDIOC_G_FREQUENCY: | 1483 | { |
1672 | case VIDIOC_S_FREQUENCY: | 1484 | return 0; |
1673 | return video_do_ioctl(inode,file,cmd,arg); | 1485 | } |
1674 | 1486 | ||
1675 | default: | 1487 | static int radio_s_input (struct file *file, void *fh, unsigned int i) |
1676 | return v4l_compat_translate_ioctl(inode,file,cmd,arg, | 1488 | { |
1677 | radio_do_ioctl); | ||
1678 | } | ||
1679 | return 0; | 1489 | return 0; |
1680 | }; | 1490 | } |
1681 | 1491 | ||
1682 | static int radio_ioctl(struct inode *inode, struct file *file, | 1492 | static int radio_queryctrl (struct file *file, void *priv, |
1683 | unsigned int cmd, unsigned long arg) | 1493 | struct v4l2_queryctrl *c) |
1684 | { | 1494 | { |
1685 | return video_usercopy(inode, file, cmd, arg, radio_do_ioctl); | 1495 | int i; |
1686 | }; | 1496 | |
1497 | if (c->id < V4L2_CID_BASE || | ||
1498 | c->id >= V4L2_CID_LASTP1) | ||
1499 | return -EINVAL; | ||
1500 | if (c->id == V4L2_CID_AUDIO_MUTE) { | ||
1501 | for (i = 0; i < CX8800_CTLS; i++) | ||
1502 | if (cx8800_ctls[i].v.id == c->id) | ||
1503 | break; | ||
1504 | *c = cx8800_ctls[i].v; | ||
1505 | } else | ||
1506 | *c = no_ctl; | ||
1507 | return 0; | ||
1508 | } | ||
1687 | 1509 | ||
1688 | /* ----------------------------------------------------------- */ | 1510 | /* ----------------------------------------------------------- */ |
1689 | 1511 | ||
@@ -1816,27 +1638,52 @@ static const struct file_operations video_fops = | |||
1816 | .read = video_read, | 1638 | .read = video_read, |
1817 | .poll = video_poll, | 1639 | .poll = video_poll, |
1818 | .mmap = video_mmap, | 1640 | .mmap = video_mmap, |
1819 | .ioctl = video_ioctl, | 1641 | .ioctl = video_ioctl2, |
1820 | .compat_ioctl = v4l_compat_ioctl32, | 1642 | .compat_ioctl = v4l_compat_ioctl32, |
1821 | .llseek = no_llseek, | 1643 | .llseek = no_llseek, |
1822 | }; | 1644 | }; |
1823 | 1645 | ||
1646 | static struct video_device cx8800_vbi_template; | ||
1824 | static struct video_device cx8800_video_template = | 1647 | static struct video_device cx8800_video_template = |
1825 | { | 1648 | { |
1826 | .name = "cx8800-video", | 1649 | .name = "cx8800-video", |
1827 | .type = VID_TYPE_CAPTURE|VID_TYPE_TUNER|VID_TYPE_SCALES, | 1650 | .type = VID_TYPE_CAPTURE|VID_TYPE_TUNER|VID_TYPE_SCALES, |
1828 | .hardware = 0, | 1651 | .fops = &video_fops, |
1829 | .fops = &video_fops, | 1652 | .minor = -1, |
1830 | .minor = -1, | 1653 | .vidioc_querycap = vidioc_querycap, |
1831 | }; | 1654 | .vidioc_enum_fmt_cap = vidioc_enum_fmt_cap, |
1832 | 1655 | .vidioc_g_fmt_cap = vidioc_g_fmt_cap, | |
1833 | static struct video_device cx8800_vbi_template = | 1656 | .vidioc_try_fmt_cap = vidioc_try_fmt_cap, |
1834 | { | 1657 | .vidioc_s_fmt_cap = vidioc_s_fmt_cap, |
1835 | .name = "cx8800-vbi", | 1658 | .vidioc_g_fmt_vbi = cx8800_vbi_fmt, |
1836 | .type = VID_TYPE_TELETEXT|VID_TYPE_TUNER, | 1659 | .vidioc_try_fmt_vbi = cx8800_vbi_fmt, |
1837 | .hardware = 0, | 1660 | .vidioc_s_fmt_vbi = cx8800_vbi_fmt, |
1838 | .fops = &video_fops, | 1661 | .vidioc_reqbufs = vidioc_reqbufs, |
1839 | .minor = -1, | 1662 | .vidioc_querybuf = vidioc_querybuf, |
1663 | .vidioc_qbuf = vidioc_qbuf, | ||
1664 | .vidioc_dqbuf = vidioc_dqbuf, | ||
1665 | .vidioc_s_std = vidioc_s_std, | ||
1666 | .vidioc_enum_input = vidioc_enum_input, | ||
1667 | .vidioc_g_input = vidioc_g_input, | ||
1668 | .vidioc_s_input = vidioc_s_input, | ||
1669 | .vidioc_queryctrl = vidioc_queryctrl, | ||
1670 | .vidioc_g_ctrl = vidioc_g_ctrl, | ||
1671 | .vidioc_s_ctrl = vidioc_s_ctrl, | ||
1672 | .vidioc_streamon = vidioc_streamon, | ||
1673 | .vidioc_streamoff = vidioc_streamoff, | ||
1674 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | ||
1675 | .vidiocgmbuf = vidiocgmbuf, | ||
1676 | #endif | ||
1677 | .vidioc_g_tuner = vidioc_g_tuner, | ||
1678 | .vidioc_s_tuner = vidioc_s_tuner, | ||
1679 | .vidioc_g_frequency = vidioc_g_frequency, | ||
1680 | .vidioc_s_frequency = vidioc_s_frequency, | ||
1681 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
1682 | .vidioc_g_register = vidioc_g_register, | ||
1683 | .vidioc_s_register = vidioc_s_register, | ||
1684 | #endif | ||
1685 | .tvnorms = CX88_NORMS, | ||
1686 | .current_norm = V4L2_STD_NTSC_M, | ||
1840 | }; | 1687 | }; |
1841 | 1688 | ||
1842 | static const struct file_operations radio_fops = | 1689 | static const struct file_operations radio_fops = |
@@ -1844,18 +1691,30 @@ static const struct file_operations radio_fops = | |||
1844 | .owner = THIS_MODULE, | 1691 | .owner = THIS_MODULE, |
1845 | .open = video_open, | 1692 | .open = video_open, |
1846 | .release = video_release, | 1693 | .release = video_release, |
1847 | .ioctl = radio_ioctl, | 1694 | .ioctl = video_ioctl2, |
1848 | .compat_ioctl = v4l_compat_ioctl32, | 1695 | .compat_ioctl = v4l_compat_ioctl32, |
1849 | .llseek = no_llseek, | 1696 | .llseek = no_llseek, |
1850 | }; | 1697 | }; |
1851 | 1698 | ||
1852 | static struct video_device cx8800_radio_template = | 1699 | static struct video_device cx8800_radio_template = |
1853 | { | 1700 | { |
1854 | .name = "cx8800-radio", | 1701 | .name = "cx8800-radio", |
1855 | .type = VID_TYPE_TUNER, | 1702 | .type = VID_TYPE_TUNER, |
1856 | .hardware = 0, | 1703 | .hardware = 0, |
1857 | .fops = &radio_fops, | 1704 | .fops = &radio_fops, |
1858 | .minor = -1, | 1705 | .minor = -1, |
1706 | .vidioc_querycap = radio_querycap, | ||
1707 | .vidioc_g_tuner = radio_g_tuner, | ||
1708 | .vidioc_enum_input = radio_enum_input, | ||
1709 | .vidioc_g_audio = radio_g_audio, | ||
1710 | .vidioc_s_tuner = radio_s_tuner, | ||
1711 | .vidioc_s_audio = radio_s_audio, | ||
1712 | .vidioc_s_input = radio_s_input, | ||
1713 | .vidioc_queryctrl = radio_queryctrl, | ||
1714 | .vidioc_g_ctrl = vidioc_g_ctrl, | ||
1715 | .vidioc_s_ctrl = vidioc_s_ctrl, | ||
1716 | .vidioc_g_frequency = vidioc_g_frequency, | ||
1717 | .vidioc_s_frequency = vidioc_s_frequency, | ||
1859 | }; | 1718 | }; |
1860 | 1719 | ||
1861 | /* ----------------------------------------------------------- */ | 1720 | /* ----------------------------------------------------------- */ |
@@ -1890,6 +1749,7 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, | |||
1890 | { | 1749 | { |
1891 | struct cx8800_dev *dev; | 1750 | struct cx8800_dev *dev; |
1892 | struct cx88_core *core; | 1751 | struct cx88_core *core; |
1752 | |||
1893 | int err; | 1753 | int err; |
1894 | 1754 | ||
1895 | dev = kzalloc(sizeof(*dev),GFP_KERNEL); | 1755 | dev = kzalloc(sizeof(*dev),GFP_KERNEL); |
@@ -1924,9 +1784,15 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, | |||
1924 | goto fail_core; | 1784 | goto fail_core; |
1925 | } | 1785 | } |
1926 | 1786 | ||
1787 | /* Initialize VBI template */ | ||
1788 | memcpy( &cx8800_vbi_template, &cx8800_video_template, | ||
1789 | sizeof(cx8800_vbi_template) ); | ||
1790 | strcpy(cx8800_vbi_template.name,"cx8800-vbi"); | ||
1791 | cx8800_vbi_template.type = VID_TYPE_TELETEXT|VID_TYPE_TUNER; | ||
1792 | |||
1927 | /* initialize driver struct */ | 1793 | /* initialize driver struct */ |
1928 | spin_lock_init(&dev->slock); | 1794 | spin_lock_init(&dev->slock); |
1929 | core->tvnorm = tvnorms; | 1795 | core->tvnorm = cx8800_video_template.current_norm; |
1930 | 1796 | ||
1931 | /* init video dma queues */ | 1797 | /* init video dma queues */ |
1932 | INIT_LIST_HEAD(&dev->vidq.active); | 1798 | INIT_LIST_HEAD(&dev->vidq.active); |
@@ -2007,9 +1873,9 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, | |||
2007 | 1873 | ||
2008 | /* initial device configuration */ | 1874 | /* initial device configuration */ |
2009 | mutex_lock(&core->lock); | 1875 | mutex_lock(&core->lock); |
2010 | cx88_set_tvnorm(core,tvnorms); | 1876 | cx88_set_tvnorm(core,core->tvnorm); |
2011 | init_controls(core); | 1877 | init_controls(core); |
2012 | video_mux(core,0); | 1878 | cx88_video_mux(core,0); |
2013 | mutex_unlock(&core->lock); | 1879 | mutex_unlock(&core->lock); |
2014 | 1880 | ||
2015 | /* start tvaudio thread */ | 1881 | /* start tvaudio thread */ |
@@ -2178,8 +2044,6 @@ static void cx8800_fini(void) | |||
2178 | module_init(cx8800_init); | 2044 | module_init(cx8800_init); |
2179 | module_exit(cx8800_fini); | 2045 | module_exit(cx8800_fini); |
2180 | 2046 | ||
2181 | EXPORT_SYMBOL(cx88_do_ioctl); | ||
2182 | |||
2183 | /* ----------------------------------------------------------- */ | 2047 | /* ----------------------------------------------------------- */ |
2184 | /* | 2048 | /* |
2185 | * Local variables: | 2049 | * Local variables: |
diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index a9575ad8ca27..d2ecfba9bb4d 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h | |||
@@ -31,7 +31,9 @@ | |||
31 | #include <media/video-buf.h> | 31 | #include <media/video-buf.h> |
32 | #include <media/cx2341x.h> | 32 | #include <media/cx2341x.h> |
33 | #include <media/audiochip.h> | 33 | #include <media/audiochip.h> |
34 | #if defined(CONFIG_VIDEO_BUF_DVB) || defined(CONFIG_VIDEO_BUF_DVB_MODULE) | ||
34 | #include <media/video-buf-dvb.h> | 35 | #include <media/video-buf-dvb.h> |
36 | #endif | ||
35 | 37 | ||
36 | #include "btcx-risc.h" | 38 | #include "btcx-risc.h" |
37 | #include "cx88-reg.h" | 39 | #include "cx88-reg.h" |
@@ -50,6 +52,13 @@ | |||
50 | /* ----------------------------------------------------------- */ | 52 | /* ----------------------------------------------------------- */ |
51 | /* defines and enums */ | 53 | /* defines and enums */ |
52 | 54 | ||
55 | /* Currently unsupported by the driver: PAL/H, NTSC/Kr, SECAM B/G/H/LC */ | ||
56 | #define CX88_NORMS (\ | ||
57 | V4L2_STD_NTSC_M| V4L2_STD_NTSC_M_JP| V4L2_STD_NTSC_443 | \ | ||
58 | V4L2_STD_PAL_BG| V4L2_STD_PAL_DK | V4L2_STD_PAL_I | \ | ||
59 | V4L2_STD_PAL_M | V4L2_STD_PAL_N | V4L2_STD_PAL_Nc | \ | ||
60 | V4L2_STD_PAL_60| V4L2_STD_SECAM_L | V4L2_STD_SECAM_DK ) | ||
61 | |||
53 | #define FORMAT_FLAGS_PACKED 0x01 | 62 | #define FORMAT_FLAGS_PACKED 0x01 |
54 | #define FORMAT_FLAGS_PLANAR 0x02 | 63 | #define FORMAT_FLAGS_PLANAR 0x02 |
55 | 64 | ||
@@ -82,22 +91,15 @@ enum cx8802_board_access { | |||
82 | /* ----------------------------------------------------------- */ | 91 | /* ----------------------------------------------------------- */ |
83 | /* tv norms */ | 92 | /* tv norms */ |
84 | 93 | ||
85 | struct cx88_tvnorm { | 94 | static unsigned int inline norm_maxw(v4l2_std_id norm) |
86 | char *name; | ||
87 | v4l2_std_id id; | ||
88 | u32 cxiformat; | ||
89 | u32 cxoformat; | ||
90 | }; | ||
91 | |||
92 | static unsigned int inline norm_maxw(struct cx88_tvnorm *norm) | ||
93 | { | 95 | { |
94 | return (norm->id & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 720 : 768; | 96 | return (norm & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 720 : 768; |
95 | } | 97 | } |
96 | 98 | ||
97 | 99 | ||
98 | static unsigned int inline norm_maxh(struct cx88_tvnorm *norm) | 100 | static unsigned int inline norm_maxh(v4l2_std_id norm) |
99 | { | 101 | { |
100 | return (norm->id & V4L2_STD_625_50) ? 576 : 480; | 102 | return (norm & V4L2_STD_625_50) ? 576 : 480; |
101 | } | 103 | } |
102 | 104 | ||
103 | /* ----------------------------------------------------------- */ | 105 | /* ----------------------------------------------------------- */ |
@@ -313,13 +315,15 @@ struct cx88_core { | |||
313 | unsigned int tuner_formats; | 315 | unsigned int tuner_formats; |
314 | 316 | ||
315 | /* config info -- dvb */ | 317 | /* config info -- dvb */ |
318 | #if defined(CONFIG_VIDEO_BUF_DVB) || defined(CONFIG_VIDEO_BUF_DVB_MODULE) | ||
316 | struct dvb_pll_desc *pll_desc; | 319 | struct dvb_pll_desc *pll_desc; |
317 | unsigned int pll_addr; | 320 | unsigned int pll_addr; |
318 | int (*prev_set_voltage)(struct dvb_frontend* fe, fe_sec_voltage_t voltage); | 321 | int (*prev_set_voltage)(struct dvb_frontend* fe, fe_sec_voltage_t voltage); |
322 | #endif | ||
319 | 323 | ||
320 | /* state info */ | 324 | /* state info */ |
321 | struct task_struct *kthread; | 325 | struct task_struct *kthread; |
322 | struct cx88_tvnorm *tvnorm; | 326 | v4l2_std_id tvnorm; |
323 | u32 tvaudio; | 327 | u32 tvaudio; |
324 | u32 audiomode_manual; | 328 | u32 audiomode_manual; |
325 | u32 audiomode_current; | 329 | u32 audiomode_current; |
@@ -460,12 +464,14 @@ struct cx8802_dev { | |||
460 | int width; | 464 | int width; |
461 | int height; | 465 | int height; |
462 | 466 | ||
467 | #if defined(CONFIG_VIDEO_BUF_DVB) || defined(CONFIG_VIDEO_BUF_DVB_MODULE) | ||
463 | /* for dvb only */ | 468 | /* for dvb only */ |
464 | struct videobuf_dvb dvb; | 469 | struct videobuf_dvb dvb; |
465 | void* fe_handle; | 470 | void* fe_handle; |
466 | int (*fe_release)(void *handle); | 471 | int (*fe_release)(void *handle); |
467 | 472 | ||
468 | void *card_priv; | 473 | void *card_priv; |
474 | #endif | ||
469 | /* for switching modulation types */ | 475 | /* for switching modulation types */ |
470 | unsigned char ts_gen_cntrl; | 476 | unsigned char ts_gen_cntrl; |
471 | 477 | ||
@@ -536,7 +542,7 @@ extern void cx88_sram_channel_dump(struct cx88_core *core, | |||
536 | 542 | ||
537 | extern int cx88_set_scale(struct cx88_core *core, unsigned int width, | 543 | extern int cx88_set_scale(struct cx88_core *core, unsigned int width, |
538 | unsigned int height, enum v4l2_field field); | 544 | unsigned int height, enum v4l2_field field); |
539 | extern int cx88_set_tvnorm(struct cx88_core *core, struct cx88_tvnorm *norm); | 545 | extern int cx88_set_tvnorm(struct cx88_core *core, v4l2_std_id norm); |
540 | 546 | ||
541 | extern struct video_device *cx88_vdev_init(struct cx88_core *core, | 547 | extern struct video_device *cx88_vdev_init(struct cx88_core *core, |
542 | struct pci_dev *pci, | 548 | struct pci_dev *pci, |
@@ -553,7 +559,10 @@ extern int cx88_stop_audio_dma(struct cx88_core *core); | |||
553 | /* ----------------------------------------------------------- */ | 559 | /* ----------------------------------------------------------- */ |
554 | /* cx88-vbi.c */ | 560 | /* cx88-vbi.c */ |
555 | 561 | ||
556 | void cx8800_vbi_fmt(struct cx8800_dev *dev, struct v4l2_format *f); | 562 | /* Can be used as g_vbi_fmt, try_vbi_fmt and s_vbi_fmt */ |
563 | int cx8800_vbi_fmt (struct file *file, void *priv, | ||
564 | struct v4l2_format *f); | ||
565 | |||
557 | /* | 566 | /* |
558 | int cx8800_start_vbi_dma(struct cx8800_dev *dev, | 567 | int cx8800_start_vbi_dma(struct cx8800_dev *dev, |
559 | struct cx88_dmaqueue *q, | 568 | struct cx88_dmaqueue *q, |
@@ -633,19 +642,14 @@ int cx8802_suspend_common(struct pci_dev *pci_dev, pm_message_t state); | |||
633 | int cx8802_resume_common(struct pci_dev *pci_dev); | 642 | int cx8802_resume_common(struct pci_dev *pci_dev); |
634 | 643 | ||
635 | /* ----------------------------------------------------------- */ | 644 | /* ----------------------------------------------------------- */ |
636 | /* cx88-video.c */ | 645 | /* cx88-video.c*/ |
637 | extern int cx88_do_ioctl(struct inode *inode, struct file *file, int radio, | ||
638 | struct cx88_core *core, unsigned int cmd, | ||
639 | void *arg, v4l2_kioctl driver_ioctl); | ||
640 | extern const u32 cx88_user_ctrls[]; | 646 | extern const u32 cx88_user_ctrls[]; |
641 | extern int cx8800_ctrl_query(struct v4l2_queryctrl *qctrl); | 647 | extern int cx8800_ctrl_query(struct v4l2_queryctrl *qctrl); |
642 | 648 | int cx88_enum_input (struct cx88_core *core,struct v4l2_input *i); | |
643 | /* ----------------------------------------------------------- */ | 649 | int cx88_set_freq (struct cx88_core *core,struct v4l2_frequency *f); |
644 | /* cx88-blackbird.c */ | 650 | int cx88_get_control(struct cx88_core *core, struct v4l2_control *ctl); |
645 | /* used by cx88-ivtv ioctl emulation layer */ | 651 | int cx88_set_control(struct cx88_core *core, struct v4l2_control *ctl); |
646 | extern int (*cx88_ioctl_hook)(struct inode *inode, struct file *file, | 652 | int cx88_video_mux(struct cx88_core *core, unsigned int input); |
647 | unsigned int cmd, void *arg); | ||
648 | extern unsigned int (*cx88_ioctl_translator)(unsigned int cmd); | ||
649 | 653 | ||
650 | /* | 654 | /* |
651 | * Local variables: | 655 | * Local variables: |
diff --git a/drivers/media/video/et61x251/et61x251.h b/drivers/media/video/et61x251/et61x251.h index 2e5ca4032489..262f98e12409 100644 --- a/drivers/media/video/et61x251/et61x251.h +++ b/drivers/media/video/et61x251/et61x251.h | |||
@@ -171,10 +171,7 @@ struct et61x251_device { | |||
171 | struct et61x251_device* | 171 | struct et61x251_device* |
172 | et61x251_match_id(struct et61x251_device* cam, const struct usb_device_id *id) | 172 | et61x251_match_id(struct et61x251_device* cam, const struct usb_device_id *id) |
173 | { | 173 | { |
174 | if (usb_match_id(usb_ifnum_to_if(cam->usbdev, 0), id)) | 174 | return usb_match_id(usb_ifnum_to_if(cam->usbdev, 0), id) ? cam : NULL; |
175 | return cam; | ||
176 | |||
177 | return NULL; | ||
178 | } | 175 | } |
179 | 176 | ||
180 | 177 | ||
diff --git a/drivers/media/video/et61x251/et61x251_core.c b/drivers/media/video/et61x251/et61x251_core.c index 49792ae8c61c..a6525513cd1e 100644 --- a/drivers/media/video/et61x251/et61x251_core.c +++ b/drivers/media/video/et61x251/et61x251_core.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /*************************************************************************** | 1 | /*************************************************************************** |
2 | * V4L2 driver for ET61X[12]51 PC Camera Controllers * | 2 | * V4L2 driver for ET61X[12]51 PC Camera Controllers * |
3 | * * | 3 | * * |
4 | * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it> * | 4 | * Copyright (C) 2006-2007 by Luca Risolia <luca.risolia@studio.unibo.it> * |
5 | * * | 5 | * * |
6 | * This program is free software; you can redistribute it and/or modify * | 6 | * This program is free software; you can redistribute it and/or modify * |
7 | * it under the terms of the GNU General Public License as published by * | 7 | * it under the terms of the GNU General Public License as published by * |
@@ -48,8 +48,8 @@ | |||
48 | #define ET61X251_MODULE_AUTHOR "(C) 2006 Luca Risolia" | 48 | #define ET61X251_MODULE_AUTHOR "(C) 2006 Luca Risolia" |
49 | #define ET61X251_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>" | 49 | #define ET61X251_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>" |
50 | #define ET61X251_MODULE_LICENSE "GPL" | 50 | #define ET61X251_MODULE_LICENSE "GPL" |
51 | #define ET61X251_MODULE_VERSION "1:1.02" | 51 | #define ET61X251_MODULE_VERSION "1:1.04" |
52 | #define ET61X251_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 2) | 52 | #define ET61X251_MODULE_VERSION_CODE KERNEL_VERSION(1, 1, 4) |
53 | 53 | ||
54 | /*****************************************************************************/ | 54 | /*****************************************************************************/ |
55 | 55 | ||
@@ -85,7 +85,7 @@ MODULE_PARM_DESC(force_munmap, | |||
85 | "\ndetected camera." | 85 | "\ndetected camera." |
86 | "\n 0 = do not force memory unmapping" | 86 | "\n 0 = do not force memory unmapping" |
87 | "\n 1 = force memory unmapping (save memory)" | 87 | "\n 1 = force memory unmapping (save memory)" |
88 | "\nDefault value is "__MODULE_STRING(SN9C102_FORCE_MUNMAP)"." | 88 | "\nDefault value is "__MODULE_STRING(ET61X251_FORCE_MUNMAP)"." |
89 | "\n"); | 89 | "\n"); |
90 | 90 | ||
91 | static unsigned int frame_timeout[] = {[0 ... ET61X251_MAX_DEVICES-1] = | 91 | static unsigned int frame_timeout[] = {[0 ... ET61X251_MAX_DEVICES-1] = |
@@ -133,7 +133,8 @@ et61x251_request_buffers(struct et61x251_device* cam, u32 count, | |||
133 | 133 | ||
134 | cam->nbuffers = count; | 134 | cam->nbuffers = count; |
135 | while (cam->nbuffers > 0) { | 135 | while (cam->nbuffers > 0) { |
136 | if ((buff = vmalloc_32(cam->nbuffers * PAGE_ALIGN(imagesize)))) | 136 | if ((buff = vmalloc_32_user(cam->nbuffers * |
137 | PAGE_ALIGN(imagesize)))) | ||
137 | break; | 138 | break; |
138 | cam->nbuffers--; | 139 | cam->nbuffers--; |
139 | } | 140 | } |
@@ -543,10 +544,11 @@ static int et61x251_start_transfer(struct et61x251_device* cam) | |||
543 | { | 544 | { |
544 | struct usb_device *udev = cam->usbdev; | 545 | struct usb_device *udev = cam->usbdev; |
545 | struct urb* urb; | 546 | struct urb* urb; |
546 | const unsigned int wMaxPacketSize[] = {0, 256, 384, 512, 640, 768, 832, | 547 | struct usb_host_interface* altsetting = usb_altnum_to_altsetting( |
547 | 864, 896, 920, 956, 980, 1000, | 548 | usb_ifnum_to_if(udev, 0), |
548 | 1022}; | 549 | ET61X251_ALTERNATE_SETTING); |
549 | const unsigned int psz = wMaxPacketSize[ET61X251_ALTERNATE_SETTING]; | 550 | const unsigned int psz = le16_to_cpu(altsetting-> |
551 | endpoint[0].desc.wMaxPacketSize); | ||
550 | s8 i, j; | 552 | s8 i, j; |
551 | int err = 0; | 553 | int err = 0; |
552 | 554 | ||
@@ -976,29 +978,31 @@ static CLASS_DEVICE_ATTR(i2c_val, S_IRUGO | S_IWUSR, | |||
976 | static int et61x251_create_sysfs(struct et61x251_device* cam) | 978 | static int et61x251_create_sysfs(struct et61x251_device* cam) |
977 | { | 979 | { |
978 | struct video_device *v4ldev = cam->v4ldev; | 980 | struct video_device *v4ldev = cam->v4ldev; |
979 | int rc; | 981 | int err = 0; |
982 | |||
983 | if ((err = video_device_create_file(v4ldev, &class_device_attr_reg))) | ||
984 | goto err_out; | ||
985 | if ((err = video_device_create_file(v4ldev, &class_device_attr_val))) | ||
986 | goto err_reg; | ||
980 | 987 | ||
981 | rc = video_device_create_file(v4ldev, &class_device_attr_reg); | ||
982 | if (rc) goto err; | ||
983 | rc = video_device_create_file(v4ldev, &class_device_attr_val); | ||
984 | if (rc) goto err_reg; | ||
985 | if (cam->sensor.sysfs_ops) { | 988 | if (cam->sensor.sysfs_ops) { |
986 | rc = video_device_create_file(v4ldev, &class_device_attr_i2c_reg); | 989 | if ((err = video_device_create_file(v4ldev, |
987 | if (rc) goto err_val; | 990 | &class_device_attr_i2c_reg))) |
988 | rc = video_device_create_file(v4ldev, &class_device_attr_i2c_val); | 991 | goto err_val; |
989 | if (rc) goto err_i2c_reg; | 992 | if ((err = video_device_create_file(v4ldev, |
993 | &class_device_attr_i2c_val))) | ||
994 | goto err_i2c_reg; | ||
990 | } | 995 | } |
991 | 996 | ||
992 | return 0; | ||
993 | |||
994 | err_i2c_reg: | 997 | err_i2c_reg: |
998 | if (cam->sensor.sysfs_ops) | ||
995 | video_device_remove_file(v4ldev, &class_device_attr_i2c_reg); | 999 | video_device_remove_file(v4ldev, &class_device_attr_i2c_reg); |
996 | err_val: | 1000 | err_val: |
997 | video_device_remove_file(v4ldev, &class_device_attr_val); | 1001 | video_device_remove_file(v4ldev, &class_device_attr_val); |
998 | err_reg: | 1002 | err_reg: |
999 | video_device_remove_file(v4ldev, &class_device_attr_reg); | 1003 | video_device_remove_file(v4ldev, &class_device_attr_reg); |
1000 | err: | 1004 | err_out: |
1001 | return rc; | 1005 | return err; |
1002 | } | 1006 | } |
1003 | #endif /* CONFIG_VIDEO_ADV_DEBUG */ | 1007 | #endif /* CONFIG_VIDEO_ADV_DEBUG */ |
1004 | 1008 | ||
@@ -1767,10 +1771,10 @@ et61x251_vidioc_s_crop(struct et61x251_device* cam, void __user * arg) | |||
1767 | rect->left = (s->_rect.left & 1L) ? rect->left | 1L : rect->left & ~1L; | 1771 | rect->left = (s->_rect.left & 1L) ? rect->left | 1L : rect->left & ~1L; |
1768 | rect->top = (s->_rect.top & 1L) ? rect->top | 1L : rect->top & ~1L; | 1772 | rect->top = (s->_rect.top & 1L) ? rect->top | 1L : rect->top & ~1L; |
1769 | 1773 | ||
1770 | if (rect->width < 4) | 1774 | if (rect->width < 16) |
1771 | rect->width = 4; | 1775 | rect->width = 16; |
1772 | if (rect->height < 4) | 1776 | if (rect->height < 16) |
1773 | rect->height = 4; | 1777 | rect->height = 16; |
1774 | if (rect->width > bounds->width) | 1778 | if (rect->width > bounds->width) |
1775 | rect->width = bounds->width; | 1779 | rect->width = bounds->width; |
1776 | if (rect->height > bounds->height) | 1780 | if (rect->height > bounds->height) |
@@ -1784,8 +1788,8 @@ et61x251_vidioc_s_crop(struct et61x251_device* cam, void __user * arg) | |||
1784 | if (rect->top + rect->height > bounds->top + bounds->height) | 1788 | if (rect->top + rect->height > bounds->top + bounds->height) |
1785 | rect->top = bounds->top+bounds->height - rect->height; | 1789 | rect->top = bounds->top+bounds->height - rect->height; |
1786 | 1790 | ||
1787 | rect->width &= ~3L; | 1791 | rect->width &= ~15L; |
1788 | rect->height &= ~3L; | 1792 | rect->height &= ~15L; |
1789 | 1793 | ||
1790 | if (ET61X251_PRESERVE_IMGSCALE) { | 1794 | if (ET61X251_PRESERVE_IMGSCALE) { |
1791 | /* Calculate the actual scaling factor */ | 1795 | /* Calculate the actual scaling factor */ |
@@ -1846,6 +1850,35 @@ et61x251_vidioc_s_crop(struct et61x251_device* cam, void __user * arg) | |||
1846 | 1850 | ||
1847 | 1851 | ||
1848 | static int | 1852 | static int |
1853 | et61x251_vidioc_enum_framesizes(struct et61x251_device* cam, void __user * arg) | ||
1854 | { | ||
1855 | struct v4l2_frmsizeenum frmsize; | ||
1856 | |||
1857 | if (copy_from_user(&frmsize, arg, sizeof(frmsize))) | ||
1858 | return -EFAULT; | ||
1859 | |||
1860 | if (frmsize.index != 0) | ||
1861 | return -EINVAL; | ||
1862 | |||
1863 | if (frmsize.pixel_format != V4L2_PIX_FMT_ET61X251 && | ||
1864 | frmsize.pixel_format != V4L2_PIX_FMT_SBGGR8) | ||
1865 | return -EINVAL; | ||
1866 | |||
1867 | frmsize.type = V4L2_FRMSIZE_TYPE_STEPWISE; | ||
1868 | frmsize.stepwise.min_width = frmsize.stepwise.step_width = 16; | ||
1869 | frmsize.stepwise.min_height = frmsize.stepwise.step_height = 16; | ||
1870 | frmsize.stepwise.max_width = cam->sensor.cropcap.bounds.width; | ||
1871 | frmsize.stepwise.max_height = cam->sensor.cropcap.bounds.height; | ||
1872 | memset(&frmsize.reserved, 0, sizeof(frmsize.reserved)); | ||
1873 | |||
1874 | if (copy_to_user(arg, &frmsize, sizeof(frmsize))) | ||
1875 | return -EFAULT; | ||
1876 | |||
1877 | return 0; | ||
1878 | } | ||
1879 | |||
1880 | |||
1881 | static int | ||
1849 | et61x251_vidioc_enum_fmt(struct et61x251_device* cam, void __user * arg) | 1882 | et61x251_vidioc_enum_fmt(struct et61x251_device* cam, void __user * arg) |
1850 | { | 1883 | { |
1851 | struct v4l2_fmtdesc fmtd; | 1884 | struct v4l2_fmtdesc fmtd; |
@@ -1853,6 +1886,9 @@ et61x251_vidioc_enum_fmt(struct et61x251_device* cam, void __user * arg) | |||
1853 | if (copy_from_user(&fmtd, arg, sizeof(fmtd))) | 1886 | if (copy_from_user(&fmtd, arg, sizeof(fmtd))) |
1854 | return -EFAULT; | 1887 | return -EFAULT; |
1855 | 1888 | ||
1889 | if (fmtd.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
1890 | return -EINVAL; | ||
1891 | |||
1856 | if (fmtd.index == 0) { | 1892 | if (fmtd.index == 0) { |
1857 | strcpy(fmtd.description, "bayer rgb"); | 1893 | strcpy(fmtd.description, "bayer rgb"); |
1858 | fmtd.pixelformat = V4L2_PIX_FMT_SBGGR8; | 1894 | fmtd.pixelformat = V4L2_PIX_FMT_SBGGR8; |
@@ -1934,17 +1970,17 @@ et61x251_vidioc_try_s_fmt(struct et61x251_device* cam, unsigned int cmd, | |||
1934 | rect.width = scale * pix->width; | 1970 | rect.width = scale * pix->width; |
1935 | rect.height = scale * pix->height; | 1971 | rect.height = scale * pix->height; |
1936 | 1972 | ||
1937 | if (rect.width < 4) | 1973 | if (rect.width < 16) |
1938 | rect.width = 4; | 1974 | rect.width = 16; |
1939 | if (rect.height < 4) | 1975 | if (rect.height < 16) |
1940 | rect.height = 4; | 1976 | rect.height = 16; |
1941 | if (rect.width > bounds->left + bounds->width - rect.left) | 1977 | if (rect.width > bounds->left + bounds->width - rect.left) |
1942 | rect.width = bounds->left + bounds->width - rect.left; | 1978 | rect.width = bounds->left + bounds->width - rect.left; |
1943 | if (rect.height > bounds->top + bounds->height - rect.top) | 1979 | if (rect.height > bounds->top + bounds->height - rect.top) |
1944 | rect.height = bounds->top + bounds->height - rect.top; | 1980 | rect.height = bounds->top + bounds->height - rect.top; |
1945 | 1981 | ||
1946 | rect.width &= ~3L; | 1982 | rect.width &= ~15L; |
1947 | rect.height &= ~3L; | 1983 | rect.height &= ~15L; |
1948 | 1984 | ||
1949 | { /* adjust the scaling factor */ | 1985 | { /* adjust the scaling factor */ |
1950 | u32 a, b; | 1986 | u32 a, b; |
@@ -2378,6 +2414,9 @@ static int et61x251_ioctl_v4l2(struct inode* inode, struct file* filp, | |||
2378 | case VIDIOC_S_FMT: | 2414 | case VIDIOC_S_FMT: |
2379 | return et61x251_vidioc_try_s_fmt(cam, cmd, arg); | 2415 | return et61x251_vidioc_try_s_fmt(cam, cmd, arg); |
2380 | 2416 | ||
2417 | case VIDIOC_ENUM_FRAMESIZES: | ||
2418 | return et61x251_vidioc_enum_framesizes(cam, arg); | ||
2419 | |||
2381 | case VIDIOC_G_JPEGCOMP: | 2420 | case VIDIOC_G_JPEGCOMP: |
2382 | return et61x251_vidioc_g_jpegcomp(cam, arg); | 2421 | return et61x251_vidioc_g_jpegcomp(cam, arg); |
2383 | 2422 | ||
@@ -2413,6 +2452,7 @@ static int et61x251_ioctl_v4l2(struct inode* inode, struct file* filp, | |||
2413 | case VIDIOC_QUERYSTD: | 2452 | case VIDIOC_QUERYSTD: |
2414 | case VIDIOC_ENUMSTD: | 2453 | case VIDIOC_ENUMSTD: |
2415 | case VIDIOC_QUERYMENU: | 2454 | case VIDIOC_QUERYMENU: |
2455 | case VIDIOC_ENUM_FRAMEINTERVALS: | ||
2416 | return -EINVAL; | 2456 | return -EINVAL; |
2417 | 2457 | ||
2418 | default: | 2458 | default: |
@@ -2459,6 +2499,7 @@ static const struct file_operations et61x251_fops = { | |||
2459 | .open = et61x251_open, | 2499 | .open = et61x251_open, |
2460 | .release = et61x251_release, | 2500 | .release = et61x251_release, |
2461 | .ioctl = et61x251_ioctl, | 2501 | .ioctl = et61x251_ioctl, |
2502 | .compat_ioctl = v4l_compat_ioctl32, | ||
2462 | .read = et61x251_read, | 2503 | .read = et61x251_read, |
2463 | .poll = et61x251_poll, | 2504 | .poll = et61x251_poll, |
2464 | .mmap = et61x251_mmap, | 2505 | .mmap = et61x251_mmap, |
@@ -2497,7 +2538,7 @@ et61x251_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) | |||
2497 | mutex_init(&cam->dev_mutex); | 2538 | mutex_init(&cam->dev_mutex); |
2498 | 2539 | ||
2499 | DBG(2, "ET61X[12]51 PC Camera Controller detected " | 2540 | DBG(2, "ET61X[12]51 PC Camera Controller detected " |
2500 | "(vid/pid 0x%04X/0x%04X)",id->idVendor, id->idProduct); | 2541 | "(vid/pid 0x%04X:0x%04X)",id->idVendor, id->idProduct); |
2501 | 2542 | ||
2502 | for (i = 0; et61x251_sensor_table[i]; i++) { | 2543 | for (i = 0; et61x251_sensor_table[i]; i++) { |
2503 | err = et61x251_sensor_table[i](cam); | 2544 | err = et61x251_sensor_table[i](cam); |
@@ -2550,9 +2591,14 @@ et61x251_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) | |||
2550 | 2591 | ||
2551 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 2592 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
2552 | err = et61x251_create_sysfs(cam); | 2593 | err = et61x251_create_sysfs(cam); |
2553 | if (err) | 2594 | if (!err) |
2554 | goto fail2; | 2595 | DBG(2, "Optional device control through 'sysfs' " |
2555 | DBG(2, "Optional device control through 'sysfs' interface ready"); | 2596 | "interface ready"); |
2597 | else | ||
2598 | DBG(2, "Failed to create 'sysfs' interface for optional " | ||
2599 | "device controlling. Error #%d", err); | ||
2600 | #else | ||
2601 | DBG(2, "Optional device control through 'sysfs' interface disabled"); | ||
2556 | #endif | 2602 | #endif |
2557 | 2603 | ||
2558 | usb_set_intfdata(intf, cam); | 2604 | usb_set_intfdata(intf, cam); |
@@ -2561,13 +2607,6 @@ et61x251_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) | |||
2561 | 2607 | ||
2562 | return 0; | 2608 | return 0; |
2563 | 2609 | ||
2564 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
2565 | fail2: | ||
2566 | video_nr[dev_nr] = -1; | ||
2567 | dev_nr = (dev_nr < ET61X251_MAX_DEVICES-1) ? dev_nr+1 : 0; | ||
2568 | mutex_unlock(&cam->dev_mutex); | ||
2569 | video_unregister_device(cam->v4ldev); | ||
2570 | #endif | ||
2571 | fail: | 2610 | fail: |
2572 | if (cam) { | 2611 | if (cam) { |
2573 | kfree(cam->control_buffer); | 2612 | kfree(cam->control_buffer); |
diff --git a/drivers/media/video/et61x251/et61x251_sensor.h b/drivers/media/video/et61x251/et61x251_sensor.h index 65edd08dc386..5fadb5de68bf 100644 --- a/drivers/media/video/et61x251/et61x251_sensor.h +++ b/drivers/media/video/et61x251/et61x251_sensor.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /*************************************************************************** | 1 | /*************************************************************************** |
2 | * API for image sensors connected to ET61X[12]51 PC Camera Controllers * | 2 | * API for image sensors connected to ET61X[12]51 PC Camera Controllers * |
3 | * * | 3 | * * |
4 | * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it> * | 4 | * Copyright (C) 2006-2007 by Luca Risolia <luca.risolia@studio.unibo.it> * |
5 | * * | 5 | * * |
6 | * This program is free software; you can redistribute it and/or modify * | 6 | * This program is free software; you can redistribute it and/or modify * |
7 | * it under the terms of the GNU General Public License as published by * | 7 | * it under the terms of the GNU General Public License as published by * |
@@ -82,7 +82,7 @@ enum et61x251_i2c_rsta { | |||
82 | ET61X251_I2C_RSTA_REPEAT = 0x01, /* repeat start */ | 82 | ET61X251_I2C_RSTA_REPEAT = 0x01, /* repeat start */ |
83 | }; | 83 | }; |
84 | 84 | ||
85 | #define ET61X251_MAX_CTRLS V4L2_CID_LASTP1-V4L2_CID_BASE+10 | 85 | #define ET61X251_MAX_CTRLS (V4L2_CID_LASTP1-V4L2_CID_BASE+10) |
86 | 86 | ||
87 | struct et61x251_sensor { | 87 | struct et61x251_sensor { |
88 | char name[32]; | 88 | char name[32]; |
diff --git a/drivers/media/video/et61x251/et61x251_tas5130d1b.c b/drivers/media/video/et61x251/et61x251_tas5130d1b.c index a7d65b82b2fb..b06643409842 100644 --- a/drivers/media/video/et61x251/et61x251_tas5130d1b.c +++ b/drivers/media/video/et61x251/et61x251_tas5130d1b.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * Plug-in for TAS5130D1B image sensor connected to the ET61X[12]51 * | 2 | * Plug-in for TAS5130D1B image sensor connected to the ET61X[12]51 * |
3 | * PC Camera Controllers * | 3 | * PC Camera Controllers * |
4 | * * | 4 | * * |
5 | * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it> * | 5 | * Copyright (C) 2006-2007 by Luca Risolia <luca.risolia@studio.unibo.it> * |
6 | * * | 6 | * * |
7 | * This program is free software; you can redistribute it and/or modify * | 7 | * This program is free software; you can redistribute it and/or modify * |
8 | * it under the terms of the GNU General Public License as published by * | 8 | * it under the terms of the GNU General Public License as published by * |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-audio.c b/drivers/media/video/pvrusb2/pvrusb2-audio.c index 122496f36845..379645e481c6 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-audio.c +++ b/drivers/media/video/pvrusb2/pvrusb2-audio.c | |||
@@ -31,7 +31,6 @@ struct pvr2_msp3400_handler { | |||
31 | struct pvr2_hdw *hdw; | 31 | struct pvr2_hdw *hdw; |
32 | struct pvr2_i2c_client *client; | 32 | struct pvr2_i2c_client *client; |
33 | struct pvr2_i2c_handler i2c_handler; | 33 | struct pvr2_i2c_handler i2c_handler; |
34 | struct pvr2_audio_stat astat; | ||
35 | unsigned long stale_mask; | 34 | unsigned long stale_mask; |
36 | }; | 35 | }; |
37 | 36 | ||
@@ -44,13 +43,6 @@ static void set_stereo(struct pvr2_msp3400_handler *ctxt) | |||
44 | 43 | ||
45 | pvr2_trace(PVR2_TRACE_CHIPS,"i2c msp3400 v4l2 set_stereo"); | 44 | pvr2_trace(PVR2_TRACE_CHIPS,"i2c msp3400 v4l2 set_stereo"); |
46 | 45 | ||
47 | if (hdw->input_val == PVR2_CVAL_INPUT_TV) { | ||
48 | struct v4l2_tuner vt; | ||
49 | memset(&vt,0,sizeof(vt)); | ||
50 | vt.audmode = hdw->audiomode_val; | ||
51 | pvr2_i2c_client_cmd(ctxt->client,VIDIOC_S_TUNER,&vt); | ||
52 | } | ||
53 | |||
54 | route.input = MSP_INPUT_DEFAULT; | 46 | route.input = MSP_INPUT_DEFAULT; |
55 | route.output = MSP_OUTPUT(MSP_SC_IN_DSP_SCART1); | 47 | route.output = MSP_OUTPUT(MSP_SC_IN_DSP_SCART1); |
56 | switch (hdw->input_val) { | 48 | switch (hdw->input_val) { |
@@ -78,8 +70,7 @@ static void set_stereo(struct pvr2_msp3400_handler *ctxt) | |||
78 | static int check_stereo(struct pvr2_msp3400_handler *ctxt) | 70 | static int check_stereo(struct pvr2_msp3400_handler *ctxt) |
79 | { | 71 | { |
80 | struct pvr2_hdw *hdw = ctxt->hdw; | 72 | struct pvr2_hdw *hdw = ctxt->hdw; |
81 | return (hdw->input_dirty || | 73 | return hdw->input_dirty; |
82 | hdw->audiomode_dirty); | ||
83 | } | 74 | } |
84 | 75 | ||
85 | 76 | ||
@@ -99,8 +90,7 @@ static int msp3400_check(struct pvr2_msp3400_handler *ctxt) | |||
99 | unsigned long msk; | 90 | unsigned long msk; |
100 | unsigned int idx; | 91 | unsigned int idx; |
101 | 92 | ||
102 | for (idx = 0; idx < sizeof(msp3400_ops)/sizeof(msp3400_ops[0]); | 93 | for (idx = 0; idx < ARRAY_SIZE(msp3400_ops); idx++) { |
103 | idx++) { | ||
104 | msk = 1 << idx; | 94 | msk = 1 << idx; |
105 | if (ctxt->stale_mask & msk) continue; | 95 | if (ctxt->stale_mask & msk) continue; |
106 | if (msp3400_ops[idx].check(ctxt)) { | 96 | if (msp3400_ops[idx].check(ctxt)) { |
@@ -116,8 +106,7 @@ static void msp3400_update(struct pvr2_msp3400_handler *ctxt) | |||
116 | unsigned long msk; | 106 | unsigned long msk; |
117 | unsigned int idx; | 107 | unsigned int idx; |
118 | 108 | ||
119 | for (idx = 0; idx < sizeof(msp3400_ops)/sizeof(msp3400_ops[0]); | 109 | for (idx = 0; idx < ARRAY_SIZE(msp3400_ops); idx++) { |
120 | idx++) { | ||
121 | msk = 1 << idx; | 110 | msk = 1 << idx; |
122 | if (!(ctxt->stale_mask & msk)) continue; | 111 | if (!(ctxt->stale_mask & msk)) continue; |
123 | ctxt->stale_mask &= ~msk; | 112 | ctxt->stale_mask &= ~msk; |
@@ -126,27 +115,9 @@ static void msp3400_update(struct pvr2_msp3400_handler *ctxt) | |||
126 | } | 115 | } |
127 | 116 | ||
128 | 117 | ||
129 | /* This reads back the current signal type */ | ||
130 | static int get_audio_status(struct pvr2_msp3400_handler *ctxt) | ||
131 | { | ||
132 | struct v4l2_tuner vt; | ||
133 | int stat; | ||
134 | |||
135 | memset(&vt,0,sizeof(vt)); | ||
136 | stat = pvr2_i2c_client_cmd(ctxt->client,VIDIOC_G_TUNER,&vt); | ||
137 | if (stat < 0) return stat; | ||
138 | |||
139 | ctxt->hdw->flag_stereo = (vt.audmode & V4L2_TUNER_MODE_STEREO) != 0; | ||
140 | ctxt->hdw->flag_bilingual = | ||
141 | (vt.audmode & V4L2_TUNER_MODE_LANG2) != 0; | ||
142 | return 0; | ||
143 | } | ||
144 | |||
145 | |||
146 | static void pvr2_msp3400_detach(struct pvr2_msp3400_handler *ctxt) | 118 | static void pvr2_msp3400_detach(struct pvr2_msp3400_handler *ctxt) |
147 | { | 119 | { |
148 | ctxt->client->handler = NULL; | 120 | ctxt->client->handler = NULL; |
149 | ctxt->hdw->audio_stat = NULL; | ||
150 | kfree(ctxt); | 121 | kfree(ctxt); |
151 | } | 122 | } |
152 | 123 | ||
@@ -169,24 +140,17 @@ static const struct pvr2_i2c_handler_functions msp3400_funcs = { | |||
169 | int pvr2_i2c_msp3400_setup(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp) | 140 | int pvr2_i2c_msp3400_setup(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp) |
170 | { | 141 | { |
171 | struct pvr2_msp3400_handler *ctxt; | 142 | struct pvr2_msp3400_handler *ctxt; |
172 | if (hdw->audio_stat) return 0; | ||
173 | if (cp->handler) return 0; | 143 | if (cp->handler) return 0; |
174 | 144 | ||
175 | ctxt = kmalloc(sizeof(*ctxt),GFP_KERNEL); | 145 | ctxt = kzalloc(sizeof(*ctxt),GFP_KERNEL); |
176 | if (!ctxt) return 0; | 146 | if (!ctxt) return 0; |
177 | memset(ctxt,0,sizeof(*ctxt)); | ||
178 | 147 | ||
179 | ctxt->i2c_handler.func_data = ctxt; | 148 | ctxt->i2c_handler.func_data = ctxt; |
180 | ctxt->i2c_handler.func_table = &msp3400_funcs; | 149 | ctxt->i2c_handler.func_table = &msp3400_funcs; |
181 | ctxt->client = cp; | 150 | ctxt->client = cp; |
182 | ctxt->hdw = hdw; | 151 | ctxt->hdw = hdw; |
183 | ctxt->astat.ctxt = ctxt; | 152 | ctxt->stale_mask = (1 << ARRAY_SIZE(msp3400_ops)) - 1; |
184 | ctxt->astat.status = (int (*)(void *))get_audio_status; | ||
185 | ctxt->astat.detach = (void (*)(void *))pvr2_msp3400_detach; | ||
186 | ctxt->stale_mask = (1 << (sizeof(msp3400_ops)/ | ||
187 | sizeof(msp3400_ops[0]))) - 1; | ||
188 | cp->handler = &ctxt->i2c_handler; | 153 | cp->handler = &ctxt->i2c_handler; |
189 | hdw->audio_stat = &ctxt->astat; | ||
190 | pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x msp3400 V4L2 handler set up", | 154 | pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x msp3400 V4L2 handler set up", |
191 | cp->client->addr); | 155 | cp->client->addr); |
192 | return !0; | 156 | return !0; |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-context.c b/drivers/media/video/pvrusb2/pvrusb2-context.c index cf129746205d..6bbed88d7867 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-context.c +++ b/drivers/media/video/pvrusb2/pvrusb2-context.c | |||
@@ -83,9 +83,8 @@ struct pvr2_context *pvr2_context_create( | |||
83 | void (*setup_func)(struct pvr2_context *)) | 83 | void (*setup_func)(struct pvr2_context *)) |
84 | { | 84 | { |
85 | struct pvr2_context *mp = NULL; | 85 | struct pvr2_context *mp = NULL; |
86 | mp = kmalloc(sizeof(*mp),GFP_KERNEL); | 86 | mp = kzalloc(sizeof(*mp),GFP_KERNEL); |
87 | if (!mp) goto done; | 87 | if (!mp) goto done; |
88 | memset(mp,0,sizeof(*mp)); | ||
89 | pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_main id=%p",mp); | 88 | pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_main id=%p",mp); |
90 | mp->setup_func = setup_func; | 89 | mp->setup_func = setup_func; |
91 | mutex_init(&mp->mutex); | 90 | mutex_init(&mp->mutex); |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-ctrl.c b/drivers/media/video/pvrusb2/pvrusb2-ctrl.c index c77de859cc8e..f569b00201dd 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-ctrl.c +++ b/drivers/media/video/pvrusb2/pvrusb2-ctrl.c | |||
@@ -26,6 +26,27 @@ | |||
26 | #include <linux/mutex.h> | 26 | #include <linux/mutex.h> |
27 | 27 | ||
28 | 28 | ||
29 | static int pvr2_ctrl_range_check(struct pvr2_ctrl *cptr,int val) | ||
30 | { | ||
31 | if (cptr->info->check_value) { | ||
32 | if (!cptr->info->check_value(cptr,val)) return -ERANGE; | ||
33 | } else { | ||
34 | int lim; | ||
35 | lim = cptr->info->def.type_int.min_value; | ||
36 | if (cptr->info->get_min_value) { | ||
37 | cptr->info->get_min_value(cptr,&lim); | ||
38 | } | ||
39 | if (val < lim) return -ERANGE; | ||
40 | lim = cptr->info->def.type_int.max_value; | ||
41 | if (cptr->info->get_max_value) { | ||
42 | cptr->info->get_max_value(cptr,&lim); | ||
43 | } | ||
44 | if (val > lim) return -ERANGE; | ||
45 | } | ||
46 | return 0; | ||
47 | } | ||
48 | |||
49 | |||
29 | /* Set the given control. */ | 50 | /* Set the given control. */ |
30 | int pvr2_ctrl_set_value(struct pvr2_ctrl *cptr,int val) | 51 | int pvr2_ctrl_set_value(struct pvr2_ctrl *cptr,int val) |
31 | { | 52 | { |
@@ -43,17 +64,8 @@ int pvr2_ctrl_set_mask_value(struct pvr2_ctrl *cptr,int mask,int val) | |||
43 | if (cptr->info->type == pvr2_ctl_bitmask) { | 64 | if (cptr->info->type == pvr2_ctl_bitmask) { |
44 | mask &= cptr->info->def.type_bitmask.valid_bits; | 65 | mask &= cptr->info->def.type_bitmask.valid_bits; |
45 | } else if (cptr->info->type == pvr2_ctl_int) { | 66 | } else if (cptr->info->type == pvr2_ctl_int) { |
46 | int lim; | 67 | ret = pvr2_ctrl_range_check(cptr,val); |
47 | lim = cptr->info->def.type_int.min_value; | 68 | if (ret < 0) break; |
48 | if (cptr->info->get_min_value) { | ||
49 | cptr->info->get_min_value(cptr,&lim); | ||
50 | } | ||
51 | if (val < lim) break; | ||
52 | lim = cptr->info->def.type_int.max_value; | ||
53 | if (cptr->info->get_max_value) { | ||
54 | cptr->info->get_max_value(cptr,&lim); | ||
55 | } | ||
56 | if (val > lim) break; | ||
57 | } else if (cptr->info->type == pvr2_ctl_enum) { | 69 | } else if (cptr->info->type == pvr2_ctl_enum) { |
58 | if (val >= cptr->info->def.type_enum.count) { | 70 | if (val >= cptr->info->def.type_enum.count) { |
59 | break; | 71 | break; |
@@ -498,16 +510,13 @@ int pvr2_ctrl_sym_to_value(struct pvr2_ctrl *cptr, | |||
498 | LOCK_TAKE(cptr->hdw->big_lock); do { | 510 | LOCK_TAKE(cptr->hdw->big_lock); do { |
499 | if (cptr->info->type == pvr2_ctl_int) { | 511 | if (cptr->info->type == pvr2_ctl_int) { |
500 | ret = parse_token(ptr,len,valptr,NULL,0); | 512 | ret = parse_token(ptr,len,valptr,NULL,0); |
501 | if ((ret >= 0) && | 513 | if (ret >= 0) { |
502 | ((*valptr < cptr->info->def.type_int.min_value) || | 514 | ret = pvr2_ctrl_range_check(cptr,*valptr); |
503 | (*valptr > cptr->info->def.type_int.max_value))) { | ||
504 | ret = -ERANGE; | ||
505 | } | 515 | } |
506 | if (maskptr) *maskptr = ~0; | 516 | if (maskptr) *maskptr = ~0; |
507 | } else if (cptr->info->type == pvr2_ctl_bool) { | 517 | } else if (cptr->info->type == pvr2_ctl_bool) { |
508 | ret = parse_token( | 518 | ret = parse_token(ptr,len,valptr,boolNames, |
509 | ptr,len,valptr,boolNames, | 519 | ARRAY_SIZE(boolNames)); |
510 | sizeof(boolNames)/sizeof(boolNames[0])); | ||
511 | if (ret == 1) { | 520 | if (ret == 1) { |
512 | *valptr = *valptr ? !0 : 0; | 521 | *valptr = *valptr ? !0 : 0; |
513 | } else if (ret == 0) { | 522 | } else if (ret == 0) { |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c index 8df969c4874c..e8a9252c7df6 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c +++ b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c | |||
@@ -63,6 +63,7 @@ static void set_input(struct pvr2_v4l_cx2584x *ctxt) | |||
63 | vid_input = CX25840_COMPOSITE7; | 63 | vid_input = CX25840_COMPOSITE7; |
64 | aud_input = CX25840_AUDIO8; | 64 | aud_input = CX25840_AUDIO8; |
65 | break; | 65 | break; |
66 | case PVR2_CVAL_INPUT_RADIO: // Treat same as composite | ||
66 | case PVR2_CVAL_INPUT_COMPOSITE: | 67 | case PVR2_CVAL_INPUT_COMPOSITE: |
67 | vid_input = CX25840_COMPOSITE3; | 68 | vid_input = CX25840_COMPOSITE3; |
68 | aud_input = CX25840_AUDIO_SERIAL; | 69 | aud_input = CX25840_AUDIO_SERIAL; |
@@ -71,7 +72,6 @@ static void set_input(struct pvr2_v4l_cx2584x *ctxt) | |||
71 | vid_input = CX25840_SVIDEO1; | 72 | vid_input = CX25840_SVIDEO1; |
72 | aud_input = CX25840_AUDIO_SERIAL; | 73 | aud_input = CX25840_AUDIO_SERIAL; |
73 | break; | 74 | break; |
74 | case PVR2_CVAL_INPUT_RADIO: | ||
75 | default: | 75 | default: |
76 | // Just set it to be composite input for now... | 76 | // Just set it to be composite input for now... |
77 | vid_input = CX25840_COMPOSITE3; | 77 | vid_input = CX25840_COMPOSITE3; |
@@ -150,8 +150,7 @@ static int decoder_check(struct pvr2_v4l_cx2584x *ctxt) | |||
150 | unsigned long msk; | 150 | unsigned long msk; |
151 | unsigned int idx; | 151 | unsigned int idx; |
152 | 152 | ||
153 | for (idx = 0; idx < sizeof(decoder_ops)/sizeof(decoder_ops[0]); | 153 | for (idx = 0; idx < ARRAY_SIZE(decoder_ops); idx++) { |
154 | idx++) { | ||
155 | msk = 1 << idx; | 154 | msk = 1 << idx; |
156 | if (ctxt->stale_mask & msk) continue; | 155 | if (ctxt->stale_mask & msk) continue; |
157 | if (decoder_ops[idx].check(ctxt)) { | 156 | if (decoder_ops[idx].check(ctxt)) { |
@@ -167,8 +166,7 @@ static void decoder_update(struct pvr2_v4l_cx2584x *ctxt) | |||
167 | unsigned long msk; | 166 | unsigned long msk; |
168 | unsigned int idx; | 167 | unsigned int idx; |
169 | 168 | ||
170 | for (idx = 0; idx < sizeof(decoder_ops)/sizeof(decoder_ops[0]); | 169 | for (idx = 0; idx < ARRAY_SIZE(decoder_ops); idx++) { |
171 | idx++) { | ||
172 | msk = 1 << idx; | 170 | msk = 1 << idx; |
173 | if (!(ctxt->stale_mask & msk)) continue; | 171 | if (!(ctxt->stale_mask & msk)) continue; |
174 | ctxt->stale_mask &= ~msk; | 172 | ctxt->stale_mask &= ~msk; |
@@ -199,18 +197,6 @@ static int decoder_detect(struct pvr2_i2c_client *cp) | |||
199 | } | 197 | } |
200 | 198 | ||
201 | 199 | ||
202 | static int decoder_is_tuned(struct pvr2_v4l_cx2584x *ctxt) | ||
203 | { | ||
204 | struct v4l2_tuner vt; | ||
205 | int ret; | ||
206 | |||
207 | memset(&vt,0,sizeof(vt)); | ||
208 | ret = pvr2_i2c_client_cmd(ctxt->client,VIDIOC_G_TUNER,&vt); | ||
209 | if (ret < 0) return -EINVAL; | ||
210 | return vt.signal ? 1 : 0; | ||
211 | } | ||
212 | |||
213 | |||
214 | static unsigned int decoder_describe(struct pvr2_v4l_cx2584x *ctxt, | 200 | static unsigned int decoder_describe(struct pvr2_v4l_cx2584x *ctxt, |
215 | char *buf,unsigned int cnt) | 201 | char *buf,unsigned int cnt) |
216 | { | 202 | { |
@@ -243,21 +229,18 @@ int pvr2_i2c_cx2584x_v4l_setup(struct pvr2_hdw *hdw, | |||
243 | if (cp->handler) return 0; | 229 | if (cp->handler) return 0; |
244 | if (!decoder_detect(cp)) return 0; | 230 | if (!decoder_detect(cp)) return 0; |
245 | 231 | ||
246 | ctxt = kmalloc(sizeof(*ctxt),GFP_KERNEL); | 232 | ctxt = kzalloc(sizeof(*ctxt),GFP_KERNEL); |
247 | if (!ctxt) return 0; | 233 | if (!ctxt) return 0; |
248 | memset(ctxt,0,sizeof(*ctxt)); | ||
249 | 234 | ||
250 | ctxt->handler.func_data = ctxt; | 235 | ctxt->handler.func_data = ctxt; |
251 | ctxt->handler.func_table = &hfuncs; | 236 | ctxt->handler.func_table = &hfuncs; |
252 | ctxt->ctrl.ctxt = ctxt; | 237 | ctxt->ctrl.ctxt = ctxt; |
253 | ctxt->ctrl.detach = (void (*)(void *))decoder_detach; | 238 | ctxt->ctrl.detach = (void (*)(void *))decoder_detach; |
254 | ctxt->ctrl.enable = (void (*)(void *,int))decoder_enable; | 239 | ctxt->ctrl.enable = (void (*)(void *,int))decoder_enable; |
255 | ctxt->ctrl.tuned = (int (*)(void *))decoder_is_tuned; | ||
256 | ctxt->ctrl.force_reset = (void (*)(void*))decoder_reset; | 240 | ctxt->ctrl.force_reset = (void (*)(void*))decoder_reset; |
257 | ctxt->client = cp; | 241 | ctxt->client = cp; |
258 | ctxt->hdw = hdw; | 242 | ctxt->hdw = hdw; |
259 | ctxt->stale_mask = (1 << (sizeof(decoder_ops)/ | 243 | ctxt->stale_mask = (1 << ARRAY_SIZE(decoder_ops)) - 1; |
260 | sizeof(decoder_ops[0]))) - 1; | ||
261 | hdw->decoder_ctrl = &ctxt->ctrl; | 244 | hdw->decoder_ctrl = &ctxt->ctrl; |
262 | cp->handler = &ctxt->handler; | 245 | cp->handler = &ctxt->handler; |
263 | { | 246 | { |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-debugifc.c b/drivers/media/video/pvrusb2/pvrusb2-debugifc.c index f985f00d885a..e9da9bb8f8de 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-debugifc.c +++ b/drivers/media/video/pvrusb2/pvrusb2-debugifc.c | |||
@@ -152,7 +152,7 @@ static unsigned long debugifc_find_mask(const char *buf,unsigned int count) | |||
152 | { | 152 | { |
153 | struct debugifc_mask_item *mip; | 153 | struct debugifc_mask_item *mip; |
154 | unsigned int idx; | 154 | unsigned int idx; |
155 | for (idx = 0; idx < sizeof(mask_items)/sizeof(mask_items[0]); idx++) { | 155 | for (idx = 0; idx < ARRAY_SIZE(mask_items); idx++) { |
156 | mip = mask_items + idx; | 156 | mip = mask_items + idx; |
157 | if (debugifc_match_keyword(buf,count,mip->name)) { | 157 | if (debugifc_match_keyword(buf,count,mip->name)) { |
158 | return mip->msk; | 158 | return mip->msk; |
@@ -169,7 +169,7 @@ static int debugifc_print_mask(char *buf,unsigned int sz, | |||
169 | unsigned int idx; | 169 | unsigned int idx; |
170 | int bcnt = 0; | 170 | int bcnt = 0; |
171 | int ccnt; | 171 | int ccnt; |
172 | for (idx = 0; idx < sizeof(mask_items)/sizeof(mask_items[0]); idx++) { | 172 | for (idx = 0; idx < ARRAY_SIZE(mask_items); idx++) { |
173 | mip = mask_items + idx; | 173 | mip = mask_items + idx; |
174 | if (!(mip->msk & msk)) continue; | 174 | if (!(mip->msk & msk)) continue; |
175 | ccnt = scnprintf(buf,sz,"%s%c%s", | 175 | ccnt = scnprintf(buf,sz,"%s%c%s", |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-eeprom.c b/drivers/media/video/pvrusb2/pvrusb2-eeprom.c index 6cff8e75f426..45cbca0143ca 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-eeprom.c +++ b/drivers/media/video/pvrusb2/pvrusb2-eeprom.c | |||
@@ -102,9 +102,8 @@ static u8 *pvr2_eeprom_fetch(struct pvr2_hdw *hdw) | |||
102 | } | 102 | } |
103 | msg[1].len = pcnt; | 103 | msg[1].len = pcnt; |
104 | msg[1].buf = eeprom+tcnt; | 104 | msg[1].buf = eeprom+tcnt; |
105 | if ((ret = i2c_transfer( | 105 | if ((ret = i2c_transfer(&hdw->i2c_adap, |
106 | &hdw->i2c_adap, | 106 | msg,ARRAY_SIZE(msg))) != 2) { |
107 | msg,sizeof(msg)/sizeof(msg[0]))) != 2) { | ||
108 | pvr2_trace(PVR2_TRACE_ERROR_LEGS, | 107 | pvr2_trace(PVR2_TRACE_ERROR_LEGS, |
109 | "eeprom fetch set offs err=%d",ret); | 108 | "eeprom fetch set offs err=%d",ret); |
110 | kfree(eeprom); | 109 | kfree(eeprom); |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-encoder.c b/drivers/media/video/pvrusb2/pvrusb2-encoder.c index c94f97b79392..5786faf9b3b8 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-encoder.c +++ b/drivers/media/video/pvrusb2/pvrusb2-encoder.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include "pvrusb2-encoder.h" | 26 | #include "pvrusb2-encoder.h" |
27 | #include "pvrusb2-hdw-internal.h" | 27 | #include "pvrusb2-hdw-internal.h" |
28 | #include "pvrusb2-debug.h" | 28 | #include "pvrusb2-debug.h" |
29 | #include "pvrusb2-fx2-cmd.h" | ||
29 | 30 | ||
30 | 31 | ||
31 | 32 | ||
@@ -34,34 +35,41 @@ | |||
34 | #define IVTV_MBOX_DRIVER_DONE 0x00000002 | 35 | #define IVTV_MBOX_DRIVER_DONE 0x00000002 |
35 | #define IVTV_MBOX_DRIVER_BUSY 0x00000001 | 36 | #define IVTV_MBOX_DRIVER_BUSY 0x00000001 |
36 | 37 | ||
38 | #define MBOX_BASE 0x44 | ||
39 | |||
37 | 40 | ||
38 | static int pvr2_encoder_write_words(struct pvr2_hdw *hdw, | 41 | static int pvr2_encoder_write_words(struct pvr2_hdw *hdw, |
42 | unsigned int offs, | ||
39 | const u32 *data, unsigned int dlen) | 43 | const u32 *data, unsigned int dlen) |
40 | { | 44 | { |
41 | unsigned int idx; | 45 | unsigned int idx,addr; |
46 | unsigned int bAddr; | ||
42 | int ret; | 47 | int ret; |
43 | unsigned int offs = 0; | ||
44 | unsigned int chunkCnt; | 48 | unsigned int chunkCnt; |
45 | 49 | ||
46 | /* | 50 | /* |
47 | 51 | ||
48 | Format: First byte must be 0x01. Remaining 32 bit words are | 52 | Format: First byte must be 0x01. Remaining 32 bit words are |
49 | spread out into chunks of 7 bytes each, little-endian ordered, | 53 | spread out into chunks of 7 bytes each, with the first 4 bytes |
50 | offset at zero within each 2 blank bytes following and a | 54 | being the data word (little endian), and the next 3 bytes |
51 | single byte that is 0x44 plus the offset of the word. Repeat | 55 | being the address where that data word is to be written (big |
52 | request for additional words, with offset adjusted | 56 | endian). Repeat request for additional words, with offset |
53 | accordingly. | 57 | adjusted accordingly. |
54 | 58 | ||
55 | */ | 59 | */ |
56 | while (dlen) { | 60 | while (dlen) { |
57 | chunkCnt = 8; | 61 | chunkCnt = 8; |
58 | if (chunkCnt > dlen) chunkCnt = dlen; | 62 | if (chunkCnt > dlen) chunkCnt = dlen; |
59 | memset(hdw->cmd_buffer,0,sizeof(hdw->cmd_buffer)); | 63 | memset(hdw->cmd_buffer,0,sizeof(hdw->cmd_buffer)); |
60 | hdw->cmd_buffer[0] = 0x01; | 64 | bAddr = 0; |
65 | hdw->cmd_buffer[bAddr++] = FX2CMD_MEM_WRITE_DWORD; | ||
61 | for (idx = 0; idx < chunkCnt; idx++) { | 66 | for (idx = 0; idx < chunkCnt; idx++) { |
62 | hdw->cmd_buffer[1+(idx*7)+6] = 0x44 + idx + offs; | 67 | addr = idx + offs; |
63 | PVR2_DECOMPOSE_LE(hdw->cmd_buffer, 1+(idx*7), | 68 | hdw->cmd_buffer[bAddr+6] = (addr & 0xffu); |
64 | data[idx]); | 69 | hdw->cmd_buffer[bAddr+5] = ((addr>>8) & 0xffu); |
70 | hdw->cmd_buffer[bAddr+4] = ((addr>>16) & 0xffu); | ||
71 | PVR2_DECOMPOSE_LE(hdw->cmd_buffer, bAddr,data[idx]); | ||
72 | bAddr += 7; | ||
65 | } | 73 | } |
66 | ret = pvr2_send_request(hdw, | 74 | ret = pvr2_send_request(hdw, |
67 | hdw->cmd_buffer,1+(chunkCnt*7), | 75 | hdw->cmd_buffer,1+(chunkCnt*7), |
@@ -76,33 +84,42 @@ static int pvr2_encoder_write_words(struct pvr2_hdw *hdw, | |||
76 | } | 84 | } |
77 | 85 | ||
78 | 86 | ||
79 | static int pvr2_encoder_read_words(struct pvr2_hdw *hdw,int statusFl, | 87 | static int pvr2_encoder_read_words(struct pvr2_hdw *hdw, |
88 | unsigned int offs, | ||
80 | u32 *data, unsigned int dlen) | 89 | u32 *data, unsigned int dlen) |
81 | { | 90 | { |
82 | unsigned int idx; | 91 | unsigned int idx; |
83 | int ret; | 92 | int ret; |
84 | unsigned int offs = 0; | ||
85 | unsigned int chunkCnt; | 93 | unsigned int chunkCnt; |
86 | 94 | ||
87 | /* | 95 | /* |
88 | 96 | ||
89 | Format: First byte must be 0x02 (status check) or 0x28 (read | 97 | Format: First byte must be 0x02 (status check) or 0x28 (read |
90 | back block of 32 bit words). Next 6 bytes must be zero, | 98 | back block of 32 bit words). Next 6 bytes must be zero, |
91 | followed by a single byte of 0x44+offset for portion to be | 99 | followed by a single byte of MBOX_BASE+offset for portion to |
92 | read. Returned data is packed set of 32 bits words that were | 100 | be read. Returned data is packed set of 32 bits words that |
93 | read. | 101 | were read. |
94 | 102 | ||
95 | */ | 103 | */ |
96 | 104 | ||
97 | while (dlen) { | 105 | while (dlen) { |
98 | chunkCnt = 16; | 106 | chunkCnt = 16; |
99 | if (chunkCnt > dlen) chunkCnt = dlen; | 107 | if (chunkCnt > dlen) chunkCnt = dlen; |
100 | memset(hdw->cmd_buffer,0,sizeof(hdw->cmd_buffer)); | 108 | if (chunkCnt < 16) chunkCnt = 1; |
101 | hdw->cmd_buffer[0] = statusFl ? 0x02 : 0x28; | 109 | hdw->cmd_buffer[0] = |
102 | hdw->cmd_buffer[7] = 0x44 + offs; | 110 | ((chunkCnt == 1) ? |
111 | FX2CMD_MEM_READ_DWORD : FX2CMD_MEM_READ_64BYTES); | ||
112 | hdw->cmd_buffer[1] = 0; | ||
113 | hdw->cmd_buffer[2] = 0; | ||
114 | hdw->cmd_buffer[3] = 0; | ||
115 | hdw->cmd_buffer[4] = 0; | ||
116 | hdw->cmd_buffer[5] = ((offs>>16) & 0xffu); | ||
117 | hdw->cmd_buffer[6] = ((offs>>8) & 0xffu); | ||
118 | hdw->cmd_buffer[7] = (offs & 0xffu); | ||
103 | ret = pvr2_send_request(hdw, | 119 | ret = pvr2_send_request(hdw, |
104 | hdw->cmd_buffer,8, | 120 | hdw->cmd_buffer,8, |
105 | hdw->cmd_buffer,chunkCnt * 4); | 121 | hdw->cmd_buffer, |
122 | (chunkCnt == 1 ? 4 : 16 * 4)); | ||
106 | if (ret) return ret; | 123 | if (ret) return ret; |
107 | 124 | ||
108 | for (idx = 0; idx < chunkCnt; idx++) { | 125 | for (idx = 0; idx < chunkCnt; idx++) { |
@@ -129,6 +146,8 @@ static int pvr2_encoder_cmd(void *ctxt, | |||
129 | u32 *argp) | 146 | u32 *argp) |
130 | { | 147 | { |
131 | unsigned int poll_count; | 148 | unsigned int poll_count; |
149 | unsigned int try_count = 0; | ||
150 | int retry_flag; | ||
132 | int ret = 0; | 151 | int ret = 0; |
133 | unsigned int idx; | 152 | unsigned int idx; |
134 | /* These sizes look to be limited by the FX2 firmware implementation */ | 153 | /* These sizes look to be limited by the FX2 firmware implementation */ |
@@ -140,14 +159,15 @@ static int pvr2_encoder_cmd(void *ctxt, | |||
140 | /* | 159 | /* |
141 | 160 | ||
142 | The encoder seems to speak entirely using blocks 32 bit words. | 161 | The encoder seems to speak entirely using blocks 32 bit words. |
143 | In ivtv driver terms, this is a mailbox which we populate with | 162 | In ivtv driver terms, this is a mailbox at MBOX_BASE which we |
144 | data and watch what the hardware does with it. The first word | 163 | populate with data and watch what the hardware does with it. |
145 | is a set of flags used to control the transaction, the second | 164 | The first word is a set of flags used to control the |
146 | word is the command to execute, the third byte is zero (ivtv | 165 | transaction, the second word is the command to execute, the |
147 | driver suggests that this is some kind of return value), and | 166 | third byte is zero (ivtv driver suggests that this is some |
148 | the fourth byte is a specified timeout (windows driver always | 167 | kind of return value), and the fourth byte is a specified |
149 | uses 0x00060000 except for one case when it is zero). All | 168 | timeout (windows driver always uses 0x00060000 except for one |
150 | successive words are the argument words for the command. | 169 | case when it is zero). All successive words are the argument |
170 | words for the command. | ||
151 | 171 | ||
152 | First, write out the entire set of words, with the first word | 172 | First, write out the entire set of words, with the first word |
153 | being zero. | 173 | being zero. |
@@ -156,44 +176,42 @@ static int pvr2_encoder_cmd(void *ctxt, | |||
156 | IVTV_MBOX_DRIVER_DONE | IVTV_DRIVER_BUSY this time (which | 176 | IVTV_MBOX_DRIVER_DONE | IVTV_DRIVER_BUSY this time (which |
157 | probably means "go"). | 177 | probably means "go"). |
158 | 178 | ||
159 | Next, read back 16 words as status. Check the first word, | 179 | Next, read back the return count words. Check the first word, |
160 | which should have IVTV_MBOX_FIRMWARE_DONE set. If however | 180 | which should have IVTV_MBOX_FIRMWARE_DONE set. If however |
161 | that bit is not set, then the command isn't done so repeat the | 181 | that bit is not set, then the command isn't done so repeat the |
162 | read. | 182 | read until it is set. |
163 | |||
164 | Next, read back 32 words and compare with the original | ||
165 | arugments. Hopefully they will match. | ||
166 | 183 | ||
167 | Finally, write out just the first word again, but set it to | 184 | Finally, write out just the first word again, but set it to |
168 | 0x0 this time (which probably means "idle"). | 185 | 0x0 this time (which probably means "idle"). |
169 | 186 | ||
170 | */ | 187 | */ |
171 | 188 | ||
172 | if (arg_cnt_send > (sizeof(wrData)/sizeof(wrData[0]))-4) { | 189 | if (arg_cnt_send > (ARRAY_SIZE(wrData) - 4)) { |
173 | pvr2_trace( | 190 | pvr2_trace( |
174 | PVR2_TRACE_ERROR_LEGS, | 191 | PVR2_TRACE_ERROR_LEGS, |
175 | "Failed to write cx23416 command" | 192 | "Failed to write cx23416 command" |
176 | " - too many input arguments" | 193 | " - too many input arguments" |
177 | " (was given %u limit %u)", | 194 | " (was given %u limit %lu)", |
178 | arg_cnt_send, | 195 | arg_cnt_send, (long unsigned) ARRAY_SIZE(wrData) - 4); |
179 | (unsigned int)(sizeof(wrData)/sizeof(wrData[0])) - 4); | ||
180 | return -EINVAL; | 196 | return -EINVAL; |
181 | } | 197 | } |
182 | 198 | ||
183 | if (arg_cnt_recv > (sizeof(rdData)/sizeof(rdData[0]))-4) { | 199 | if (arg_cnt_recv > (ARRAY_SIZE(rdData) - 4)) { |
184 | pvr2_trace( | 200 | pvr2_trace( |
185 | PVR2_TRACE_ERROR_LEGS, | 201 | PVR2_TRACE_ERROR_LEGS, |
186 | "Failed to write cx23416 command" | 202 | "Failed to write cx23416 command" |
187 | " - too many return arguments" | 203 | " - too many return arguments" |
188 | " (was given %u limit %u)", | 204 | " (was given %u limit %lu)", |
189 | arg_cnt_recv, | 205 | arg_cnt_recv, (long unsigned) ARRAY_SIZE(rdData) - 4); |
190 | (unsigned int)(sizeof(rdData)/sizeof(rdData[0])) - 4); | ||
191 | return -EINVAL; | 206 | return -EINVAL; |
192 | } | 207 | } |
193 | 208 | ||
194 | 209 | ||
195 | LOCK_TAKE(hdw->ctl_lock); do { | 210 | LOCK_TAKE(hdw->ctl_lock); do { |
196 | 211 | ||
212 | retry_flag = 0; | ||
213 | try_count++; | ||
214 | ret = 0; | ||
197 | wrData[0] = 0; | 215 | wrData[0] = 0; |
198 | wrData[1] = cmd; | 216 | wrData[1] = cmd; |
199 | wrData[2] = 0; | 217 | wrData[2] = 0; |
@@ -201,59 +219,74 @@ static int pvr2_encoder_cmd(void *ctxt, | |||
201 | for (idx = 0; idx < arg_cnt_send; idx++) { | 219 | for (idx = 0; idx < arg_cnt_send; idx++) { |
202 | wrData[idx+4] = argp[idx]; | 220 | wrData[idx+4] = argp[idx]; |
203 | } | 221 | } |
204 | for (; idx < (sizeof(wrData)/sizeof(wrData[0]))-4; idx++) { | 222 | for (; idx < ARRAY_SIZE(wrData) - 4; idx++) { |
205 | wrData[idx+4] = 0; | 223 | wrData[idx+4] = 0; |
206 | } | 224 | } |
207 | 225 | ||
208 | ret = pvr2_encoder_write_words(hdw,wrData,idx); | 226 | ret = pvr2_encoder_write_words(hdw,MBOX_BASE,wrData,idx); |
209 | if (ret) break; | 227 | if (ret) break; |
210 | wrData[0] = IVTV_MBOX_DRIVER_DONE|IVTV_MBOX_DRIVER_BUSY; | 228 | wrData[0] = IVTV_MBOX_DRIVER_DONE|IVTV_MBOX_DRIVER_BUSY; |
211 | ret = pvr2_encoder_write_words(hdw,wrData,1); | 229 | ret = pvr2_encoder_write_words(hdw,MBOX_BASE,wrData,1); |
212 | if (ret) break; | 230 | if (ret) break; |
213 | poll_count = 0; | 231 | poll_count = 0; |
214 | while (1) { | 232 | while (1) { |
215 | if (poll_count < 10000000) poll_count++; | 233 | poll_count++; |
216 | ret = pvr2_encoder_read_words(hdw,!0,rdData,1); | 234 | ret = pvr2_encoder_read_words(hdw,MBOX_BASE,rdData, |
217 | if (ret) break; | 235 | arg_cnt_recv+4); |
236 | if (ret) { | ||
237 | break; | ||
238 | } | ||
218 | if (rdData[0] & IVTV_MBOX_FIRMWARE_DONE) { | 239 | if (rdData[0] & IVTV_MBOX_FIRMWARE_DONE) { |
219 | break; | 240 | break; |
220 | } | 241 | } |
221 | if (poll_count == 100) { | 242 | if (rdData[0] && (poll_count < 1000)) continue; |
243 | if (!rdData[0]) { | ||
244 | retry_flag = !0; | ||
222 | pvr2_trace( | 245 | pvr2_trace( |
223 | PVR2_TRACE_ERROR_LEGS, | 246 | PVR2_TRACE_ERROR_LEGS, |
224 | "***WARNING*** device's encoder" | 247 | "Encoder timed out waiting for us" |
225 | " appears to be stuck" | 248 | "; arranging to retry"); |
226 | " (status=0%08x)",rdData[0]); | 249 | } else { |
227 | pvr2_trace( | 250 | pvr2_trace( |
228 | PVR2_TRACE_ERROR_LEGS, | 251 | PVR2_TRACE_ERROR_LEGS, |
229 | "Encoder command: 0x%02x",cmd); | 252 | "***WARNING*** device's encoder" |
230 | for (idx = 4; idx < arg_cnt_send; idx++) { | 253 | " appears to be stuck" |
231 | pvr2_trace( | 254 | " (status=0x%08x)",rdData[0]); |
232 | PVR2_TRACE_ERROR_LEGS, | 255 | } |
233 | "Encoder arg%d: 0x%08x", | 256 | pvr2_trace( |
234 | idx-3,wrData[idx]); | 257 | PVR2_TRACE_ERROR_LEGS, |
235 | } | 258 | "Encoder command: 0x%02x",cmd); |
259 | for (idx = 4; idx < arg_cnt_send; idx++) { | ||
236 | pvr2_trace( | 260 | pvr2_trace( |
237 | PVR2_TRACE_ERROR_LEGS, | 261 | PVR2_TRACE_ERROR_LEGS, |
238 | "Giving up waiting." | 262 | "Encoder arg%d: 0x%08x", |
239 | " It is likely that" | 263 | idx-3,wrData[idx]); |
240 | " this is a bad idea..."); | ||
241 | ret = -EBUSY; | ||
242 | break; | ||
243 | } | 264 | } |
265 | ret = -EBUSY; | ||
266 | break; | ||
267 | } | ||
268 | if (retry_flag) { | ||
269 | if (try_count < 20) continue; | ||
270 | pvr2_trace( | ||
271 | PVR2_TRACE_ERROR_LEGS, | ||
272 | "Too many retries..."); | ||
273 | ret = -EBUSY; | ||
274 | } | ||
275 | if (ret) { | ||
276 | pvr2_trace( | ||
277 | PVR2_TRACE_ERROR_LEGS, | ||
278 | "Giving up on command." | ||
279 | " It is likely that" | ||
280 | " this is a bad idea..."); | ||
281 | break; | ||
244 | } | 282 | } |
245 | if (ret) break; | ||
246 | wrData[0] = 0x7; | 283 | wrData[0] = 0x7; |
247 | ret = pvr2_encoder_read_words( | ||
248 | hdw,0,rdData, | ||
249 | sizeof(rdData)/sizeof(rdData[0])); | ||
250 | if (ret) break; | ||
251 | for (idx = 0; idx < arg_cnt_recv; idx++) { | 284 | for (idx = 0; idx < arg_cnt_recv; idx++) { |
252 | argp[idx] = rdData[idx+4]; | 285 | argp[idx] = rdData[idx+4]; |
253 | } | 286 | } |
254 | 287 | ||
255 | wrData[0] = 0x0; | 288 | wrData[0] = 0x0; |
256 | ret = pvr2_encoder_write_words(hdw,wrData,1); | 289 | ret = pvr2_encoder_write_words(hdw,MBOX_BASE,wrData,1); |
257 | if (ret) break; | 290 | if (ret) break; |
258 | 291 | ||
259 | } while(0); LOCK_GIVE(hdw->ctl_lock); | 292 | } while(0); LOCK_GIVE(hdw->ctl_lock); |
@@ -269,13 +302,13 @@ static int pvr2_encoder_vcmd(struct pvr2_hdw *hdw, int cmd, | |||
269 | unsigned int idx; | 302 | unsigned int idx; |
270 | u32 data[12]; | 303 | u32 data[12]; |
271 | 304 | ||
272 | if (args > sizeof(data)/sizeof(data[0])) { | 305 | if (args > ARRAY_SIZE(data)) { |
273 | pvr2_trace( | 306 | pvr2_trace( |
274 | PVR2_TRACE_ERROR_LEGS, | 307 | PVR2_TRACE_ERROR_LEGS, |
275 | "Failed to write cx23416 command" | 308 | "Failed to write cx23416 command" |
276 | " - too many arguments" | 309 | " - too many arguments" |
277 | " (was given %u limit %u)", | 310 | " (was given %u limit %lu)", |
278 | args,(unsigned int)(sizeof(data)/sizeof(data[0]))); | 311 | args, (long unsigned) ARRAY_SIZE(data)); |
279 | return -EINVAL; | 312 | return -EINVAL; |
280 | } | 313 | } |
281 | 314 | ||
@@ -288,6 +321,73 @@ static int pvr2_encoder_vcmd(struct pvr2_hdw *hdw, int cmd, | |||
288 | return pvr2_encoder_cmd(hdw,cmd,args,0,data); | 321 | return pvr2_encoder_cmd(hdw,cmd,args,0,data); |
289 | } | 322 | } |
290 | 323 | ||
324 | |||
325 | /* This implements some extra setup for the encoder that seems to be | ||
326 | specific to the PVR USB2 hardware. */ | ||
327 | int pvr2_encoder_prep_config(struct pvr2_hdw *hdw) | ||
328 | { | ||
329 | int ret = 0; | ||
330 | int encMisc3Arg = 0; | ||
331 | |||
332 | #if 0 | ||
333 | /* This inexplicable bit happens in the Hauppage windows | ||
334 | driver (for both 24xxx and 29xxx devices). However I | ||
335 | currently see no difference in behavior with or without | ||
336 | this stuff. Leave this here as a note of its existence, | ||
337 | but don't use it. */ | ||
338 | LOCK_TAKE(hdw->ctl_lock); do { | ||
339 | u32 dat[1]; | ||
340 | dat[0] = 0x80000640; | ||
341 | pvr2_encoder_write_words(hdw,0x01fe,dat,1); | ||
342 | pvr2_encoder_write_words(hdw,0x023e,dat,1); | ||
343 | } while(0); LOCK_GIVE(hdw->ctl_lock); | ||
344 | #endif | ||
345 | |||
346 | /* Mike Isely <isely@pobox.com> 26-Jan-2006 The windows driver | ||
347 | sends the following list of ENC_MISC commands (for both | ||
348 | 24xxx and 29xxx devices). Meanings are not entirely clear, | ||
349 | however without the ENC_MISC(3,1) command then we risk | ||
350 | random perpetual video corruption whenever the video input | ||
351 | breaks up for a moment (like when switching channels). */ | ||
352 | |||
353 | |||
354 | #if 0 | ||
355 | /* This ENC_MISC(5,0) command seems to hurt 29xxx sync | ||
356 | performance on channel changes, but is not a problem on | ||
357 | 24xxx devices. */ | ||
358 | ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 5,0,0,0); | ||
359 | #endif | ||
360 | |||
361 | /* This ENC_MISC(3,encMisc3Arg) command is critical - without | ||
362 | it there will eventually be video corruption. Also, the | ||
363 | 29xxx case is strange - the Windows driver is passing 1 | ||
364 | regardless of device type but if we have 1 for 29xxx device | ||
365 | the video turns sluggish. */ | ||
366 | switch (hdw->hdw_type) { | ||
367 | case PVR2_HDW_TYPE_24XXX: encMisc3Arg = 1; break; | ||
368 | case PVR2_HDW_TYPE_29XXX: encMisc3Arg = 0; break; | ||
369 | default: break; | ||
370 | } | ||
371 | ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 3, | ||
372 | encMisc3Arg,0,0); | ||
373 | |||
374 | ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 8,0,0,0); | ||
375 | |||
376 | #if 0 | ||
377 | /* This ENC_MISC(4,1) command is poisonous, so it is commented | ||
378 | out. But I'm leaving it here anyway to document its | ||
379 | existence in the Windows driver. The effect of this | ||
380 | command is that apps displaying the stream become sluggish | ||
381 | with stuttering video. */ | ||
382 | ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 4,1,0,0); | ||
383 | #endif | ||
384 | |||
385 | ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 0,3,0,0); | ||
386 | ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4,15,0,0,0); | ||
387 | |||
388 | return ret; | ||
389 | } | ||
390 | |||
291 | int pvr2_encoder_configure(struct pvr2_hdw *hdw) | 391 | int pvr2_encoder_configure(struct pvr2_hdw *hdw) |
292 | { | 392 | { |
293 | int ret; | 393 | int ret; |
@@ -302,6 +402,8 @@ int pvr2_encoder_configure(struct pvr2_hdw *hdw) | |||
302 | 402 | ||
303 | ret = 0; | 403 | ret = 0; |
304 | 404 | ||
405 | ret |= pvr2_encoder_prep_config(hdw); | ||
406 | |||
305 | if (!ret) ret = pvr2_encoder_vcmd( | 407 | if (!ret) ret = pvr2_encoder_vcmd( |
306 | hdw,CX2341X_ENC_SET_NUM_VSYNC_LINES, 2, | 408 | hdw,CX2341X_ENC_SET_NUM_VSYNC_LINES, 2, |
307 | 0xf0, 0xf0); | 409 | 0xf0, 0xf0); |
@@ -360,15 +462,22 @@ int pvr2_encoder_start(struct pvr2_hdw *hdw) | |||
360 | pvr2_hdw_gpio_chg_dir(hdw,0xffffffff,0x00000481); | 462 | pvr2_hdw_gpio_chg_dir(hdw,0xffffffff,0x00000481); |
361 | pvr2_hdw_gpio_chg_out(hdw,0xffffffff,0x00000000); | 463 | pvr2_hdw_gpio_chg_out(hdw,0xffffffff,0x00000000); |
362 | 464 | ||
363 | if (hdw->config == pvr2_config_vbi) { | 465 | pvr2_encoder_vcmd(hdw,CX2341X_ENC_MUTE_VIDEO,1, |
466 | hdw->input_val == PVR2_CVAL_INPUT_RADIO ? 1 : 0); | ||
467 | |||
468 | switch (hdw->config) { | ||
469 | case pvr2_config_vbi: | ||
364 | status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2, | 470 | status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2, |
365 | 0x01,0x14); | 471 | 0x01,0x14); |
366 | } else if (hdw->config == pvr2_config_mpeg) { | 472 | break; |
473 | case pvr2_config_mpeg: | ||
367 | status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2, | 474 | status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2, |
368 | 0,0x13); | 475 | 0,0x13); |
369 | } else { | 476 | break; |
477 | default: /* Unhandled cases for now */ | ||
370 | status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2, | 478 | status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2, |
371 | 0,0x13); | 479 | 0,0x13); |
480 | break; | ||
372 | } | 481 | } |
373 | if (!status) { | 482 | if (!status) { |
374 | hdw->subsys_enabled_mask |= (1<<PVR2_SUBSYS_B_ENC_RUN); | 483 | hdw->subsys_enabled_mask |= (1<<PVR2_SUBSYS_B_ENC_RUN); |
@@ -383,15 +492,19 @@ int pvr2_encoder_stop(struct pvr2_hdw *hdw) | |||
383 | /* mask all interrupts */ | 492 | /* mask all interrupts */ |
384 | pvr2_write_register(hdw, 0x0048, 0xffffffff); | 493 | pvr2_write_register(hdw, 0x0048, 0xffffffff); |
385 | 494 | ||
386 | if (hdw->config == pvr2_config_vbi) { | 495 | switch (hdw->config) { |
496 | case pvr2_config_vbi: | ||
387 | status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3, | 497 | status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3, |
388 | 0x01,0x01,0x14); | 498 | 0x01,0x01,0x14); |
389 | } else if (hdw->config == pvr2_config_mpeg) { | 499 | break; |
500 | case pvr2_config_mpeg: | ||
390 | status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3, | 501 | status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3, |
391 | 0x01,0,0x13); | 502 | 0x01,0,0x13); |
392 | } else { | 503 | break; |
504 | default: /* Unhandled cases for now */ | ||
393 | status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3, | 505 | status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3, |
394 | 0x01,0,0x13); | 506 | 0x01,0,0x13); |
507 | break; | ||
395 | } | 508 | } |
396 | 509 | ||
397 | /* change some GPIO data */ | 510 | /* change some GPIO data */ |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-fx2-cmd.h b/drivers/media/video/pvrusb2/pvrusb2-fx2-cmd.h new file mode 100644 index 000000000000..ffbc6d096108 --- /dev/null +++ b/drivers/media/video/pvrusb2/pvrusb2-fx2-cmd.h | |||
@@ -0,0 +1,62 @@ | |||
1 | /* | ||
2 | * | ||
3 | * $Id$ | ||
4 | * | ||
5 | * Copyright (C) 2007 Michael Krufky <mkrufky@linuxtv.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | #ifndef _PVRUSB2_FX2_CMD_H_ | ||
23 | #define _PVRUSB2_FX2_CMD_H_ | ||
24 | |||
25 | #define FX2CMD_MEM_WRITE_DWORD 0x01 | ||
26 | #define FX2CMD_MEM_READ_DWORD 0x02 | ||
27 | |||
28 | #define FX2CMD_MEM_READ_64BYTES 0x28 | ||
29 | |||
30 | #define FX2CMD_REG_WRITE 0x04 | ||
31 | #define FX2CMD_REG_READ 0x05 | ||
32 | #define FX2CMD_MEMSEL 0x06 | ||
33 | |||
34 | #define FX2CMD_I2C_WRITE 0x08 | ||
35 | #define FX2CMD_I2C_READ 0x09 | ||
36 | |||
37 | #define FX2CMD_GET_USB_SPEED 0x0b | ||
38 | |||
39 | #define FX2CMD_STREAMING_ON 0x36 | ||
40 | #define FX2CMD_STREAMING_OFF 0x37 | ||
41 | |||
42 | #define FX2CMD_FWPOST1 0x52 | ||
43 | |||
44 | #define FX2CMD_POWER_OFF 0xdc | ||
45 | #define FX2CMD_POWER_ON 0xde | ||
46 | |||
47 | #define FX2CMD_DEEP_RESET 0xdd | ||
48 | |||
49 | #define FX2CMD_GET_EEPROM_ADDR 0xeb | ||
50 | #define FX2CMD_GET_IR_CODE 0xec | ||
51 | |||
52 | #endif /* _PVRUSB2_FX2_CMD_H_ */ | ||
53 | |||
54 | /* | ||
55 | Stuff for Emacs to see, in order to encourage consistent editing style: | ||
56 | *** Local Variables: *** | ||
57 | *** mode: c *** | ||
58 | *** fill-column: 75 *** | ||
59 | *** tab-width: 8 *** | ||
60 | *** c-basic-offset: 8 *** | ||
61 | *** End: *** | ||
62 | */ | ||
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h index 34b08fbcc6ea..16bd74199601 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h | |||
@@ -60,6 +60,7 @@ struct pvr2_decoder; | |||
60 | 60 | ||
61 | typedef int (*pvr2_ctlf_is_dirty)(struct pvr2_ctrl *); | 61 | typedef int (*pvr2_ctlf_is_dirty)(struct pvr2_ctrl *); |
62 | typedef void (*pvr2_ctlf_clear_dirty)(struct pvr2_ctrl *); | 62 | typedef void (*pvr2_ctlf_clear_dirty)(struct pvr2_ctrl *); |
63 | typedef int (*pvr2_ctlf_check_value)(struct pvr2_ctrl *,int); | ||
63 | typedef int (*pvr2_ctlf_get_value)(struct pvr2_ctrl *,int *); | 64 | typedef int (*pvr2_ctlf_get_value)(struct pvr2_ctrl *,int *); |
64 | typedef int (*pvr2_ctlf_set_value)(struct pvr2_ctrl *,int msk,int val); | 65 | typedef int (*pvr2_ctlf_set_value)(struct pvr2_ctrl *,int msk,int val); |
65 | typedef int (*pvr2_ctlf_val_to_sym)(struct pvr2_ctrl *,int msk,int val, | 66 | typedef int (*pvr2_ctlf_val_to_sym)(struct pvr2_ctrl *,int msk,int val, |
@@ -83,6 +84,7 @@ struct pvr2_ctl_info { | |||
83 | pvr2_ctlf_get_value get_min_value; /* Get minimum allowed value */ | 84 | pvr2_ctlf_get_value get_min_value; /* Get minimum allowed value */ |
84 | pvr2_ctlf_get_value get_max_value; /* Get maximum allowed value */ | 85 | pvr2_ctlf_get_value get_max_value; /* Get maximum allowed value */ |
85 | pvr2_ctlf_set_value set_value; /* Set its value */ | 86 | pvr2_ctlf_set_value set_value; /* Set its value */ |
87 | pvr2_ctlf_check_value check_value; /* Check that value is valid */ | ||
86 | pvr2_ctlf_val_to_sym val_to_sym; /* Custom convert value->symbol */ | 88 | pvr2_ctlf_val_to_sym val_to_sym; /* Custom convert value->symbol */ |
87 | pvr2_ctlf_sym_to_val sym_to_val; /* Custom convert symbol->value */ | 89 | pvr2_ctlf_sym_to_val sym_to_val; /* Custom convert symbol->value */ |
88 | pvr2_ctlf_is_dirty is_dirty; /* Return true if dirty */ | 90 | pvr2_ctlf_is_dirty is_dirty; /* Return true if dirty */ |
@@ -135,17 +137,10 @@ struct pvr2_ctrl { | |||
135 | }; | 137 | }; |
136 | 138 | ||
137 | 139 | ||
138 | struct pvr2_audio_stat { | ||
139 | void *ctxt; | ||
140 | void (*detach)(void *); | ||
141 | int (*status)(void *); | ||
142 | }; | ||
143 | |||
144 | struct pvr2_decoder_ctrl { | 140 | struct pvr2_decoder_ctrl { |
145 | void *ctxt; | 141 | void *ctxt; |
146 | void (*detach)(void *); | 142 | void (*detach)(void *); |
147 | void (*enable)(void *,int); | 143 | void (*enable)(void *,int); |
148 | int (*tuned)(void *); | ||
149 | void (*force_reset)(void *); | 144 | void (*force_reset)(void *); |
150 | }; | 145 | }; |
151 | 146 | ||
@@ -212,7 +207,6 @@ struct pvr2_hdw { | |||
212 | /* Frequency table */ | 207 | /* Frequency table */ |
213 | unsigned int freqTable[FREQTABLE_SIZE]; | 208 | unsigned int freqTable[FREQTABLE_SIZE]; |
214 | unsigned int freqProgSlot; | 209 | unsigned int freqProgSlot; |
215 | unsigned int freqSlot; | ||
216 | 210 | ||
217 | /* Stuff for handling low level control interaction with device */ | 211 | /* Stuff for handling low level control interaction with device */ |
218 | struct mutex ctl_lock_mutex; | 212 | struct mutex ctl_lock_mutex; |
@@ -258,9 +252,17 @@ struct pvr2_hdw { | |||
258 | /* Tuner / frequency control stuff */ | 252 | /* Tuner / frequency control stuff */ |
259 | unsigned int tuner_type; | 253 | unsigned int tuner_type; |
260 | int tuner_updated; | 254 | int tuner_updated; |
261 | unsigned int freqVal; | 255 | unsigned int freqValTelevision; /* Current freq for tv mode */ |
256 | unsigned int freqValRadio; /* Current freq for radio mode */ | ||
257 | unsigned int freqSlotTelevision; /* Current slot for tv mode */ | ||
258 | unsigned int freqSlotRadio; /* Current slot for radio mode */ | ||
259 | unsigned int freqSelector; /* 0=radio 1=television */ | ||
262 | int freqDirty; | 260 | int freqDirty; |
263 | 261 | ||
262 | /* Current tuner info - this information is polled from the I2C bus */ | ||
263 | struct v4l2_tuner tuner_signal_info; | ||
264 | int tuner_signal_stale; | ||
265 | |||
264 | /* Video standard handling */ | 266 | /* Video standard handling */ |
265 | v4l2_std_id std_mask_eeprom; // Hardware supported selections | 267 | v4l2_std_id std_mask_eeprom; // Hardware supported selections |
266 | v4l2_std_id std_mask_avail; // Which standards we may select from | 268 | v4l2_std_id std_mask_avail; // Which standards we may select from |
@@ -281,20 +283,17 @@ struct pvr2_hdw { | |||
281 | int unit_number; /* ID for driver instance */ | 283 | int unit_number; /* ID for driver instance */ |
282 | unsigned long serial_number; /* ID for hardware itself */ | 284 | unsigned long serial_number; /* ID for hardware itself */ |
283 | 285 | ||
284 | /* Minor number used by v4l logic (yes, this is a hack, as there should | 286 | /* Minor numbers used by v4l logic (yes, this is a hack, as there |
285 | be no v4l junk here). Probably a better way to do this. */ | 287 | should be no v4l junk here). Probably a better way to do this. */ |
286 | int v4l_minor_number; | 288 | int v4l_minor_number_video; |
289 | int v4l_minor_number_vbi; | ||
290 | int v4l_minor_number_radio; | ||
287 | 291 | ||
288 | /* Location of eeprom or a negative number if none */ | 292 | /* Location of eeprom or a negative number if none */ |
289 | int eeprom_addr; | 293 | int eeprom_addr; |
290 | 294 | ||
291 | enum pvr2_config config; | 295 | enum pvr2_config config; |
292 | 296 | ||
293 | /* Information about what audio signal we're hearing */ | ||
294 | int flag_stereo; | ||
295 | int flag_bilingual; | ||
296 | struct pvr2_audio_stat *audio_stat; | ||
297 | |||
298 | /* Control state needed for cx2341x module */ | 297 | /* Control state needed for cx2341x module */ |
299 | struct cx2341x_mpeg_params enc_cur_state; | 298 | struct cx2341x_mpeg_params enc_cur_state; |
300 | struct cx2341x_mpeg_params enc_ctl_state; | 299 | struct cx2341x_mpeg_params enc_ctl_state; |
@@ -327,6 +326,9 @@ struct pvr2_hdw { | |||
327 | unsigned int control_cnt; | 326 | unsigned int control_cnt; |
328 | }; | 327 | }; |
329 | 328 | ||
329 | /* This function gets the current frequency */ | ||
330 | unsigned long pvr2_hdw_get_cur_freq(struct pvr2_hdw *); | ||
331 | |||
330 | #endif /* __PVRUSB2_HDW_INTERNAL_H */ | 332 | #endif /* __PVRUSB2_HDW_INTERNAL_H */ |
331 | 333 | ||
332 | /* | 334 | /* |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index d2004965187b..a1ca0f5007e0 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c | |||
@@ -36,6 +36,10 @@ | |||
36 | #include "pvrusb2-hdw-internal.h" | 36 | #include "pvrusb2-hdw-internal.h" |
37 | #include "pvrusb2-encoder.h" | 37 | #include "pvrusb2-encoder.h" |
38 | #include "pvrusb2-debug.h" | 38 | #include "pvrusb2-debug.h" |
39 | #include "pvrusb2-fx2-cmd.h" | ||
40 | |||
41 | #define TV_MIN_FREQ 55250000L | ||
42 | #define TV_MAX_FREQ 850000000L | ||
39 | 43 | ||
40 | struct usb_device_id pvr2_device_table[] = { | 44 | struct usb_device_id pvr2_device_table[] = { |
41 | [PVR2_HDW_TYPE_29XXX] = { USB_DEVICE(0x2040, 0x2900) }, | 45 | [PVR2_HDW_TYPE_29XXX] = { USB_DEVICE(0x2040, 0x2900) }, |
@@ -71,12 +75,10 @@ static const char *pvr2_client_29xxx[] = { | |||
71 | 75 | ||
72 | static struct pvr2_string_table pvr2_client_lists[] = { | 76 | static struct pvr2_string_table pvr2_client_lists[] = { |
73 | [PVR2_HDW_TYPE_29XXX] = { | 77 | [PVR2_HDW_TYPE_29XXX] = { |
74 | pvr2_client_29xxx, | 78 | pvr2_client_29xxx, ARRAY_SIZE(pvr2_client_29xxx) |
75 | sizeof(pvr2_client_29xxx)/sizeof(pvr2_client_29xxx[0]), | ||
76 | }, | 79 | }, |
77 | [PVR2_HDW_TYPE_24XXX] = { | 80 | [PVR2_HDW_TYPE_24XXX] = { |
78 | pvr2_client_24xxx, | 81 | pvr2_client_24xxx, ARRAY_SIZE(pvr2_client_24xxx) |
79 | sizeof(pvr2_client_24xxx)/sizeof(pvr2_client_24xxx[0]), | ||
80 | }, | 82 | }, |
81 | }; | 83 | }; |
82 | 84 | ||
@@ -160,9 +162,6 @@ static const struct pvr2_mpeg_ids mpeg_ids[] = { | |||
160 | .strid = "video_gop_closure", | 162 | .strid = "video_gop_closure", |
161 | .id = V4L2_CID_MPEG_VIDEO_GOP_CLOSURE, | 163 | .id = V4L2_CID_MPEG_VIDEO_GOP_CLOSURE, |
162 | },{ | 164 | },{ |
163 | .strid = "video_pulldown", | ||
164 | .id = V4L2_CID_MPEG_VIDEO_PULLDOWN, | ||
165 | },{ | ||
166 | .strid = "video_bitrate_mode", | 165 | .strid = "video_bitrate_mode", |
167 | .id = V4L2_CID_MPEG_VIDEO_BITRATE_MODE, | 166 | .id = V4L2_CID_MPEG_VIDEO_BITRATE_MODE, |
168 | },{ | 167 | },{ |
@@ -212,7 +211,7 @@ static const struct pvr2_mpeg_ids mpeg_ids[] = { | |||
212 | .id = V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM, | 211 | .id = V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM, |
213 | } | 212 | } |
214 | }; | 213 | }; |
215 | #define MPEGDEF_COUNT (sizeof(mpeg_ids)/sizeof(mpeg_ids[0])) | 214 | #define MPEGDEF_COUNT ARRAY_SIZE(mpeg_ids) |
216 | 215 | ||
217 | 216 | ||
218 | static const char *control_values_srate[] = { | 217 | static const char *control_values_srate[] = { |
@@ -255,10 +254,10 @@ static const char *control_values_subsystem[] = { | |||
255 | [PVR2_SUBSYS_B_ENC_RUN] = "enc_run", | 254 | [PVR2_SUBSYS_B_ENC_RUN] = "enc_run", |
256 | }; | 255 | }; |
257 | 256 | ||
257 | static void pvr2_hdw_set_cur_freq(struct pvr2_hdw *,unsigned long); | ||
258 | static int pvr2_hdw_cmd_usbstream(struct pvr2_hdw *hdw,int runFl); | 258 | static int pvr2_hdw_cmd_usbstream(struct pvr2_hdw *hdw,int runFl); |
259 | static int pvr2_hdw_commit_ctl_internal(struct pvr2_hdw *hdw); | 259 | static int pvr2_hdw_commit_ctl_internal(struct pvr2_hdw *hdw); |
260 | static int pvr2_hdw_get_eeprom_addr(struct pvr2_hdw *hdw); | 260 | static int pvr2_hdw_get_eeprom_addr(struct pvr2_hdw *hdw); |
261 | static unsigned int pvr2_hdw_get_signal_status_internal(struct pvr2_hdw *hdw); | ||
262 | static void pvr2_hdw_internal_find_stdenum(struct pvr2_hdw *hdw); | 261 | static void pvr2_hdw_internal_find_stdenum(struct pvr2_hdw *hdw); |
263 | static void pvr2_hdw_internal_set_std_avail(struct pvr2_hdw *hdw); | 262 | static void pvr2_hdw_internal_set_std_avail(struct pvr2_hdw *hdw); |
264 | static void pvr2_hdw_render_useless_unlocked(struct pvr2_hdw *hdw); | 263 | static void pvr2_hdw_render_useless_unlocked(struct pvr2_hdw *hdw); |
@@ -272,8 +271,6 @@ static int pvr2_send_request_ex(struct pvr2_hdw *hdw, | |||
272 | unsigned int timeout,int probe_fl, | 271 | unsigned int timeout,int probe_fl, |
273 | void *write_data,unsigned int write_len, | 272 | void *write_data,unsigned int write_len, |
274 | void *read_data,unsigned int read_len); | 273 | void *read_data,unsigned int read_len); |
275 | static int pvr2_write_u16(struct pvr2_hdw *hdw, u16 data, int res); | ||
276 | static int pvr2_write_u8(struct pvr2_hdw *hdw, u8 data, int res); | ||
277 | 274 | ||
278 | static int ctrl_channelfreq_get(struct pvr2_ctrl *cptr,int *vp) | 275 | static int ctrl_channelfreq_get(struct pvr2_ctrl *cptr,int *vp) |
279 | { | 276 | { |
@@ -289,8 +286,21 @@ static int ctrl_channelfreq_get(struct pvr2_ctrl *cptr,int *vp) | |||
289 | static int ctrl_channelfreq_set(struct pvr2_ctrl *cptr,int m,int v) | 286 | static int ctrl_channelfreq_set(struct pvr2_ctrl *cptr,int m,int v) |
290 | { | 287 | { |
291 | struct pvr2_hdw *hdw = cptr->hdw; | 288 | struct pvr2_hdw *hdw = cptr->hdw; |
292 | if ((hdw->freqProgSlot > 0) && (hdw->freqProgSlot <= FREQTABLE_SIZE)) { | 289 | unsigned int slotId = hdw->freqProgSlot; |
293 | hdw->freqTable[hdw->freqProgSlot-1] = v; | 290 | if ((slotId > 0) && (slotId <= FREQTABLE_SIZE)) { |
291 | hdw->freqTable[slotId-1] = v; | ||
292 | /* Handle side effects correctly - if we're tuned to this | ||
293 | slot, then forgot the slot id relation since the stored | ||
294 | frequency has been changed. */ | ||
295 | if (hdw->freqSelector) { | ||
296 | if (hdw->freqSlotRadio == slotId) { | ||
297 | hdw->freqSlotRadio = 0; | ||
298 | } | ||
299 | } else { | ||
300 | if (hdw->freqSlotTelevision == slotId) { | ||
301 | hdw->freqSlotTelevision = 0; | ||
302 | } | ||
303 | } | ||
294 | } | 304 | } |
295 | return 0; | 305 | return 0; |
296 | } | 306 | } |
@@ -312,28 +322,32 @@ static int ctrl_channelprog_set(struct pvr2_ctrl *cptr,int m,int v) | |||
312 | 322 | ||
313 | static int ctrl_channel_get(struct pvr2_ctrl *cptr,int *vp) | 323 | static int ctrl_channel_get(struct pvr2_ctrl *cptr,int *vp) |
314 | { | 324 | { |
315 | *vp = cptr->hdw->freqSlot; | 325 | struct pvr2_hdw *hdw = cptr->hdw; |
326 | *vp = hdw->freqSelector ? hdw->freqSlotRadio : hdw->freqSlotTelevision; | ||
316 | return 0; | 327 | return 0; |
317 | } | 328 | } |
318 | 329 | ||
319 | static int ctrl_channel_set(struct pvr2_ctrl *cptr,int m,int v) | 330 | static int ctrl_channel_set(struct pvr2_ctrl *cptr,int m,int slotId) |
320 | { | 331 | { |
321 | unsigned freq = 0; | 332 | unsigned freq = 0; |
322 | struct pvr2_hdw *hdw = cptr->hdw; | 333 | struct pvr2_hdw *hdw = cptr->hdw; |
323 | hdw->freqSlot = v; | 334 | if ((slotId < 0) || (slotId > FREQTABLE_SIZE)) return 0; |
324 | if ((hdw->freqSlot > 0) && (hdw->freqSlot <= FREQTABLE_SIZE)) { | 335 | if (slotId > 0) { |
325 | freq = hdw->freqTable[hdw->freqSlot-1]; | 336 | freq = hdw->freqTable[slotId-1]; |
326 | } | 337 | if (!freq) return 0; |
327 | if (freq && (freq != hdw->freqVal)) { | 338 | pvr2_hdw_set_cur_freq(hdw,freq); |
328 | hdw->freqVal = freq; | 339 | } |
329 | hdw->freqDirty = !0; | 340 | if (hdw->freqSelector) { |
341 | hdw->freqSlotRadio = slotId; | ||
342 | } else { | ||
343 | hdw->freqSlotTelevision = slotId; | ||
330 | } | 344 | } |
331 | return 0; | 345 | return 0; |
332 | } | 346 | } |
333 | 347 | ||
334 | static int ctrl_freq_get(struct pvr2_ctrl *cptr,int *vp) | 348 | static int ctrl_freq_get(struct pvr2_ctrl *cptr,int *vp) |
335 | { | 349 | { |
336 | *vp = cptr->hdw->freqVal; | 350 | *vp = pvr2_hdw_get_cur_freq(cptr->hdw); |
337 | return 0; | 351 | return 0; |
338 | } | 352 | } |
339 | 353 | ||
@@ -349,10 +363,7 @@ static void ctrl_freq_clear_dirty(struct pvr2_ctrl *cptr) | |||
349 | 363 | ||
350 | static int ctrl_freq_set(struct pvr2_ctrl *cptr,int m,int v) | 364 | static int ctrl_freq_set(struct pvr2_ctrl *cptr,int m,int v) |
351 | { | 365 | { |
352 | struct pvr2_hdw *hdw = cptr->hdw; | 366 | pvr2_hdw_set_cur_freq(cptr->hdw,v); |
353 | hdw->freqVal = v; | ||
354 | hdw->freqDirty = !0; | ||
355 | hdw->freqSlot = 0; | ||
356 | return 0; | 367 | return 0; |
357 | } | 368 | } |
358 | 369 | ||
@@ -378,6 +389,89 @@ static int ctrl_vres_min_get(struct pvr2_ctrl *cptr,int *vp) | |||
378 | return 0; | 389 | return 0; |
379 | } | 390 | } |
380 | 391 | ||
392 | static int ctrl_get_input(struct pvr2_ctrl *cptr,int *vp) | ||
393 | { | ||
394 | *vp = cptr->hdw->input_val; | ||
395 | return 0; | ||
396 | } | ||
397 | |||
398 | static int ctrl_set_input(struct pvr2_ctrl *cptr,int m,int v) | ||
399 | { | ||
400 | struct pvr2_hdw *hdw = cptr->hdw; | ||
401 | |||
402 | if (hdw->input_val != v) { | ||
403 | hdw->input_val = v; | ||
404 | hdw->input_dirty = !0; | ||
405 | } | ||
406 | |||
407 | /* Handle side effects - if we switch to a mode that needs the RF | ||
408 | tuner, then select the right frequency choice as well and mark | ||
409 | it dirty. */ | ||
410 | if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) { | ||
411 | hdw->freqSelector = 0; | ||
412 | hdw->freqDirty = !0; | ||
413 | } else if (hdw->input_val == PVR2_CVAL_INPUT_TV) { | ||
414 | hdw->freqSelector = 1; | ||
415 | hdw->freqDirty = !0; | ||
416 | } | ||
417 | return 0; | ||
418 | } | ||
419 | |||
420 | static int ctrl_isdirty_input(struct pvr2_ctrl *cptr) | ||
421 | { | ||
422 | return cptr->hdw->input_dirty != 0; | ||
423 | } | ||
424 | |||
425 | static void ctrl_cleardirty_input(struct pvr2_ctrl *cptr) | ||
426 | { | ||
427 | cptr->hdw->input_dirty = 0; | ||
428 | } | ||
429 | |||
430 | |||
431 | static int ctrl_freq_max_get(struct pvr2_ctrl *cptr, int *vp) | ||
432 | { | ||
433 | unsigned long fv; | ||
434 | struct pvr2_hdw *hdw = cptr->hdw; | ||
435 | if (hdw->tuner_signal_stale) { | ||
436 | pvr2_i2c_core_status_poll(hdw); | ||
437 | } | ||
438 | fv = hdw->tuner_signal_info.rangehigh; | ||
439 | if (!fv) { | ||
440 | /* Safety fallback */ | ||
441 | *vp = TV_MAX_FREQ; | ||
442 | return 0; | ||
443 | } | ||
444 | if (hdw->tuner_signal_info.capability & V4L2_TUNER_CAP_LOW) { | ||
445 | fv = (fv * 125) / 2; | ||
446 | } else { | ||
447 | fv = fv * 62500; | ||
448 | } | ||
449 | *vp = fv; | ||
450 | return 0; | ||
451 | } | ||
452 | |||
453 | static int ctrl_freq_min_get(struct pvr2_ctrl *cptr, int *vp) | ||
454 | { | ||
455 | unsigned long fv; | ||
456 | struct pvr2_hdw *hdw = cptr->hdw; | ||
457 | if (hdw->tuner_signal_stale) { | ||
458 | pvr2_i2c_core_status_poll(hdw); | ||
459 | } | ||
460 | fv = hdw->tuner_signal_info.rangelow; | ||
461 | if (!fv) { | ||
462 | /* Safety fallback */ | ||
463 | *vp = TV_MIN_FREQ; | ||
464 | return 0; | ||
465 | } | ||
466 | if (hdw->tuner_signal_info.capability & V4L2_TUNER_CAP_LOW) { | ||
467 | fv = (fv * 125) / 2; | ||
468 | } else { | ||
469 | fv = fv * 62500; | ||
470 | } | ||
471 | *vp = fv; | ||
472 | return 0; | ||
473 | } | ||
474 | |||
381 | static int ctrl_cx2341x_is_dirty(struct pvr2_ctrl *cptr) | 475 | static int ctrl_cx2341x_is_dirty(struct pvr2_ctrl *cptr) |
382 | { | 476 | { |
383 | return cptr->hdw->enc_stale != 0; | 477 | return cptr->hdw->enc_stale != 0; |
@@ -534,8 +628,32 @@ static void ctrl_stdcur_clear_dirty(struct pvr2_ctrl *cptr) | |||
534 | 628 | ||
535 | static int ctrl_signal_get(struct pvr2_ctrl *cptr,int *vp) | 629 | static int ctrl_signal_get(struct pvr2_ctrl *cptr,int *vp) |
536 | { | 630 | { |
537 | *vp = ((pvr2_hdw_get_signal_status_internal(cptr->hdw) & | 631 | struct pvr2_hdw *hdw = cptr->hdw; |
538 | PVR2_SIGNAL_OK) ? 1 : 0); | 632 | pvr2_i2c_core_status_poll(hdw); |
633 | *vp = hdw->tuner_signal_info.signal; | ||
634 | return 0; | ||
635 | } | ||
636 | |||
637 | static int ctrl_audio_modes_present_get(struct pvr2_ctrl *cptr,int *vp) | ||
638 | { | ||
639 | int val = 0; | ||
640 | unsigned int subchan; | ||
641 | struct pvr2_hdw *hdw = cptr->hdw; | ||
642 | pvr2_i2c_core_status_poll(hdw); | ||
643 | subchan = hdw->tuner_signal_info.rxsubchans; | ||
644 | if (subchan & V4L2_TUNER_SUB_MONO) { | ||
645 | val |= (1 << V4L2_TUNER_MODE_MONO); | ||
646 | } | ||
647 | if (subchan & V4L2_TUNER_SUB_STEREO) { | ||
648 | val |= (1 << V4L2_TUNER_MODE_STEREO); | ||
649 | } | ||
650 | if (subchan & V4L2_TUNER_SUB_LANG1) { | ||
651 | val |= (1 << V4L2_TUNER_MODE_LANG1); | ||
652 | } | ||
653 | if (subchan & V4L2_TUNER_SUB_LANG2) { | ||
654 | val |= (1 << V4L2_TUNER_MODE_LANG2); | ||
655 | } | ||
656 | *vp = val; | ||
539 | return 0; | 657 | return 0; |
540 | } | 658 | } |
541 | 659 | ||
@@ -604,7 +722,7 @@ static void ctrl_stdenumcur_clear_dirty(struct pvr2_ctrl *cptr) | |||
604 | 722 | ||
605 | #define DEFENUM(tab) \ | 723 | #define DEFENUM(tab) \ |
606 | .type = pvr2_ctl_enum, \ | 724 | .type = pvr2_ctl_enum, \ |
607 | .def.type_enum.count = (sizeof(tab)/sizeof((tab)[0])), \ | 725 | .def.type_enum.count = ARRAY_SIZE(tab), \ |
608 | .def.type_enum.value_names = tab | 726 | .def.type_enum.value_names = tab |
609 | 727 | ||
610 | #define DEFBOOL \ | 728 | #define DEFBOOL \ |
@@ -641,15 +759,11 @@ VCREATE_FUNCS(balance) | |||
641 | VCREATE_FUNCS(bass) | 759 | VCREATE_FUNCS(bass) |
642 | VCREATE_FUNCS(treble) | 760 | VCREATE_FUNCS(treble) |
643 | VCREATE_FUNCS(mute) | 761 | VCREATE_FUNCS(mute) |
644 | VCREATE_FUNCS(input) | ||
645 | VCREATE_FUNCS(audiomode) | 762 | VCREATE_FUNCS(audiomode) |
646 | VCREATE_FUNCS(res_hor) | 763 | VCREATE_FUNCS(res_hor) |
647 | VCREATE_FUNCS(res_ver) | 764 | VCREATE_FUNCS(res_ver) |
648 | VCREATE_FUNCS(srate) | 765 | VCREATE_FUNCS(srate) |
649 | 766 | ||
650 | #define MIN_FREQ 55250000L | ||
651 | #define MAX_FREQ 850000000L | ||
652 | |||
653 | /* Table definition of all controls which can be manipulated */ | 767 | /* Table definition of all controls which can be manipulated */ |
654 | static const struct pvr2_ctl_info control_defs[] = { | 768 | static const struct pvr2_ctl_info control_defs[] = { |
655 | { | 769 | { |
@@ -684,7 +798,7 @@ static const struct pvr2_ctl_info control_defs[] = { | |||
684 | .v4l_id = V4L2_CID_AUDIO_VOLUME, | 798 | .v4l_id = V4L2_CID_AUDIO_VOLUME, |
685 | .desc = "Volume", | 799 | .desc = "Volume", |
686 | .name = "volume", | 800 | .name = "volume", |
687 | .default_value = 65535, | 801 | .default_value = 62000, |
688 | DEFREF(volume), | 802 | DEFREF(volume), |
689 | DEFINT(0,65535), | 803 | DEFINT(0,65535), |
690 | },{ | 804 | },{ |
@@ -758,12 +872,16 @@ static const struct pvr2_ctl_info control_defs[] = { | |||
758 | .desc = "Tuner Frequency (Hz)", | 872 | .desc = "Tuner Frequency (Hz)", |
759 | .name = "frequency", | 873 | .name = "frequency", |
760 | .internal_id = PVR2_CID_FREQUENCY, | 874 | .internal_id = PVR2_CID_FREQUENCY, |
761 | .default_value = 175250000L, | 875 | .default_value = 0, |
762 | .set_value = ctrl_freq_set, | 876 | .set_value = ctrl_freq_set, |
763 | .get_value = ctrl_freq_get, | 877 | .get_value = ctrl_freq_get, |
764 | .is_dirty = ctrl_freq_is_dirty, | 878 | .is_dirty = ctrl_freq_is_dirty, |
765 | .clear_dirty = ctrl_freq_clear_dirty, | 879 | .clear_dirty = ctrl_freq_clear_dirty, |
766 | DEFINT(MIN_FREQ,MAX_FREQ), | 880 | DEFINT(0,0), |
881 | /* Hook in check for input value (tv/radio) and adjust | ||
882 | max/min values accordingly */ | ||
883 | .get_max_value = ctrl_freq_max_get, | ||
884 | .get_min_value = ctrl_freq_min_get, | ||
767 | },{ | 885 | },{ |
768 | .desc = "Channel", | 886 | .desc = "Channel", |
769 | .name = "channel", | 887 | .name = "channel", |
@@ -775,7 +893,11 @@ static const struct pvr2_ctl_info control_defs[] = { | |||
775 | .name = "freq_table_value", | 893 | .name = "freq_table_value", |
776 | .set_value = ctrl_channelfreq_set, | 894 | .set_value = ctrl_channelfreq_set, |
777 | .get_value = ctrl_channelfreq_get, | 895 | .get_value = ctrl_channelfreq_get, |
778 | DEFINT(MIN_FREQ,MAX_FREQ), | 896 | DEFINT(0,0), |
897 | /* Hook in check for input value (tv/radio) and adjust | ||
898 | max/min values accordingly */ | ||
899 | .get_max_value = ctrl_freq_max_get, | ||
900 | .get_min_value = ctrl_freq_min_get, | ||
779 | },{ | 901 | },{ |
780 | .desc = "Channel Program ID", | 902 | .desc = "Channel Program ID", |
781 | .name = "freq_table_channel", | 903 | .name = "freq_table_channel", |
@@ -796,7 +918,20 @@ static const struct pvr2_ctl_info control_defs[] = { | |||
796 | .desc = "Signal Present", | 918 | .desc = "Signal Present", |
797 | .name = "signal_present", | 919 | .name = "signal_present", |
798 | .get_value = ctrl_signal_get, | 920 | .get_value = ctrl_signal_get, |
799 | DEFBOOL, | 921 | DEFINT(0,65535), |
922 | },{ | ||
923 | .desc = "Audio Modes Present", | ||
924 | .name = "audio_modes_present", | ||
925 | .get_value = ctrl_audio_modes_present_get, | ||
926 | /* For this type we "borrow" the V4L2_TUNER_MODE enum from | ||
927 | v4l. Nothing outside of this module cares about this, | ||
928 | but I reuse it in order to also reuse the | ||
929 | control_values_audiomode string table. */ | ||
930 | DEFMASK(((1 << V4L2_TUNER_MODE_MONO)| | ||
931 | (1 << V4L2_TUNER_MODE_STEREO)| | ||
932 | (1 << V4L2_TUNER_MODE_LANG1)| | ||
933 | (1 << V4L2_TUNER_MODE_LANG2)), | ||
934 | control_values_audiomode), | ||
800 | },{ | 935 | },{ |
801 | .desc = "Video Standards Available Mask", | 936 | .desc = "Video Standards Available Mask", |
802 | .name = "video_standard_mask_available", | 937 | .name = "video_standard_mask_available", |
@@ -846,7 +981,7 @@ static const struct pvr2_ctl_info control_defs[] = { | |||
846 | } | 981 | } |
847 | }; | 982 | }; |
848 | 983 | ||
849 | #define CTRLDEF_COUNT (sizeof(control_defs)/sizeof(control_defs[0])) | 984 | #define CTRLDEF_COUNT ARRAY_SIZE(control_defs) |
850 | 985 | ||
851 | 986 | ||
852 | const char *pvr2_config_get_name(enum pvr2_config cfg) | 987 | const char *pvr2_config_get_name(enum pvr2_config cfg) |
@@ -855,7 +990,8 @@ const char *pvr2_config_get_name(enum pvr2_config cfg) | |||
855 | case pvr2_config_empty: return "empty"; | 990 | case pvr2_config_empty: return "empty"; |
856 | case pvr2_config_mpeg: return "mpeg"; | 991 | case pvr2_config_mpeg: return "mpeg"; |
857 | case pvr2_config_vbi: return "vbi"; | 992 | case pvr2_config_vbi: return "vbi"; |
858 | case pvr2_config_radio: return "radio"; | 993 | case pvr2_config_pcm: return "pcm"; |
994 | case pvr2_config_rawvideo: return "raw video"; | ||
859 | } | 995 | } |
860 | return "<unknown>"; | 996 | return "<unknown>"; |
861 | } | 997 | } |
@@ -872,6 +1008,40 @@ unsigned long pvr2_hdw_get_sn(struct pvr2_hdw *hdw) | |||
872 | return hdw->serial_number; | 1008 | return hdw->serial_number; |
873 | } | 1009 | } |
874 | 1010 | ||
1011 | unsigned long pvr2_hdw_get_cur_freq(struct pvr2_hdw *hdw) | ||
1012 | { | ||
1013 | return hdw->freqSelector ? hdw->freqValTelevision : hdw->freqValRadio; | ||
1014 | } | ||
1015 | |||
1016 | /* Set the currently tuned frequency and account for all possible | ||
1017 | driver-core side effects of this action. */ | ||
1018 | void pvr2_hdw_set_cur_freq(struct pvr2_hdw *hdw,unsigned long val) | ||
1019 | { | ||
1020 | if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) { | ||
1021 | if (hdw->freqSelector) { | ||
1022 | /* Swing over to radio frequency selection */ | ||
1023 | hdw->freqSelector = 0; | ||
1024 | hdw->freqDirty = !0; | ||
1025 | } | ||
1026 | if (hdw->freqValRadio != val) { | ||
1027 | hdw->freqValRadio = val; | ||
1028 | hdw->freqSlotRadio = 0; | ||
1029 | hdw->freqDirty = !0; | ||
1030 | } | ||
1031 | } else { | ||
1032 | if (!(hdw->freqSelector)) { | ||
1033 | /* Swing over to television frequency selection */ | ||
1034 | hdw->freqSelector = 1; | ||
1035 | hdw->freqDirty = !0; | ||
1036 | } | ||
1037 | if (hdw->freqValTelevision != val) { | ||
1038 | hdw->freqValTelevision = val; | ||
1039 | hdw->freqSlotTelevision = 0; | ||
1040 | hdw->freqDirty = !0; | ||
1041 | } | ||
1042 | } | ||
1043 | } | ||
1044 | |||
875 | int pvr2_hdw_get_unit_number(struct pvr2_hdw *hdw) | 1045 | int pvr2_hdw_get_unit_number(struct pvr2_hdw *hdw) |
876 | { | 1046 | { |
877 | return hdw->unit_number; | 1047 | return hdw->unit_number; |
@@ -960,12 +1130,10 @@ static int pvr2_upload_firmware1(struct pvr2_hdw *hdw) | |||
960 | }; | 1130 | }; |
961 | static const struct pvr2_string_table fw_file_defs[] = { | 1131 | static const struct pvr2_string_table fw_file_defs[] = { |
962 | [PVR2_HDW_TYPE_29XXX] = { | 1132 | [PVR2_HDW_TYPE_29XXX] = { |
963 | fw_files_29xxx, | 1133 | fw_files_29xxx, ARRAY_SIZE(fw_files_29xxx) |
964 | sizeof(fw_files_29xxx)/sizeof(fw_files_29xxx[0]), | ||
965 | }, | 1134 | }, |
966 | [PVR2_HDW_TYPE_24XXX] = { | 1135 | [PVR2_HDW_TYPE_24XXX] = { |
967 | fw_files_24xxx, | 1136 | fw_files_24xxx, ARRAY_SIZE(fw_files_24xxx) |
968 | sizeof(fw_files_24xxx)/sizeof(fw_files_24xxx[0]), | ||
969 | }, | 1137 | }, |
970 | }; | 1138 | }; |
971 | hdw->fw1_state = FW1_STATE_FAILED; // default result | 1139 | hdw->fw1_state = FW1_STATE_FAILED; // default result |
@@ -1041,7 +1209,7 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw) | |||
1041 | { | 1209 | { |
1042 | const struct firmware *fw_entry = NULL; | 1210 | const struct firmware *fw_entry = NULL; |
1043 | void *fw_ptr; | 1211 | void *fw_ptr; |
1044 | unsigned int pipe, fw_len, fw_done; | 1212 | unsigned int pipe, fw_len, fw_done, bcnt, icnt; |
1045 | int actual_length; | 1213 | int actual_length; |
1046 | int ret = 0; | 1214 | int ret = 0; |
1047 | int fwidx; | 1215 | int fwidx; |
@@ -1052,8 +1220,7 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw) | |||
1052 | trace_firmware("pvr2_upload_firmware2"); | 1220 | trace_firmware("pvr2_upload_firmware2"); |
1053 | 1221 | ||
1054 | ret = pvr2_locate_firmware(hdw,&fw_entry,"encoder", | 1222 | ret = pvr2_locate_firmware(hdw,&fw_entry,"encoder", |
1055 | sizeof(fw_files)/sizeof(fw_files[0]), | 1223 | ARRAY_SIZE(fw_files), fw_files); |
1056 | fw_files); | ||
1057 | if (ret < 0) return ret; | 1224 | if (ret < 0) return ret; |
1058 | fwidx = ret; | 1225 | fwidx = ret; |
1059 | ret = 0; | 1226 | ret = 0; |
@@ -1079,8 +1246,13 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw) | |||
1079 | ret |= pvr2_write_register(hdw, 0xaa04, 0x00057810); /*unknown*/ | 1246 | ret |= pvr2_write_register(hdw, 0xaa04, 0x00057810); /*unknown*/ |
1080 | ret |= pvr2_write_register(hdw, 0xaa10, 0x00148500); /*unknown*/ | 1247 | ret |= pvr2_write_register(hdw, 0xaa10, 0x00148500); /*unknown*/ |
1081 | ret |= pvr2_write_register(hdw, 0xaa18, 0x00840000); /*unknown*/ | 1248 | ret |= pvr2_write_register(hdw, 0xaa18, 0x00840000); /*unknown*/ |
1082 | ret |= pvr2_write_u8(hdw, 0x52, 0); | 1249 | LOCK_TAKE(hdw->ctl_lock); do { |
1083 | ret |= pvr2_write_u16(hdw, 0x0600, 0); | 1250 | hdw->cmd_buffer[0] = FX2CMD_FWPOST1; |
1251 | ret |= pvr2_send_request(hdw,hdw->cmd_buffer,1,0,0); | ||
1252 | hdw->cmd_buffer[0] = FX2CMD_MEMSEL; | ||
1253 | hdw->cmd_buffer[1] = 0; | ||
1254 | ret |= pvr2_send_request(hdw,hdw->cmd_buffer,2,0,0); | ||
1255 | } while (0); LOCK_GIVE(hdw->ctl_lock); | ||
1084 | 1256 | ||
1085 | if (ret) { | 1257 | if (ret) { |
1086 | pvr2_trace(PVR2_TRACE_ERROR_LEGS, | 1258 | pvr2_trace(PVR2_TRACE_ERROR_LEGS, |
@@ -1093,11 +1265,11 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw) | |||
1093 | 1265 | ||
1094 | fw_len = fw_entry->size; | 1266 | fw_len = fw_entry->size; |
1095 | 1267 | ||
1096 | if (fw_len % FIRMWARE_CHUNK_SIZE) { | 1268 | if (fw_len % sizeof(u32)) { |
1097 | pvr2_trace(PVR2_TRACE_ERROR_LEGS, | 1269 | pvr2_trace(PVR2_TRACE_ERROR_LEGS, |
1098 | "size of %s firmware" | 1270 | "size of %s firmware" |
1099 | " must be a multiple of 8192B", | 1271 | " must be a multiple of %u bytes", |
1100 | fw_files[fwidx]); | 1272 | fw_files[fwidx],sizeof(u32)); |
1101 | release_firmware(fw_entry); | 1273 | release_firmware(fw_entry); |
1102 | return -1; | 1274 | return -1; |
1103 | } | 1275 | } |
@@ -1112,18 +1284,21 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw) | |||
1112 | 1284 | ||
1113 | pipe = usb_sndbulkpipe(hdw->usb_dev, PVR2_FIRMWARE_ENDPOINT); | 1285 | pipe = usb_sndbulkpipe(hdw->usb_dev, PVR2_FIRMWARE_ENDPOINT); |
1114 | 1286 | ||
1115 | for (fw_done = 0 ; (fw_done < fw_len) && !ret ; | 1287 | fw_done = 0; |
1116 | fw_done += FIRMWARE_CHUNK_SIZE ) { | 1288 | for (fw_done = 0; fw_done < fw_len;) { |
1117 | int i; | 1289 | bcnt = fw_len - fw_done; |
1118 | memcpy(fw_ptr, fw_entry->data + fw_done, FIRMWARE_CHUNK_SIZE); | 1290 | if (bcnt > FIRMWARE_CHUNK_SIZE) bcnt = FIRMWARE_CHUNK_SIZE; |
1119 | /* Usbsnoop log shows that we must swap bytes... */ | 1291 | memcpy(fw_ptr, fw_entry->data + fw_done, bcnt); |
1120 | for (i = 0; i < FIRMWARE_CHUNK_SIZE/4 ; i++) | 1292 | /* Usbsnoop log shows that we must swap bytes... */ |
1121 | ((u32 *)fw_ptr)[i] = ___swab32(((u32 *)fw_ptr)[i]); | 1293 | for (icnt = 0; icnt < bcnt/4 ; icnt++) |
1122 | 1294 | ((u32 *)fw_ptr)[icnt] = | |
1123 | ret |= usb_bulk_msg(hdw->usb_dev, pipe, fw_ptr, | 1295 | ___swab32(((u32 *)fw_ptr)[icnt]); |
1124 | FIRMWARE_CHUNK_SIZE, | 1296 | |
1297 | ret |= usb_bulk_msg(hdw->usb_dev, pipe, fw_ptr,bcnt, | ||
1125 | &actual_length, HZ); | 1298 | &actual_length, HZ); |
1126 | ret |= (actual_length != FIRMWARE_CHUNK_SIZE); | 1299 | ret |= (actual_length != bcnt); |
1300 | if (ret) break; | ||
1301 | fw_done += bcnt; | ||
1127 | } | 1302 | } |
1128 | 1303 | ||
1129 | trace_firmware("upload of %s : %i / %i ", | 1304 | trace_firmware("upload of %s : %i / %i ", |
@@ -1142,7 +1317,11 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw) | |||
1142 | 1317 | ||
1143 | ret |= pvr2_write_register(hdw, 0x9054, 0xffffffff); /*reset hw blocks*/ | 1318 | ret |= pvr2_write_register(hdw, 0x9054, 0xffffffff); /*reset hw blocks*/ |
1144 | ret |= pvr2_write_register(hdw, 0x9058, 0xffffffe8); /*VPU ctrl*/ | 1319 | ret |= pvr2_write_register(hdw, 0x9058, 0xffffffe8); /*VPU ctrl*/ |
1145 | ret |= pvr2_write_u16(hdw, 0x0600, 0); | 1320 | LOCK_TAKE(hdw->ctl_lock); do { |
1321 | hdw->cmd_buffer[0] = FX2CMD_MEMSEL; | ||
1322 | hdw->cmd_buffer[1] = 0; | ||
1323 | ret |= pvr2_send_request(hdw,hdw->cmd_buffer,2,0,0); | ||
1324 | } while (0); LOCK_GIVE(hdw->ctl_lock); | ||
1146 | 1325 | ||
1147 | if (ret) { | 1326 | if (ret) { |
1148 | pvr2_trace(PVR2_TRACE_ERROR_LEGS, | 1327 | pvr2_trace(PVR2_TRACE_ERROR_LEGS, |
@@ -1479,7 +1658,7 @@ static int pvr2_hdw_check_firmware(struct pvr2_hdw *hdw) | |||
1479 | firmware needs be loaded. */ | 1658 | firmware needs be loaded. */ |
1480 | int result; | 1659 | int result; |
1481 | LOCK_TAKE(hdw->ctl_lock); do { | 1660 | LOCK_TAKE(hdw->ctl_lock); do { |
1482 | hdw->cmd_buffer[0] = 0xeb; | 1661 | hdw->cmd_buffer[0] = FX2CMD_GET_EEPROM_ADDR; |
1483 | result = pvr2_send_request_ex(hdw,HZ*1,!0, | 1662 | result = pvr2_send_request_ex(hdw,HZ*1,!0, |
1484 | hdw->cmd_buffer,1, | 1663 | hdw->cmd_buffer,1, |
1485 | hdw->cmd_buffer,1); | 1664 | hdw->cmd_buffer,1); |
@@ -1611,6 +1790,16 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw) | |||
1611 | cptr->info->set_value(cptr,~0,cptr->info->default_value); | 1790 | cptr->info->set_value(cptr,~0,cptr->info->default_value); |
1612 | } | 1791 | } |
1613 | 1792 | ||
1793 | /* Set up special default values for the television and radio | ||
1794 | frequencies here. It's not really important what these defaults | ||
1795 | are, but I set them to something usable in the Chicago area just | ||
1796 | to make driver testing a little easier. */ | ||
1797 | |||
1798 | /* US Broadcast channel 7 (175.25 MHz) */ | ||
1799 | hdw->freqValTelevision = 175250000L; | ||
1800 | /* 104.3 MHz, a usable FM station for my area */ | ||
1801 | hdw->freqValRadio = 104300000L; | ||
1802 | |||
1614 | // Do not use pvr2_reset_ctl_endpoints() here. It is not | 1803 | // Do not use pvr2_reset_ctl_endpoints() here. It is not |
1615 | // thread-safe against the normal pvr2_send_request() mechanism. | 1804 | // thread-safe against the normal pvr2_send_request() mechanism. |
1616 | // (We should make it thread safe). | 1805 | // (We should make it thread safe). |
@@ -1750,26 +1939,24 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, | |||
1750 | struct pvr2_ctl_info *ciptr; | 1939 | struct pvr2_ctl_info *ciptr; |
1751 | 1940 | ||
1752 | hdw_type = devid - pvr2_device_table; | 1941 | hdw_type = devid - pvr2_device_table; |
1753 | if (hdw_type >= | 1942 | if (hdw_type >= ARRAY_SIZE(pvr2_device_names)) { |
1754 | sizeof(pvr2_device_names)/sizeof(pvr2_device_names[0])) { | ||
1755 | pvr2_trace(PVR2_TRACE_ERROR_LEGS, | 1943 | pvr2_trace(PVR2_TRACE_ERROR_LEGS, |
1756 | "Bogus device type of %u reported",hdw_type); | 1944 | "Bogus device type of %u reported",hdw_type); |
1757 | return NULL; | 1945 | return NULL; |
1758 | } | 1946 | } |
1759 | 1947 | ||
1760 | hdw = kmalloc(sizeof(*hdw),GFP_KERNEL); | 1948 | hdw = kzalloc(sizeof(*hdw),GFP_KERNEL); |
1761 | pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_create: hdw=%p, type \"%s\"", | 1949 | pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_create: hdw=%p, type \"%s\"", |
1762 | hdw,pvr2_device_names[hdw_type]); | 1950 | hdw,pvr2_device_names[hdw_type]); |
1763 | if (!hdw) goto fail; | 1951 | if (!hdw) goto fail; |
1764 | memset(hdw,0,sizeof(*hdw)); | 1952 | hdw->tuner_signal_stale = !0; |
1765 | cx2341x_fill_defaults(&hdw->enc_ctl_state); | 1953 | cx2341x_fill_defaults(&hdw->enc_ctl_state); |
1766 | 1954 | ||
1767 | hdw->control_cnt = CTRLDEF_COUNT; | 1955 | hdw->control_cnt = CTRLDEF_COUNT; |
1768 | hdw->control_cnt += MPEGDEF_COUNT; | 1956 | hdw->control_cnt += MPEGDEF_COUNT; |
1769 | hdw->controls = kmalloc(sizeof(struct pvr2_ctrl) * hdw->control_cnt, | 1957 | hdw->controls = kzalloc(sizeof(struct pvr2_ctrl) * hdw->control_cnt, |
1770 | GFP_KERNEL); | 1958 | GFP_KERNEL); |
1771 | if (!hdw->controls) goto fail; | 1959 | if (!hdw->controls) goto fail; |
1772 | memset(hdw->controls,0,sizeof(struct pvr2_ctrl) * hdw->control_cnt); | ||
1773 | hdw->hdw_type = hdw_type; | 1960 | hdw->hdw_type = hdw_type; |
1774 | for (idx = 0; idx < hdw->control_cnt; idx++) { | 1961 | for (idx = 0; idx < hdw->control_cnt; idx++) { |
1775 | cptr = hdw->controls + idx; | 1962 | cptr = hdw->controls + idx; |
@@ -1783,11 +1970,9 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, | |||
1783 | cptr->info = control_defs+idx; | 1970 | cptr->info = control_defs+idx; |
1784 | } | 1971 | } |
1785 | /* Define and configure additional controls from cx2341x module. */ | 1972 | /* Define and configure additional controls from cx2341x module. */ |
1786 | hdw->mpeg_ctrl_info = kmalloc( | 1973 | hdw->mpeg_ctrl_info = kzalloc( |
1787 | sizeof(*(hdw->mpeg_ctrl_info)) * MPEGDEF_COUNT, GFP_KERNEL); | 1974 | sizeof(*(hdw->mpeg_ctrl_info)) * MPEGDEF_COUNT, GFP_KERNEL); |
1788 | if (!hdw->mpeg_ctrl_info) goto fail; | 1975 | if (!hdw->mpeg_ctrl_info) goto fail; |
1789 | memset(hdw->mpeg_ctrl_info,0, | ||
1790 | sizeof(*(hdw->mpeg_ctrl_info)) * MPEGDEF_COUNT); | ||
1791 | for (idx = 0; idx < MPEGDEF_COUNT; idx++) { | 1976 | for (idx = 0; idx < MPEGDEF_COUNT; idx++) { |
1792 | cptr = hdw->controls + idx + CTRLDEF_COUNT; | 1977 | cptr = hdw->controls + idx + CTRLDEF_COUNT; |
1793 | ciptr = &(hdw->mpeg_ctrl_info[idx].info); | 1978 | ciptr = &(hdw->mpeg_ctrl_info[idx].info); |
@@ -1872,7 +2057,9 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, | |||
1872 | 2057 | ||
1873 | hdw->eeprom_addr = -1; | 2058 | hdw->eeprom_addr = -1; |
1874 | hdw->unit_number = -1; | 2059 | hdw->unit_number = -1; |
1875 | hdw->v4l_minor_number = -1; | 2060 | hdw->v4l_minor_number_video = -1; |
2061 | hdw->v4l_minor_number_vbi = -1; | ||
2062 | hdw->v4l_minor_number_radio = -1; | ||
1876 | hdw->ctl_write_buffer = kmalloc(PVR2_CTL_BUFFSIZE,GFP_KERNEL); | 2063 | hdw->ctl_write_buffer = kmalloc(PVR2_CTL_BUFFSIZE,GFP_KERNEL); |
1877 | if (!hdw->ctl_write_buffer) goto fail; | 2064 | if (!hdw->ctl_write_buffer) goto fail; |
1878 | hdw->ctl_read_buffer = kmalloc(PVR2_CTL_BUFFSIZE,GFP_KERNEL); | 2065 | hdw->ctl_read_buffer = kmalloc(PVR2_CTL_BUFFSIZE,GFP_KERNEL); |
@@ -1929,10 +2116,10 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, | |||
1929 | if (hdw) { | 2116 | if (hdw) { |
1930 | usb_free_urb(hdw->ctl_read_urb); | 2117 | usb_free_urb(hdw->ctl_read_urb); |
1931 | usb_free_urb(hdw->ctl_write_urb); | 2118 | usb_free_urb(hdw->ctl_write_urb); |
1932 | if (hdw->ctl_read_buffer) kfree(hdw->ctl_read_buffer); | 2119 | kfree(hdw->ctl_read_buffer); |
1933 | if (hdw->ctl_write_buffer) kfree(hdw->ctl_write_buffer); | 2120 | kfree(hdw->ctl_write_buffer); |
1934 | if (hdw->controls) kfree(hdw->controls); | 2121 | kfree(hdw->controls); |
1935 | if (hdw->mpeg_ctrl_info) kfree(hdw->mpeg_ctrl_info); | 2122 | kfree(hdw->mpeg_ctrl_info); |
1936 | kfree(hdw); | 2123 | kfree(hdw); |
1937 | } | 2124 | } |
1938 | return NULL; | 2125 | return NULL; |
@@ -1982,9 +2169,6 @@ void pvr2_hdw_destroy(struct pvr2_hdw *hdw) | |||
1982 | pvr2_stream_destroy(hdw->vid_stream); | 2169 | pvr2_stream_destroy(hdw->vid_stream); |
1983 | hdw->vid_stream = NULL; | 2170 | hdw->vid_stream = NULL; |
1984 | } | 2171 | } |
1985 | if (hdw->audio_stat) { | ||
1986 | hdw->audio_stat->detach(hdw->audio_stat->ctxt); | ||
1987 | } | ||
1988 | if (hdw->decoder_ctrl) { | 2172 | if (hdw->decoder_ctrl) { |
1989 | hdw->decoder_ctrl->detach(hdw->decoder_ctrl->ctxt); | 2173 | hdw->decoder_ctrl->detach(hdw->decoder_ctrl->ctxt); |
1990 | } | 2174 | } |
@@ -1997,10 +2181,10 @@ void pvr2_hdw_destroy(struct pvr2_hdw *hdw) | |||
1997 | unit_pointers[hdw->unit_number] = NULL; | 2181 | unit_pointers[hdw->unit_number] = NULL; |
1998 | } | 2182 | } |
1999 | } while (0); up(&pvr2_unit_sem); | 2183 | } while (0); up(&pvr2_unit_sem); |
2000 | if (hdw->controls) kfree(hdw->controls); | 2184 | kfree(hdw->controls); |
2001 | if (hdw->mpeg_ctrl_info) kfree(hdw->mpeg_ctrl_info); | 2185 | kfree(hdw->mpeg_ctrl_info); |
2002 | if (hdw->std_defs) kfree(hdw->std_defs); | 2186 | kfree(hdw->std_defs); |
2003 | if (hdw->std_enum_names) kfree(hdw->std_enum_names); | 2187 | kfree(hdw->std_enum_names); |
2004 | kfree(hdw); | 2188 | kfree(hdw); |
2005 | } | 2189 | } |
2006 | 2190 | ||
@@ -2210,10 +2394,9 @@ static int pvr2_hdw_commit_ctl_internal(struct pvr2_hdw *hdw) | |||
2210 | cptr = hdw->controls + idx; | 2394 | cptr = hdw->controls + idx; |
2211 | if (cptr->info->is_dirty == 0) continue; | 2395 | if (cptr->info->is_dirty == 0) continue; |
2212 | if (!cptr->info->is_dirty(cptr)) continue; | 2396 | if (!cptr->info->is_dirty(cptr)) continue; |
2213 | if (!commit_flag) { | 2397 | commit_flag = !0; |
2214 | commit_flag = !0; | ||
2215 | } | ||
2216 | 2398 | ||
2399 | if (!(pvrusb2_debug & PVR2_TRACE_CTL)) continue; | ||
2217 | bcnt = scnprintf(buf,sizeof(buf),"\"%s\" <-- ", | 2400 | bcnt = scnprintf(buf,sizeof(buf),"\"%s\" <-- ", |
2218 | cptr->info->name); | 2401 | cptr->info->name); |
2219 | value = 0; | 2402 | value = 0; |
@@ -2263,6 +2446,13 @@ static int pvr2_hdw_commit_ctl_internal(struct pvr2_hdw *hdw) | |||
2263 | stale_subsys_mask |= (1<<PVR2_SUBSYS_B_ENC_CFG); | 2446 | stale_subsys_mask |= (1<<PVR2_SUBSYS_B_ENC_CFG); |
2264 | } | 2447 | } |
2265 | 2448 | ||
2449 | if (hdw->input_dirty) { | ||
2450 | /* pk: If input changes to or from radio, then the encoder | ||
2451 | needs to be restarted (for ENC_MUTE_VIDEO to work) */ | ||
2452 | stale_subsys_mask |= (1<<PVR2_SUBSYS_B_ENC_RUN); | ||
2453 | } | ||
2454 | |||
2455 | |||
2266 | if (hdw->srate_dirty) { | 2456 | if (hdw->srate_dirty) { |
2267 | /* Write new sample rate into control structure since | 2457 | /* Write new sample rate into control structure since |
2268 | * the master copy is stale. We must track srate | 2458 | * the master copy is stale. We must track srate |
@@ -2343,39 +2533,11 @@ const char *pvr2_hdw_get_driver_name(struct pvr2_hdw *hdw) | |||
2343 | } | 2533 | } |
2344 | 2534 | ||
2345 | 2535 | ||
2346 | /* Return bit mask indicating signal status */ | ||
2347 | static unsigned int pvr2_hdw_get_signal_status_internal(struct pvr2_hdw *hdw) | ||
2348 | { | ||
2349 | unsigned int msk = 0; | ||
2350 | switch (hdw->input_val) { | ||
2351 | case PVR2_CVAL_INPUT_TV: | ||
2352 | case PVR2_CVAL_INPUT_RADIO: | ||
2353 | if (hdw->decoder_ctrl && | ||
2354 | hdw->decoder_ctrl->tuned(hdw->decoder_ctrl->ctxt)) { | ||
2355 | msk |= PVR2_SIGNAL_OK; | ||
2356 | if (hdw->audio_stat && | ||
2357 | hdw->audio_stat->status(hdw->audio_stat->ctxt)) { | ||
2358 | if (hdw->flag_stereo) { | ||
2359 | msk |= PVR2_SIGNAL_STEREO; | ||
2360 | } | ||
2361 | if (hdw->flag_bilingual) { | ||
2362 | msk |= PVR2_SIGNAL_SAP; | ||
2363 | } | ||
2364 | } | ||
2365 | } | ||
2366 | break; | ||
2367 | default: | ||
2368 | msk |= PVR2_SIGNAL_OK | PVR2_SIGNAL_STEREO; | ||
2369 | } | ||
2370 | return msk; | ||
2371 | } | ||
2372 | |||
2373 | |||
2374 | int pvr2_hdw_is_hsm(struct pvr2_hdw *hdw) | 2536 | int pvr2_hdw_is_hsm(struct pvr2_hdw *hdw) |
2375 | { | 2537 | { |
2376 | int result; | 2538 | int result; |
2377 | LOCK_TAKE(hdw->ctl_lock); do { | 2539 | LOCK_TAKE(hdw->ctl_lock); do { |
2378 | hdw->cmd_buffer[0] = 0x0b; | 2540 | hdw->cmd_buffer[0] = FX2CMD_GET_USB_SPEED; |
2379 | result = pvr2_send_request(hdw, | 2541 | result = pvr2_send_request(hdw, |
2380 | hdw->cmd_buffer,1, | 2542 | hdw->cmd_buffer,1, |
2381 | hdw->cmd_buffer,1); | 2543 | hdw->cmd_buffer,1); |
@@ -2386,14 +2548,25 @@ int pvr2_hdw_is_hsm(struct pvr2_hdw *hdw) | |||
2386 | } | 2548 | } |
2387 | 2549 | ||
2388 | 2550 | ||
2389 | /* Return bit mask indicating signal status */ | 2551 | /* Execute poll of tuner status */ |
2390 | unsigned int pvr2_hdw_get_signal_status(struct pvr2_hdw *hdw) | 2552 | void pvr2_hdw_execute_tuner_poll(struct pvr2_hdw *hdw) |
2391 | { | 2553 | { |
2392 | unsigned int msk = 0; | ||
2393 | LOCK_TAKE(hdw->big_lock); do { | 2554 | LOCK_TAKE(hdw->big_lock); do { |
2394 | msk = pvr2_hdw_get_signal_status_internal(hdw); | 2555 | pvr2_i2c_core_status_poll(hdw); |
2395 | } while (0); LOCK_GIVE(hdw->big_lock); | 2556 | } while (0); LOCK_GIVE(hdw->big_lock); |
2396 | return msk; | 2557 | } |
2558 | |||
2559 | |||
2560 | /* Return information about the tuner */ | ||
2561 | int pvr2_hdw_get_tuner_status(struct pvr2_hdw *hdw,struct v4l2_tuner *vtp) | ||
2562 | { | ||
2563 | LOCK_TAKE(hdw->big_lock); do { | ||
2564 | if (hdw->tuner_signal_stale) { | ||
2565 | pvr2_i2c_core_status_poll(hdw); | ||
2566 | } | ||
2567 | memcpy(vtp,&hdw->tuner_signal_info,sizeof(struct v4l2_tuner)); | ||
2568 | } while (0); LOCK_GIVE(hdw->big_lock); | ||
2569 | return 0; | ||
2397 | } | 2570 | } |
2398 | 2571 | ||
2399 | 2572 | ||
@@ -2442,14 +2615,12 @@ void pvr2_hdw_cpufw_set_enabled(struct pvr2_hdw *hdw, int enable_flag) | |||
2442 | pvr2_trace(PVR2_TRACE_FIRMWARE, | 2615 | pvr2_trace(PVR2_TRACE_FIRMWARE, |
2443 | "Preparing to suck out CPU firmware"); | 2616 | "Preparing to suck out CPU firmware"); |
2444 | hdw->fw_size = 0x2000; | 2617 | hdw->fw_size = 0x2000; |
2445 | hdw->fw_buffer = kmalloc(hdw->fw_size,GFP_KERNEL); | 2618 | hdw->fw_buffer = kzalloc(hdw->fw_size,GFP_KERNEL); |
2446 | if (!hdw->fw_buffer) { | 2619 | if (!hdw->fw_buffer) { |
2447 | hdw->fw_size = 0; | 2620 | hdw->fw_size = 0; |
2448 | break; | 2621 | break; |
2449 | } | 2622 | } |
2450 | 2623 | ||
2451 | memset(hdw->fw_buffer,0,hdw->fw_size); | ||
2452 | |||
2453 | /* We have to hold the CPU during firmware upload. */ | 2624 | /* We have to hold the CPU during firmware upload. */ |
2454 | pvr2_hdw_cpureset_assert(hdw,1); | 2625 | pvr2_hdw_cpureset_assert(hdw,1); |
2455 | 2626 | ||
@@ -2513,16 +2684,28 @@ int pvr2_hdw_cpufw_get(struct pvr2_hdw *hdw,unsigned int offs, | |||
2513 | } | 2684 | } |
2514 | 2685 | ||
2515 | 2686 | ||
2516 | int pvr2_hdw_v4l_get_minor_number(struct pvr2_hdw *hdw) | 2687 | int pvr2_hdw_v4l_get_minor_number(struct pvr2_hdw *hdw, |
2688 | enum pvr2_v4l_type index) | ||
2517 | { | 2689 | { |
2518 | return hdw->v4l_minor_number; | 2690 | switch (index) { |
2691 | case pvr2_v4l_type_video: return hdw->v4l_minor_number_video; | ||
2692 | case pvr2_v4l_type_vbi: return hdw->v4l_minor_number_vbi; | ||
2693 | case pvr2_v4l_type_radio: return hdw->v4l_minor_number_radio; | ||
2694 | default: return -1; | ||
2695 | } | ||
2519 | } | 2696 | } |
2520 | 2697 | ||
2521 | 2698 | ||
2522 | /* Store the v4l minor device number */ | 2699 | /* Store a v4l minor device number */ |
2523 | void pvr2_hdw_v4l_store_minor_number(struct pvr2_hdw *hdw,int v) | 2700 | void pvr2_hdw_v4l_store_minor_number(struct pvr2_hdw *hdw, |
2701 | enum pvr2_v4l_type index,int v) | ||
2524 | { | 2702 | { |
2525 | hdw->v4l_minor_number = v; | 2703 | switch (index) { |
2704 | case pvr2_v4l_type_video: hdw->v4l_minor_number_video = v; | ||
2705 | case pvr2_v4l_type_vbi: hdw->v4l_minor_number_vbi = v; | ||
2706 | case pvr2_v4l_type_radio: hdw->v4l_minor_number_radio = v; | ||
2707 | default: break; | ||
2708 | } | ||
2526 | } | 2709 | } |
2527 | 2710 | ||
2528 | 2711 | ||
@@ -2804,7 +2987,7 @@ int pvr2_write_register(struct pvr2_hdw *hdw, u16 reg, u32 data) | |||
2804 | 2987 | ||
2805 | LOCK_TAKE(hdw->ctl_lock); | 2988 | LOCK_TAKE(hdw->ctl_lock); |
2806 | 2989 | ||
2807 | hdw->cmd_buffer[0] = 0x04; /* write register prefix */ | 2990 | hdw->cmd_buffer[0] = FX2CMD_REG_WRITE; /* write register prefix */ |
2808 | PVR2_DECOMPOSE_LE(hdw->cmd_buffer,1,data); | 2991 | PVR2_DECOMPOSE_LE(hdw->cmd_buffer,1,data); |
2809 | hdw->cmd_buffer[5] = 0; | 2992 | hdw->cmd_buffer[5] = 0; |
2810 | hdw->cmd_buffer[6] = (reg >> 8) & 0xff; | 2993 | hdw->cmd_buffer[6] = (reg >> 8) & 0xff; |
@@ -2825,7 +3008,7 @@ static int pvr2_read_register(struct pvr2_hdw *hdw, u16 reg, u32 *data) | |||
2825 | 3008 | ||
2826 | LOCK_TAKE(hdw->ctl_lock); | 3009 | LOCK_TAKE(hdw->ctl_lock); |
2827 | 3010 | ||
2828 | hdw->cmd_buffer[0] = 0x05; /* read register prefix */ | 3011 | hdw->cmd_buffer[0] = FX2CMD_REG_READ; /* read register prefix */ |
2829 | hdw->cmd_buffer[1] = 0; | 3012 | hdw->cmd_buffer[1] = 0; |
2830 | hdw->cmd_buffer[2] = 0; | 3013 | hdw->cmd_buffer[2] = 0; |
2831 | hdw->cmd_buffer[3] = 0; | 3014 | hdw->cmd_buffer[3] = 0; |
@@ -2843,39 +3026,6 @@ static int pvr2_read_register(struct pvr2_hdw *hdw, u16 reg, u32 *data) | |||
2843 | } | 3026 | } |
2844 | 3027 | ||
2845 | 3028 | ||
2846 | static int pvr2_write_u16(struct pvr2_hdw *hdw, u16 data, int res) | ||
2847 | { | ||
2848 | int ret; | ||
2849 | |||
2850 | LOCK_TAKE(hdw->ctl_lock); | ||
2851 | |||
2852 | hdw->cmd_buffer[0] = (data >> 8) & 0xff; | ||
2853 | hdw->cmd_buffer[1] = data & 0xff; | ||
2854 | |||
2855 | ret = pvr2_send_request(hdw, hdw->cmd_buffer, 2, hdw->cmd_buffer, res); | ||
2856 | |||
2857 | LOCK_GIVE(hdw->ctl_lock); | ||
2858 | |||
2859 | return ret; | ||
2860 | } | ||
2861 | |||
2862 | |||
2863 | static int pvr2_write_u8(struct pvr2_hdw *hdw, u8 data, int res) | ||
2864 | { | ||
2865 | int ret; | ||
2866 | |||
2867 | LOCK_TAKE(hdw->ctl_lock); | ||
2868 | |||
2869 | hdw->cmd_buffer[0] = data; | ||
2870 | |||
2871 | ret = pvr2_send_request(hdw, hdw->cmd_buffer, 1, hdw->cmd_buffer, res); | ||
2872 | |||
2873 | LOCK_GIVE(hdw->ctl_lock); | ||
2874 | |||
2875 | return ret; | ||
2876 | } | ||
2877 | |||
2878 | |||
2879 | static void pvr2_hdw_render_useless_unlocked(struct pvr2_hdw *hdw) | 3029 | static void pvr2_hdw_render_useless_unlocked(struct pvr2_hdw *hdw) |
2880 | { | 3030 | { |
2881 | if (!hdw->flag_ok) return; | 3031 | if (!hdw->flag_ok) return; |
@@ -2949,7 +3099,7 @@ int pvr2_hdw_cmd_deep_reset(struct pvr2_hdw *hdw) | |||
2949 | LOCK_TAKE(hdw->ctl_lock); do { | 3099 | LOCK_TAKE(hdw->ctl_lock); do { |
2950 | pvr2_trace(PVR2_TRACE_INIT,"Requesting uproc hard reset"); | 3100 | pvr2_trace(PVR2_TRACE_INIT,"Requesting uproc hard reset"); |
2951 | hdw->flag_ok = !0; | 3101 | hdw->flag_ok = !0; |
2952 | hdw->cmd_buffer[0] = 0xdd; | 3102 | hdw->cmd_buffer[0] = FX2CMD_DEEP_RESET; |
2953 | status = pvr2_send_request(hdw,hdw->cmd_buffer,1,NULL,0); | 3103 | status = pvr2_send_request(hdw,hdw->cmd_buffer,1,NULL,0); |
2954 | } while (0); LOCK_GIVE(hdw->ctl_lock); | 3104 | } while (0); LOCK_GIVE(hdw->ctl_lock); |
2955 | return status; | 3105 | return status; |
@@ -2961,7 +3111,7 @@ int pvr2_hdw_cmd_powerup(struct pvr2_hdw *hdw) | |||
2961 | int status; | 3111 | int status; |
2962 | LOCK_TAKE(hdw->ctl_lock); do { | 3112 | LOCK_TAKE(hdw->ctl_lock); do { |
2963 | pvr2_trace(PVR2_TRACE_INIT,"Requesting powerup"); | 3113 | pvr2_trace(PVR2_TRACE_INIT,"Requesting powerup"); |
2964 | hdw->cmd_buffer[0] = 0xde; | 3114 | hdw->cmd_buffer[0] = FX2CMD_POWER_ON; |
2965 | status = pvr2_send_request(hdw,hdw->cmd_buffer,1,NULL,0); | 3115 | status = pvr2_send_request(hdw,hdw->cmd_buffer,1,NULL,0); |
2966 | } while (0); LOCK_GIVE(hdw->ctl_lock); | 3116 | } while (0); LOCK_GIVE(hdw->ctl_lock); |
2967 | return status; | 3117 | return status; |
@@ -2994,7 +3144,8 @@ static int pvr2_hdw_cmd_usbstream(struct pvr2_hdw *hdw,int runFl) | |||
2994 | { | 3144 | { |
2995 | int status; | 3145 | int status; |
2996 | LOCK_TAKE(hdw->ctl_lock); do { | 3146 | LOCK_TAKE(hdw->ctl_lock); do { |
2997 | hdw->cmd_buffer[0] = (runFl ? 0x36 : 0x37); | 3147 | hdw->cmd_buffer[0] = |
3148 | (runFl ? FX2CMD_STREAMING_ON : FX2CMD_STREAMING_OFF); | ||
2998 | status = pvr2_send_request(hdw,hdw->cmd_buffer,1,NULL,0); | 3149 | status = pvr2_send_request(hdw,hdw->cmd_buffer,1,NULL,0); |
2999 | } while (0); LOCK_GIVE(hdw->ctl_lock); | 3150 | } while (0); LOCK_GIVE(hdw->ctl_lock); |
3000 | if (!status) { | 3151 | if (!status) { |
@@ -3093,7 +3244,7 @@ static int pvr2_hdw_get_eeprom_addr(struct pvr2_hdw *hdw) | |||
3093 | { | 3244 | { |
3094 | int result; | 3245 | int result; |
3095 | LOCK_TAKE(hdw->ctl_lock); do { | 3246 | LOCK_TAKE(hdw->ctl_lock); do { |
3096 | hdw->cmd_buffer[0] = 0xeb; | 3247 | hdw->cmd_buffer[0] = FX2CMD_GET_EEPROM_ADDR; |
3097 | result = pvr2_send_request(hdw, | 3248 | result = pvr2_send_request(hdw, |
3098 | hdw->cmd_buffer,1, | 3249 | hdw->cmd_buffer,1, |
3099 | hdw->cmd_buffer,1); | 3250 | hdw->cmd_buffer,1); |
@@ -3105,7 +3256,7 @@ static int pvr2_hdw_get_eeprom_addr(struct pvr2_hdw *hdw) | |||
3105 | 3256 | ||
3106 | 3257 | ||
3107 | int pvr2_hdw_register_access(struct pvr2_hdw *hdw, | 3258 | int pvr2_hdw_register_access(struct pvr2_hdw *hdw, |
3108 | u32 chip_id,unsigned long reg_id, | 3259 | u32 chip_id, u64 reg_id, |
3109 | int setFl,u32 *val_ptr) | 3260 | int setFl,u32 *val_ptr) |
3110 | { | 3261 | { |
3111 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 3262 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
@@ -3115,6 +3266,8 @@ int pvr2_hdw_register_access(struct pvr2_hdw *hdw, | |||
3115 | int stat = 0; | 3266 | int stat = 0; |
3116 | int okFl = 0; | 3267 | int okFl = 0; |
3117 | 3268 | ||
3269 | if (!capable(CAP_SYS_ADMIN)) return -EPERM; | ||
3270 | |||
3118 | req.i2c_id = chip_id; | 3271 | req.i2c_id = chip_id; |
3119 | req.reg = reg_id; | 3272 | req.reg = reg_id; |
3120 | if (setFl) req.val = *val_ptr; | 3273 | if (setFl) req.val = *val_ptr; |
@@ -3123,8 +3276,8 @@ int pvr2_hdw_register_access(struct pvr2_hdw *hdw, | |||
3123 | cp = list_entry(item,struct pvr2_i2c_client,list); | 3276 | cp = list_entry(item,struct pvr2_i2c_client,list); |
3124 | if (cp->client->driver->id != chip_id) continue; | 3277 | if (cp->client->driver->id != chip_id) continue; |
3125 | stat = pvr2_i2c_client_cmd( | 3278 | stat = pvr2_i2c_client_cmd( |
3126 | cp,(setFl ? VIDIOC_INT_S_REGISTER : | 3279 | cp,(setFl ? VIDIOC_DBG_S_REGISTER : |
3127 | VIDIOC_INT_G_REGISTER),&req); | 3280 | VIDIOC_DBG_G_REGISTER),&req); |
3128 | if (!setFl) *val_ptr = req.val; | 3281 | if (!setFl) *val_ptr = req.val; |
3129 | okFl = !0; | 3282 | okFl = !0; |
3130 | break; | 3283 | break; |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.h b/drivers/media/video/pvrusb2/pvrusb2-hdw.h index 29979bb2a768..566a8ef7e121 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.h +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.h | |||
@@ -44,12 +44,6 @@ | |||
44 | #define PVR2_CVAL_INPUT_COMPOSITE 2 | 44 | #define PVR2_CVAL_INPUT_COMPOSITE 2 |
45 | #define PVR2_CVAL_INPUT_RADIO 3 | 45 | #define PVR2_CVAL_INPUT_RADIO 3 |
46 | 46 | ||
47 | /* Values that pvr2_hdw_get_signal_status() returns */ | ||
48 | #define PVR2_SIGNAL_OK 0x0001 | ||
49 | #define PVR2_SIGNAL_STEREO 0x0002 | ||
50 | #define PVR2_SIGNAL_SAP 0x0004 | ||
51 | |||
52 | |||
53 | /* Subsystem definitions - these are various pieces that can be | 47 | /* Subsystem definitions - these are various pieces that can be |
54 | independently stopped / started. Usually you don't want to mess with | 48 | independently stopped / started. Usually you don't want to mess with |
55 | this directly (let the driver handle things itself), but it is useful | 49 | this directly (let the driver handle things itself), but it is useful |
@@ -72,10 +66,17 @@ | |||
72 | PVR2_SUBSYS_RUN_ALL ) | 66 | PVR2_SUBSYS_RUN_ALL ) |
73 | 67 | ||
74 | enum pvr2_config { | 68 | enum pvr2_config { |
75 | pvr2_config_empty, | 69 | pvr2_config_empty, /* No configuration */ |
76 | pvr2_config_mpeg, | 70 | pvr2_config_mpeg, /* Encoded / compressed video */ |
77 | pvr2_config_vbi, | 71 | pvr2_config_vbi, /* Standard vbi info */ |
78 | pvr2_config_radio, | 72 | pvr2_config_pcm, /* Audio raw pcm stream */ |
73 | pvr2_config_rawvideo, /* Video raw frames */ | ||
74 | }; | ||
75 | |||
76 | enum pvr2_v4l_type { | ||
77 | pvr2_v4l_type_video, | ||
78 | pvr2_v4l_type_vbi, | ||
79 | pvr2_v4l_type_radio, | ||
79 | }; | 80 | }; |
80 | 81 | ||
81 | const char *pvr2_config_get_name(enum pvr2_config); | 82 | const char *pvr2_config_get_name(enum pvr2_config); |
@@ -148,8 +149,11 @@ int pvr2_hdw_commit_ctl(struct pvr2_hdw *); | |||
148 | /* Return name for this driver instance */ | 149 | /* Return name for this driver instance */ |
149 | const char *pvr2_hdw_get_driver_name(struct pvr2_hdw *); | 150 | const char *pvr2_hdw_get_driver_name(struct pvr2_hdw *); |
150 | 151 | ||
151 | /* Return PVR2_SIGNAL_XXXX bit mask indicating signal status */ | 152 | /* Mark tuner status stale so that it will be re-fetched */ |
152 | unsigned int pvr2_hdw_get_signal_status(struct pvr2_hdw *); | 153 | void pvr2_hdw_execute_tuner_poll(struct pvr2_hdw *); |
154 | |||
155 | /* Return information about the tuner */ | ||
156 | int pvr2_hdw_get_tuner_status(struct pvr2_hdw *,struct v4l2_tuner *); | ||
153 | 157 | ||
154 | /* Query device and see if it thinks it is on a high-speed USB link */ | 158 | /* Query device and see if it thinks it is on a high-speed USB link */ |
155 | int pvr2_hdw_is_hsm(struct pvr2_hdw *); | 159 | int pvr2_hdw_is_hsm(struct pvr2_hdw *); |
@@ -205,11 +209,12 @@ int pvr2_hdw_cpufw_get_enabled(struct pvr2_hdw *); | |||
205 | int pvr2_hdw_cpufw_get(struct pvr2_hdw *,unsigned int offs, | 209 | int pvr2_hdw_cpufw_get(struct pvr2_hdw *,unsigned int offs, |
206 | char *buf,unsigned int cnt); | 210 | char *buf,unsigned int cnt); |
207 | 211 | ||
208 | /* Retrieve previously stored v4l minor device number */ | 212 | /* Retrieve a previously stored v4l minor device number */ |
209 | int pvr2_hdw_v4l_get_minor_number(struct pvr2_hdw *); | 213 | int pvr2_hdw_v4l_get_minor_number(struct pvr2_hdw *,enum pvr2_v4l_type index); |
210 | 214 | ||
211 | /* Store the v4l minor device number */ | 215 | /* Store a v4l minor device number */ |
212 | void pvr2_hdw_v4l_store_minor_number(struct pvr2_hdw *,int); | 216 | void pvr2_hdw_v4l_store_minor_number(struct pvr2_hdw *, |
217 | enum pvr2_v4l_type index,int); | ||
213 | 218 | ||
214 | /* Direct read/write access to chip's registers: | 219 | /* Direct read/write access to chip's registers: |
215 | chip_id - unique id of chip (e.g. I2C_DRIVERD_xxxx) | 220 | chip_id - unique id of chip (e.g. I2C_DRIVERD_xxxx) |
@@ -217,7 +222,7 @@ void pvr2_hdw_v4l_store_minor_number(struct pvr2_hdw *,int); | |||
217 | setFl - true to set the register, false to read it | 222 | setFl - true to set the register, false to read it |
218 | val_ptr - storage location for source / result. */ | 223 | val_ptr - storage location for source / result. */ |
219 | int pvr2_hdw_register_access(struct pvr2_hdw *, | 224 | int pvr2_hdw_register_access(struct pvr2_hdw *, |
220 | u32 chip_id,unsigned long reg_id, | 225 | u32 chip_id,u64 reg_id, |
221 | int setFl,u32 *val_ptr); | 226 | int setFl,u32 *val_ptr); |
222 | 227 | ||
223 | /* The following entry points are all lower level things you normally don't | 228 | /* The following entry points are all lower level things you normally don't |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c index 05121666b9ba..49773764383b 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c | |||
@@ -33,15 +33,17 @@ | |||
33 | #define trace_i2c(...) pvr2_trace(PVR2_TRACE_I2C,__VA_ARGS__) | 33 | #define trace_i2c(...) pvr2_trace(PVR2_TRACE_I2C,__VA_ARGS__) |
34 | 34 | ||
35 | #define OP_STANDARD 0 | 35 | #define OP_STANDARD 0 |
36 | #define OP_BCSH 1 | 36 | #define OP_AUDIOMODE 1 |
37 | #define OP_VOLUME 2 | 37 | #define OP_BCSH 2 |
38 | #define OP_FREQ 3 | 38 | #define OP_VOLUME 3 |
39 | #define OP_AUDIORATE 4 | 39 | #define OP_FREQ 4 |
40 | #define OP_SIZE 5 | 40 | #define OP_AUDIORATE 5 |
41 | #define OP_LOG 6 | 41 | #define OP_SIZE 6 |
42 | #define OP_LOG 7 | ||
42 | 43 | ||
43 | static const struct pvr2_i2c_op * const ops[] = { | 44 | static const struct pvr2_i2c_op * const ops[] = { |
44 | [OP_STANDARD] = &pvr2_i2c_op_v4l2_standard, | 45 | [OP_STANDARD] = &pvr2_i2c_op_v4l2_standard, |
46 | [OP_AUDIOMODE] = &pvr2_i2c_op_v4l2_audiomode, | ||
45 | [OP_BCSH] = &pvr2_i2c_op_v4l2_bcsh, | 47 | [OP_BCSH] = &pvr2_i2c_op_v4l2_bcsh, |
46 | [OP_VOLUME] = &pvr2_i2c_op_v4l2_volume, | 48 | [OP_VOLUME] = &pvr2_i2c_op_v4l2_volume, |
47 | [OP_FREQ] = &pvr2_i2c_op_v4l2_frequency, | 49 | [OP_FREQ] = &pvr2_i2c_op_v4l2_frequency, |
@@ -54,11 +56,13 @@ void pvr2_i2c_probe(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp) | |||
54 | int id; | 56 | int id; |
55 | id = cp->client->driver->id; | 57 | id = cp->client->driver->id; |
56 | cp->ctl_mask = ((1 << OP_STANDARD) | | 58 | cp->ctl_mask = ((1 << OP_STANDARD) | |
59 | (1 << OP_AUDIOMODE) | | ||
57 | (1 << OP_BCSH) | | 60 | (1 << OP_BCSH) | |
58 | (1 << OP_VOLUME) | | 61 | (1 << OP_VOLUME) | |
59 | (1 << OP_FREQ) | | 62 | (1 << OP_FREQ) | |
60 | (1 << OP_SIZE) | | 63 | (1 << OP_SIZE) | |
61 | (1 << OP_LOG)); | 64 | (1 << OP_LOG)); |
65 | cp->status_poll = pvr2_v4l2_cmd_status_poll; | ||
62 | 66 | ||
63 | if (id == I2C_DRIVERID_MSP3400) { | 67 | if (id == I2C_DRIVERID_MSP3400) { |
64 | if (pvr2_i2c_msp3400_setup(hdw,cp)) { | 68 | if (pvr2_i2c_msp3400_setup(hdw,cp)) { |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c index 05ea17afe903..c650e02ccd00 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c | |||
@@ -24,22 +24,26 @@ | |||
24 | #include "pvrusb2-hdw-internal.h" | 24 | #include "pvrusb2-hdw-internal.h" |
25 | #include "pvrusb2-debug.h" | 25 | #include "pvrusb2-debug.h" |
26 | #include <linux/videodev2.h> | 26 | #include <linux/videodev2.h> |
27 | 27 | #include <media/v4l2-common.h> | |
28 | 28 | ||
29 | static void set_standard(struct pvr2_hdw *hdw) | 29 | static void set_standard(struct pvr2_hdw *hdw) |
30 | { | 30 | { |
31 | v4l2_std_id vs; | 31 | pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_standard"); |
32 | vs = hdw->std_mask_cur; | 32 | |
33 | pvr2_trace(PVR2_TRACE_CHIPS, | 33 | if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) { |
34 | "i2c v4l2 set_standard(0x%llx)",(long long unsigned)vs); | 34 | pvr2_i2c_core_cmd(hdw,AUDC_SET_RADIO,NULL); |
35 | 35 | } else { | |
36 | pvr2_i2c_core_cmd(hdw,VIDIOC_S_STD,&vs); | 36 | v4l2_std_id vs; |
37 | vs = hdw->std_mask_cur; | ||
38 | pvr2_i2c_core_cmd(hdw,VIDIOC_S_STD,&vs); | ||
39 | } | ||
40 | hdw->tuner_signal_stale = !0; | ||
37 | } | 41 | } |
38 | 42 | ||
39 | 43 | ||
40 | static int check_standard(struct pvr2_hdw *hdw) | 44 | static int check_standard(struct pvr2_hdw *hdw) |
41 | { | 45 | { |
42 | return hdw->std_dirty != 0; | 46 | return (hdw->input_dirty != 0) || (hdw->std_dirty != 0); |
43 | } | 47 | } |
44 | 48 | ||
45 | 49 | ||
@@ -136,16 +140,53 @@ const struct pvr2_i2c_op pvr2_i2c_op_v4l2_volume = { | |||
136 | }; | 140 | }; |
137 | 141 | ||
138 | 142 | ||
143 | static void set_audiomode(struct pvr2_hdw *hdw) | ||
144 | { | ||
145 | struct v4l2_tuner vt; | ||
146 | memset(&vt,0,sizeof(vt)); | ||
147 | vt.audmode = hdw->audiomode_val; | ||
148 | pvr2_i2c_core_cmd(hdw,VIDIOC_S_TUNER,&vt); | ||
149 | } | ||
150 | |||
151 | |||
152 | static int check_audiomode(struct pvr2_hdw *hdw) | ||
153 | { | ||
154 | return (hdw->input_dirty || | ||
155 | hdw->audiomode_dirty); | ||
156 | } | ||
157 | |||
158 | |||
159 | const struct pvr2_i2c_op pvr2_i2c_op_v4l2_audiomode = { | ||
160 | .check = check_audiomode, | ||
161 | .update = set_audiomode, | ||
162 | .name = "v4l2_audiomode", | ||
163 | }; | ||
164 | |||
165 | |||
139 | static void set_frequency(struct pvr2_hdw *hdw) | 166 | static void set_frequency(struct pvr2_hdw *hdw) |
140 | { | 167 | { |
141 | unsigned long fv; | 168 | unsigned long fv; |
142 | struct v4l2_frequency freq; | 169 | struct v4l2_frequency freq; |
143 | fv = hdw->freqVal; | 170 | fv = pvr2_hdw_get_cur_freq(hdw); |
144 | pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_freq(%lu)",fv); | 171 | pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_freq(%lu)",fv); |
172 | if (hdw->tuner_signal_stale) { | ||
173 | pvr2_i2c_core_status_poll(hdw); | ||
174 | } | ||
145 | memset(&freq,0,sizeof(freq)); | 175 | memset(&freq,0,sizeof(freq)); |
146 | freq.frequency = fv / 62500; | 176 | if (hdw->tuner_signal_info.capability & V4L2_TUNER_CAP_LOW) { |
177 | // ((fv * 1000) / 62500) | ||
178 | freq.frequency = (fv * 2) / 125; | ||
179 | } else { | ||
180 | freq.frequency = fv / 62500; | ||
181 | } | ||
182 | /* tuner-core currently doesn't seem to care about this, but | ||
183 | let's set it anyway for completeness. */ | ||
184 | if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) { | ||
185 | freq.type = V4L2_TUNER_RADIO; | ||
186 | } else { | ||
187 | freq.type = V4L2_TUNER_ANALOG_TV; | ||
188 | } | ||
147 | freq.tuner = 0; | 189 | freq.tuner = 0; |
148 | freq.type = V4L2_TUNER_ANALOG_TV; | ||
149 | pvr2_i2c_core_cmd(hdw,VIDIOC_S_FREQUENCY,&freq); | 190 | pvr2_i2c_core_cmd(hdw,VIDIOC_S_FREQUENCY,&freq); |
150 | } | 191 | } |
151 | 192 | ||
@@ -221,6 +262,12 @@ void pvr2_v4l2_cmd_stream(struct pvr2_i2c_client *cp,int fl) | |||
221 | } | 262 | } |
222 | 263 | ||
223 | 264 | ||
265 | void pvr2_v4l2_cmd_status_poll(struct pvr2_i2c_client *cp) | ||
266 | { | ||
267 | pvr2_i2c_client_cmd(cp,VIDIOC_G_TUNER,&cp->hdw->tuner_signal_info); | ||
268 | } | ||
269 | |||
270 | |||
224 | /* | 271 | /* |
225 | Stuff for Emacs to see, in order to encourage consistent editing style: | 272 | Stuff for Emacs to see, in order to encourage consistent editing style: |
226 | *** Local Variables: *** | 273 | *** Local Variables: *** |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h index ecabddba1ec5..c838df6167f9 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h | |||
@@ -26,13 +26,16 @@ | |||
26 | #include "pvrusb2-i2c-core.h" | 26 | #include "pvrusb2-i2c-core.h" |
27 | 27 | ||
28 | extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_standard; | 28 | extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_standard; |
29 | extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_radio; | ||
29 | extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_bcsh; | 30 | extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_bcsh; |
30 | extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_volume; | 31 | extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_volume; |
31 | extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_frequency; | 32 | extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_frequency; |
32 | extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_size; | 33 | extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_size; |
34 | extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_audiomode; | ||
33 | extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_log; | 35 | extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_log; |
34 | 36 | ||
35 | void pvr2_v4l2_cmd_stream(struct pvr2_i2c_client *,int); | 37 | void pvr2_v4l2_cmd_stream(struct pvr2_i2c_client *,int); |
38 | void pvr2_v4l2_cmd_status_poll(struct pvr2_i2c_client *); | ||
36 | 39 | ||
37 | #endif /* __PVRUSB2_CMD_V4L2_H */ | 40 | #endif /* __PVRUSB2_CMD_V4L2_H */ |
38 | 41 | ||
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c index 62a7cfca837d..58fc3c730fe1 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include "pvrusb2-i2c-core.h" | 22 | #include "pvrusb2-i2c-core.h" |
23 | #include "pvrusb2-hdw-internal.h" | 23 | #include "pvrusb2-hdw-internal.h" |
24 | #include "pvrusb2-debug.h" | 24 | #include "pvrusb2-debug.h" |
25 | #include "pvrusb2-fx2-cmd.h" | ||
25 | 26 | ||
26 | #define trace_i2c(...) pvr2_trace(PVR2_TRACE_I2C,__VA_ARGS__) | 27 | #define trace_i2c(...) pvr2_trace(PVR2_TRACE_I2C,__VA_ARGS__) |
27 | 28 | ||
@@ -66,7 +67,7 @@ static int pvr2_i2c_write(struct pvr2_hdw *hdw, /* Context */ | |||
66 | memset(hdw->cmd_buffer, 0, sizeof(hdw->cmd_buffer)); | 67 | memset(hdw->cmd_buffer, 0, sizeof(hdw->cmd_buffer)); |
67 | 68 | ||
68 | /* Set up command buffer for an I2C write */ | 69 | /* Set up command buffer for an I2C write */ |
69 | hdw->cmd_buffer[0] = 0x08; /* write prefix */ | 70 | hdw->cmd_buffer[0] = FX2CMD_I2C_WRITE; /* write prefix */ |
70 | hdw->cmd_buffer[1] = i2c_addr; /* i2c addr of chip */ | 71 | hdw->cmd_buffer[1] = i2c_addr; /* i2c addr of chip */ |
71 | hdw->cmd_buffer[2] = length; /* length of what follows */ | 72 | hdw->cmd_buffer[2] = length; /* length of what follows */ |
72 | if (length) memcpy(hdw->cmd_buffer + 3, data, length); | 73 | if (length) memcpy(hdw->cmd_buffer + 3, data, length); |
@@ -128,7 +129,7 @@ static int pvr2_i2c_read(struct pvr2_hdw *hdw, /* Context */ | |||
128 | memset(hdw->cmd_buffer, 0, sizeof(hdw->cmd_buffer)); | 129 | memset(hdw->cmd_buffer, 0, sizeof(hdw->cmd_buffer)); |
129 | 130 | ||
130 | /* Set up command buffer for an I2C write followed by a read */ | 131 | /* Set up command buffer for an I2C write followed by a read */ |
131 | hdw->cmd_buffer[0] = 0x09; /* read prefix */ | 132 | hdw->cmd_buffer[0] = FX2CMD_I2C_READ; /* read prefix */ |
132 | hdw->cmd_buffer[1] = dlen; /* arg length */ | 133 | hdw->cmd_buffer[1] = dlen; /* arg length */ |
133 | hdw->cmd_buffer[2] = rlen; /* answer length. Device will send one | 134 | hdw->cmd_buffer[2] = rlen; /* answer length. Device will send one |
134 | more byte (status). */ | 135 | more byte (status). */ |
@@ -221,7 +222,7 @@ static int i2c_24xxx_ir(struct pvr2_hdw *hdw, | |||
221 | 222 | ||
222 | /* Issue a command to the FX2 to read the IR receiver. */ | 223 | /* Issue a command to the FX2 to read the IR receiver. */ |
223 | LOCK_TAKE(hdw->ctl_lock); do { | 224 | LOCK_TAKE(hdw->ctl_lock); do { |
224 | hdw->cmd_buffer[0] = 0xec; | 225 | hdw->cmd_buffer[0] = FX2CMD_GET_IR_CODE; |
225 | stat = pvr2_send_request(hdw, | 226 | stat = pvr2_send_request(hdw, |
226 | hdw->cmd_buffer,1, | 227 | hdw->cmd_buffer,1, |
227 | hdw->cmd_buffer,4); | 228 | hdw->cmd_buffer,4); |
@@ -590,6 +591,33 @@ static int handler_check(struct pvr2_i2c_client *cp) | |||
590 | 591 | ||
591 | #define BUFSIZE 500 | 592 | #define BUFSIZE 500 |
592 | 593 | ||
594 | |||
595 | void pvr2_i2c_core_status_poll(struct pvr2_hdw *hdw) | ||
596 | { | ||
597 | struct list_head *item; | ||
598 | struct pvr2_i2c_client *cp; | ||
599 | mutex_lock(&hdw->i2c_list_lock); do { | ||
600 | struct v4l2_tuner *vtp = &hdw->tuner_signal_info; | ||
601 | memset(vtp,0,sizeof(*vtp)); | ||
602 | list_for_each(item,&hdw->i2c_clients) { | ||
603 | cp = list_entry(item,struct pvr2_i2c_client,list); | ||
604 | if (!cp->detected_flag) continue; | ||
605 | if (!cp->status_poll) continue; | ||
606 | cp->status_poll(cp); | ||
607 | } | ||
608 | hdw->tuner_signal_stale = 0; | ||
609 | pvr2_trace(PVR2_TRACE_CHIPS,"i2c status poll" | ||
610 | " type=%u strength=%u audio=0x%x cap=0x%x" | ||
611 | " low=%u hi=%u", | ||
612 | vtp->type, | ||
613 | vtp->signal,vtp->rxsubchans,vtp->capability, | ||
614 | vtp->rangelow,vtp->rangehigh); | ||
615 | } while (0); mutex_unlock(&hdw->i2c_list_lock); | ||
616 | } | ||
617 | |||
618 | |||
619 | /* Issue various I2C operations to bring chip-level drivers into sync with | ||
620 | state stored in this driver. */ | ||
593 | void pvr2_i2c_core_sync(struct pvr2_hdw *hdw) | 621 | void pvr2_i2c_core_sync(struct pvr2_hdw *hdw) |
594 | { | 622 | { |
595 | unsigned long msk; | 623 | unsigned long msk; |
@@ -870,12 +898,12 @@ static int pvr2_i2c_attach_inform(struct i2c_client *client) | |||
870 | struct pvr2_hdw *hdw = (struct pvr2_hdw *)(client->adapter->algo_data); | 898 | struct pvr2_hdw *hdw = (struct pvr2_hdw *)(client->adapter->algo_data); |
871 | struct pvr2_i2c_client *cp; | 899 | struct pvr2_i2c_client *cp; |
872 | int fl = !(hdw->i2c_pend_types & PVR2_I2C_PEND_ALL); | 900 | int fl = !(hdw->i2c_pend_types & PVR2_I2C_PEND_ALL); |
873 | cp = kmalloc(sizeof(*cp),GFP_KERNEL); | 901 | cp = kzalloc(sizeof(*cp),GFP_KERNEL); |
874 | trace_i2c("i2c_attach [client=%s @ 0x%x ctxt=%p]", | 902 | trace_i2c("i2c_attach [client=%s @ 0x%x ctxt=%p]", |
875 | client->name, | 903 | client->name, |
876 | client->addr,cp); | 904 | client->addr,cp); |
877 | if (!cp) return -ENOMEM; | 905 | if (!cp) return -ENOMEM; |
878 | memset(cp,0,sizeof(*cp)); | 906 | cp->hdw = hdw; |
879 | INIT_LIST_HEAD(&cp->list); | 907 | INIT_LIST_HEAD(&cp->list); |
880 | cp->client = client; | 908 | cp->client = client; |
881 | mutex_lock(&hdw->i2c_list_lock); do { | 909 | mutex_lock(&hdw->i2c_list_lock); do { |
@@ -948,8 +976,7 @@ static void do_i2c_scan(struct pvr2_hdw *hdw) | |||
948 | printk("%s: i2c scan beginning\n",hdw->name); | 976 | printk("%s: i2c scan beginning\n",hdw->name); |
949 | for (i = 0; i < 128; i++) { | 977 | for (i = 0; i < 128; i++) { |
950 | msg[0].addr = i; | 978 | msg[0].addr = i; |
951 | rc = i2c_transfer(&hdw->i2c_adap,msg, | 979 | rc = i2c_transfer(&hdw->i2c_adap,msg, ARRAY_SIZE(msg)); |
952 | sizeof(msg)/sizeof(msg[0])); | ||
953 | if (rc != 1) continue; | 980 | if (rc != 1) continue; |
954 | printk("%s: i2c scan: found device @ 0x%x\n",hdw->name,i); | 981 | printk("%s: i2c scan: found device @ 0x%x\n",hdw->name,i); |
955 | } | 982 | } |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.h b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.h index 6d7e25247576..bd0807b905bb 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.h +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.h | |||
@@ -35,10 +35,12 @@ struct pvr2_i2c_client { | |||
35 | struct i2c_client *client; | 35 | struct i2c_client *client; |
36 | struct pvr2_i2c_handler *handler; | 36 | struct pvr2_i2c_handler *handler; |
37 | struct list_head list; | 37 | struct list_head list; |
38 | struct pvr2_hdw *hdw; | ||
38 | int detected_flag; | 39 | int detected_flag; |
39 | int recv_enable; | 40 | int recv_enable; |
40 | unsigned long pend_mask; | 41 | unsigned long pend_mask; |
41 | unsigned long ctl_mask; | 42 | unsigned long ctl_mask; |
43 | void (*status_poll)(struct pvr2_i2c_client *); | ||
42 | }; | 44 | }; |
43 | 45 | ||
44 | struct pvr2_i2c_handler { | 46 | struct pvr2_i2c_handler { |
@@ -67,6 +69,7 @@ int pvr2_i2c_core_cmd(struct pvr2_hdw *,unsigned int cmd,void *arg); | |||
67 | 69 | ||
68 | int pvr2_i2c_core_check_stale(struct pvr2_hdw *); | 70 | int pvr2_i2c_core_check_stale(struct pvr2_hdw *); |
69 | void pvr2_i2c_core_sync(struct pvr2_hdw *); | 71 | void pvr2_i2c_core_sync(struct pvr2_hdw *); |
72 | void pvr2_i2c_core_status_poll(struct pvr2_hdw *); | ||
70 | unsigned int pvr2_i2c_report(struct pvr2_hdw *,char *buf,unsigned int maxlen); | 73 | unsigned int pvr2_i2c_report(struct pvr2_hdw *,char *buf,unsigned int maxlen); |
71 | #define PVR2_I2C_DETAIL_DEBUG 0x0001 | 74 | #define PVR2_I2C_DETAIL_DEBUG 0x0001 |
72 | #define PVR2_I2C_DETAIL_HANDLER 0x0002 | 75 | #define PVR2_I2C_DETAIL_HANDLER 0x0002 |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-io.c b/drivers/media/video/pvrusb2/pvrusb2-io.c index 57fb32033543..ce3c8982ffe0 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-io.c +++ b/drivers/media/video/pvrusb2/pvrusb2-io.c | |||
@@ -474,9 +474,8 @@ static void buffer_complete(struct urb *urb) | |||
474 | struct pvr2_stream *pvr2_stream_create(void) | 474 | struct pvr2_stream *pvr2_stream_create(void) |
475 | { | 475 | { |
476 | struct pvr2_stream *sp; | 476 | struct pvr2_stream *sp; |
477 | sp = kmalloc(sizeof(*sp),GFP_KERNEL); | 477 | sp = kzalloc(sizeof(*sp),GFP_KERNEL); |
478 | if (!sp) return sp; | 478 | if (!sp) return sp; |
479 | memset(sp,0,sizeof(*sp)); | ||
480 | pvr2_trace(PVR2_TRACE_INIT,"pvr2_stream_create: sp=%p",sp); | 479 | pvr2_trace(PVR2_TRACE_INIT,"pvr2_stream_create: sp=%p",sp); |
481 | pvr2_stream_init(sp); | 480 | pvr2_stream_init(sp); |
482 | return sp; | 481 | return sp; |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-ioread.c b/drivers/media/video/pvrusb2/pvrusb2-ioread.c index b71f9a961f8a..f782418afa45 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-ioread.c +++ b/drivers/media/video/pvrusb2/pvrusb2-ioread.c | |||
@@ -87,10 +87,9 @@ static void pvr2_ioread_done(struct pvr2_ioread *cp) | |||
87 | struct pvr2_ioread *pvr2_ioread_create(void) | 87 | struct pvr2_ioread *pvr2_ioread_create(void) |
88 | { | 88 | { |
89 | struct pvr2_ioread *cp; | 89 | struct pvr2_ioread *cp; |
90 | cp = kmalloc(sizeof(*cp),GFP_KERNEL); | 90 | cp = kzalloc(sizeof(*cp),GFP_KERNEL); |
91 | if (!cp) return NULL; | 91 | if (!cp) return NULL; |
92 | pvr2_trace(PVR2_TRACE_STRUCT,"pvr2_ioread_create id=%p",cp); | 92 | pvr2_trace(PVR2_TRACE_STRUCT,"pvr2_ioread_create id=%p",cp); |
93 | memset(cp,0,sizeof(*cp)); | ||
94 | if (pvr2_ioread_init(cp) < 0) { | 93 | if (pvr2_ioread_init(cp) < 0) { |
95 | kfree(cp); | 94 | kfree(cp); |
96 | return NULL; | 95 | return NULL; |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-std.c b/drivers/media/video/pvrusb2/pvrusb2-std.c index c08925557ed4..81de26ba41d9 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-std.c +++ b/drivers/media/video/pvrusb2/pvrusb2-std.c | |||
@@ -141,10 +141,8 @@ int pvr2_std_str_to_id(v4l2_std_id *idPtr,const char *bufPtr, | |||
141 | cnt = 0; | 141 | cnt = 0; |
142 | while ((cnt < bufSize) && (bufPtr[cnt] != '-')) cnt++; | 142 | while ((cnt < bufSize) && (bufPtr[cnt] != '-')) cnt++; |
143 | if (cnt >= bufSize) return 0; // No more characters | 143 | if (cnt >= bufSize) return 0; // No more characters |
144 | sp = find_std_name( | 144 | sp = find_std_name(std_groups, ARRAY_SIZE(std_groups), |
145 | std_groups, | 145 | bufPtr,cnt); |
146 | sizeof(std_groups)/sizeof(std_groups[0]), | ||
147 | bufPtr,cnt); | ||
148 | if (!sp) return 0; // Illegal color system name | 146 | if (!sp) return 0; // Illegal color system name |
149 | cnt++; | 147 | cnt++; |
150 | bufPtr += cnt; | 148 | bufPtr += cnt; |
@@ -163,8 +161,7 @@ int pvr2_std_str_to_id(v4l2_std_id *idPtr,const char *bufPtr, | |||
163 | if (ch == '/') break; | 161 | if (ch == '/') break; |
164 | cnt++; | 162 | cnt++; |
165 | } | 163 | } |
166 | sp = find_std_name(std_items, | 164 | sp = find_std_name(std_items, ARRAY_SIZE(std_items), |
167 | sizeof(std_items)/sizeof(std_items[0]), | ||
168 | bufPtr,cnt); | 165 | bufPtr,cnt); |
169 | if (!sp) return 0; // Illegal modulation system ID | 166 | if (!sp) return 0; // Illegal modulation system ID |
170 | t = sp->id & cmsk; | 167 | t = sp->id & cmsk; |
@@ -189,14 +186,10 @@ unsigned int pvr2_std_id_to_str(char *bufPtr, unsigned int bufSize, | |||
189 | unsigned int c1,c2; | 186 | unsigned int c1,c2; |
190 | cfl = 0; | 187 | cfl = 0; |
191 | c1 = 0; | 188 | c1 = 0; |
192 | for (idx1 = 0; | 189 | for (idx1 = 0; idx1 < ARRAY_SIZE(std_groups); idx1++) { |
193 | idx1 < sizeof(std_groups)/sizeof(std_groups[0]); | ||
194 | idx1++) { | ||
195 | gp = std_groups + idx1; | 190 | gp = std_groups + idx1; |
196 | gfl = 0; | 191 | gfl = 0; |
197 | for (idx2 = 0; | 192 | for (idx2 = 0; idx2 < ARRAY_SIZE(std_items); idx2++) { |
198 | idx2 < sizeof(std_items)/sizeof(std_items[0]); | ||
199 | idx2++) { | ||
200 | ip = std_items + idx2; | 193 | ip = std_items + idx2; |
201 | if (!(gp->id & ip->id & id)) continue; | 194 | if (!(gp->id & ip->id & id)) continue; |
202 | if (!gfl) { | 195 | if (!gfl) { |
@@ -279,7 +272,7 @@ static struct v4l2_standard generic_standards[] = { | |||
279 | } | 272 | } |
280 | }; | 273 | }; |
281 | 274 | ||
282 | #define generic_standards_cnt (sizeof(generic_standards)/sizeof(generic_standards[0])) | 275 | #define generic_standards_cnt ARRAY_SIZE(generic_standards) |
283 | 276 | ||
284 | static struct v4l2_standard *match_std(v4l2_std_id id) | 277 | static struct v4l2_standard *match_std(v4l2_std_id id) |
285 | { | 278 | { |
@@ -348,7 +341,7 @@ struct v4l2_standard *pvr2_std_create_enum(unsigned int *countptr, | |||
348 | fmsk |= idmsk; | 341 | fmsk |= idmsk; |
349 | } | 342 | } |
350 | 343 | ||
351 | for (idx2 = 0; idx2 < sizeof(std_mixes)/sizeof(std_mixes[0]); idx2++) { | 344 | for (idx2 = 0; idx2 < ARRAY_SIZE(std_mixes); idx2++) { |
352 | if ((id & std_mixes[idx2]) == std_mixes[idx2]) std_cnt++; | 345 | if ((id & std_mixes[idx2]) == std_mixes[idx2]) std_cnt++; |
353 | } | 346 | } |
354 | 347 | ||
@@ -366,16 +359,15 @@ struct v4l2_standard *pvr2_std_create_enum(unsigned int *countptr, | |||
366 | std_cnt); | 359 | std_cnt); |
367 | if (!std_cnt) return NULL; // paranoia | 360 | if (!std_cnt) return NULL; // paranoia |
368 | 361 | ||
369 | stddefs = kmalloc(sizeof(struct v4l2_standard) * std_cnt, | 362 | stddefs = kzalloc(sizeof(struct v4l2_standard) * std_cnt, |
370 | GFP_KERNEL); | 363 | GFP_KERNEL); |
371 | memset(stddefs,0,sizeof(struct v4l2_standard) * std_cnt); | ||
372 | for (idx = 0; idx < std_cnt; idx++) stddefs[idx].index = idx; | 364 | for (idx = 0; idx < std_cnt; idx++) stddefs[idx].index = idx; |
373 | 365 | ||
374 | idx = 0; | 366 | idx = 0; |
375 | 367 | ||
376 | /* Enumerate potential special cases */ | 368 | /* Enumerate potential special cases */ |
377 | for (idx2 = 0; ((idx2 < sizeof(std_mixes)/sizeof(std_mixes[0])) && | 369 | for (idx2 = 0; (idx2 < ARRAY_SIZE(std_mixes)) && (idx < std_cnt); |
378 | (idx < std_cnt)); idx2++) { | 370 | idx2++) { |
379 | if (!(id & std_mixes[idx2])) continue; | 371 | if (!(id & std_mixes[idx2])) continue; |
380 | if (pvr2_std_fill(stddefs+idx,std_mixes[idx2])) idx++; | 372 | if (pvr2_std_fill(stddefs+idx,std_mixes[idx2])) idx++; |
381 | } | 373 | } |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c index c294f46db9b9..91396fd573e4 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c +++ b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c | |||
@@ -40,8 +40,10 @@ struct pvr2_sysfs { | |||
40 | struct pvr2_sysfs_ctl_item *item_first; | 40 | struct pvr2_sysfs_ctl_item *item_first; |
41 | struct pvr2_sysfs_ctl_item *item_last; | 41 | struct pvr2_sysfs_ctl_item *item_last; |
42 | struct class_device_attribute attr_v4l_minor_number; | 42 | struct class_device_attribute attr_v4l_minor_number; |
43 | struct class_device_attribute attr_v4l_radio_minor_number; | ||
43 | struct class_device_attribute attr_unit_number; | 44 | struct class_device_attribute attr_unit_number; |
44 | int v4l_minor_number_created_ok; | 45 | int v4l_minor_number_created_ok; |
46 | int v4l_radio_minor_number_created_ok; | ||
45 | int unit_number_created_ok; | 47 | int unit_number_created_ok; |
46 | }; | 48 | }; |
47 | 49 | ||
@@ -491,7 +493,7 @@ static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id) | |||
491 | unsigned int cnt,acnt; | 493 | unsigned int cnt,acnt; |
492 | int ret; | 494 | int ret; |
493 | 495 | ||
494 | if ((ctl_id < 0) || (ctl_id >= (sizeof(funcs)/sizeof(funcs[0])))) { | 496 | if ((ctl_id < 0) || (ctl_id >= ARRAY_SIZE(funcs))) { |
495 | return; | 497 | return; |
496 | } | 498 | } |
497 | 499 | ||
@@ -499,9 +501,8 @@ static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id) | |||
499 | cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,ctl_id); | 501 | cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,ctl_id); |
500 | if (!cptr) return; | 502 | if (!cptr) return; |
501 | 503 | ||
502 | cip = kmalloc(sizeof(*cip),GFP_KERNEL); | 504 | cip = kzalloc(sizeof(*cip),GFP_KERNEL); |
503 | if (!cip) return; | 505 | if (!cip) return; |
504 | memset(cip,0,sizeof(*cip)); | ||
505 | pvr2_sysfs_trace("Creating pvr2_sysfs_ctl_item id=%p",cip); | 506 | pvr2_sysfs_trace("Creating pvr2_sysfs_ctl_item id=%p",cip); |
506 | 507 | ||
507 | cip->cptr = cptr; | 508 | cip->cptr = cptr; |
@@ -611,9 +612,8 @@ static void pvr2_sysfs_add_debugifc(struct pvr2_sysfs *sfp) | |||
611 | struct pvr2_sysfs_debugifc *dip; | 612 | struct pvr2_sysfs_debugifc *dip; |
612 | int ret; | 613 | int ret; |
613 | 614 | ||
614 | dip = kmalloc(sizeof(*dip),GFP_KERNEL); | 615 | dip = kzalloc(sizeof(*dip),GFP_KERNEL); |
615 | if (!dip) return; | 616 | if (!dip) return; |
616 | memset(dip,0,sizeof(*dip)); | ||
617 | dip->attr_debugcmd.attr.owner = THIS_MODULE; | 617 | dip->attr_debugcmd.attr.owner = THIS_MODULE; |
618 | dip->attr_debugcmd.attr.name = "debugcmd"; | 618 | dip->attr_debugcmd.attr.name = "debugcmd"; |
619 | dip->attr_debugcmd.attr.mode = S_IRUGO|S_IWUSR|S_IWGRP; | 619 | dip->attr_debugcmd.attr.mode = S_IRUGO|S_IWUSR|S_IWGRP; |
@@ -709,6 +709,10 @@ static void class_dev_destroy(struct pvr2_sysfs *sfp) | |||
709 | class_device_remove_file(sfp->class_dev, | 709 | class_device_remove_file(sfp->class_dev, |
710 | &sfp->attr_v4l_minor_number); | 710 | &sfp->attr_v4l_minor_number); |
711 | } | 711 | } |
712 | if (sfp->v4l_radio_minor_number_created_ok) { | ||
713 | class_device_remove_file(sfp->class_dev, | ||
714 | &sfp->attr_v4l_radio_minor_number); | ||
715 | } | ||
712 | if (sfp->unit_number_created_ok) { | 716 | if (sfp->unit_number_created_ok) { |
713 | class_device_remove_file(sfp->class_dev, | 717 | class_device_remove_file(sfp->class_dev, |
714 | &sfp->attr_unit_number); | 718 | &sfp->attr_unit_number); |
@@ -726,7 +730,20 @@ static ssize_t v4l_minor_number_show(struct class_device *class_dev,char *buf) | |||
726 | sfp = (struct pvr2_sysfs *)class_dev->class_data; | 730 | sfp = (struct pvr2_sysfs *)class_dev->class_data; |
727 | if (!sfp) return -EINVAL; | 731 | if (!sfp) return -EINVAL; |
728 | return scnprintf(buf,PAGE_SIZE,"%d\n", | 732 | return scnprintf(buf,PAGE_SIZE,"%d\n", |
729 | pvr2_hdw_v4l_get_minor_number(sfp->channel.hdw)); | 733 | pvr2_hdw_v4l_get_minor_number(sfp->channel.hdw, |
734 | pvr2_v4l_type_video)); | ||
735 | } | ||
736 | |||
737 | |||
738 | static ssize_t v4l_radio_minor_number_show(struct class_device *class_dev, | ||
739 | char *buf) | ||
740 | { | ||
741 | struct pvr2_sysfs *sfp; | ||
742 | sfp = (struct pvr2_sysfs *)class_dev->class_data; | ||
743 | if (!sfp) return -EINVAL; | ||
744 | return scnprintf(buf,PAGE_SIZE,"%d\n", | ||
745 | pvr2_hdw_v4l_get_minor_number(sfp->channel.hdw, | ||
746 | pvr2_v4l_type_radio)); | ||
730 | } | 747 | } |
731 | 748 | ||
732 | 749 | ||
@@ -749,9 +766,8 @@ static void class_dev_create(struct pvr2_sysfs *sfp, | |||
749 | 766 | ||
750 | usb_dev = pvr2_hdw_get_dev(sfp->channel.hdw); | 767 | usb_dev = pvr2_hdw_get_dev(sfp->channel.hdw); |
751 | if (!usb_dev) return; | 768 | if (!usb_dev) return; |
752 | class_dev = kmalloc(sizeof(*class_dev),GFP_KERNEL); | 769 | class_dev = kzalloc(sizeof(*class_dev),GFP_KERNEL); |
753 | if (!class_dev) return; | 770 | if (!class_dev) return; |
754 | memset(class_dev,0,sizeof(*class_dev)); | ||
755 | 771 | ||
756 | pvr2_sysfs_trace("Creating class_dev id=%p",class_dev); | 772 | pvr2_sysfs_trace("Creating class_dev id=%p",class_dev); |
757 | 773 | ||
@@ -793,6 +809,20 @@ static void class_dev_create(struct pvr2_sysfs *sfp, | |||
793 | sfp->v4l_minor_number_created_ok = !0; | 809 | sfp->v4l_minor_number_created_ok = !0; |
794 | } | 810 | } |
795 | 811 | ||
812 | sfp->attr_v4l_radio_minor_number.attr.owner = THIS_MODULE; | ||
813 | sfp->attr_v4l_radio_minor_number.attr.name = "v4l_radio_minor_number"; | ||
814 | sfp->attr_v4l_radio_minor_number.attr.mode = S_IRUGO; | ||
815 | sfp->attr_v4l_radio_minor_number.show = v4l_radio_minor_number_show; | ||
816 | sfp->attr_v4l_radio_minor_number.store = NULL; | ||
817 | ret = class_device_create_file(sfp->class_dev, | ||
818 | &sfp->attr_v4l_radio_minor_number); | ||
819 | if (ret < 0) { | ||
820 | printk(KERN_WARNING "%s: class_device_create_file error: %d\n", | ||
821 | __FUNCTION__, ret); | ||
822 | } else { | ||
823 | sfp->v4l_radio_minor_number_created_ok = !0; | ||
824 | } | ||
825 | |||
796 | sfp->attr_unit_number.attr.owner = THIS_MODULE; | 826 | sfp->attr_unit_number.attr.owner = THIS_MODULE; |
797 | sfp->attr_unit_number.attr.name = "unit_number"; | 827 | sfp->attr_unit_number.attr.name = "unit_number"; |
798 | sfp->attr_unit_number.attr.mode = S_IRUGO; | 828 | sfp->attr_unit_number.attr.mode = S_IRUGO; |
@@ -829,9 +859,8 @@ struct pvr2_sysfs *pvr2_sysfs_create(struct pvr2_context *mp, | |||
829 | struct pvr2_sysfs_class *class_ptr) | 859 | struct pvr2_sysfs_class *class_ptr) |
830 | { | 860 | { |
831 | struct pvr2_sysfs *sfp; | 861 | struct pvr2_sysfs *sfp; |
832 | sfp = kmalloc(sizeof(*sfp),GFP_KERNEL); | 862 | sfp = kzalloc(sizeof(*sfp),GFP_KERNEL); |
833 | if (!sfp) return sfp; | 863 | if (!sfp) return sfp; |
834 | memset(sfp,0,sizeof(*sfp)); | ||
835 | pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_sysfs id=%p",sfp); | 864 | pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_sysfs id=%p",sfp); |
836 | pvr2_channel_init(&sfp->channel,mp); | 865 | pvr2_channel_init(&sfp->channel,mp); |
837 | sfp->channel.check_func = pvr2_sysfs_internal_check; | 866 | sfp->channel.check_func = pvr2_sysfs_internal_check; |
@@ -852,9 +881,8 @@ static int pvr2_sysfs_hotplug(struct class_device *cd,char **envp, | |||
852 | struct pvr2_sysfs_class *pvr2_sysfs_class_create(void) | 881 | struct pvr2_sysfs_class *pvr2_sysfs_class_create(void) |
853 | { | 882 | { |
854 | struct pvr2_sysfs_class *clp; | 883 | struct pvr2_sysfs_class *clp; |
855 | clp = kmalloc(sizeof(*clp),GFP_KERNEL); | 884 | clp = kzalloc(sizeof(*clp),GFP_KERNEL); |
856 | if (!clp) return clp; | 885 | if (!clp) return clp; |
857 | memset(clp,0,sizeof(*clp)); | ||
858 | pvr2_sysfs_trace("Creating pvr2_sysfs_class id=%p",clp); | 886 | pvr2_sysfs_trace("Creating pvr2_sysfs_class id=%p",clp); |
859 | clp->class.name = "pvrusb2"; | 887 | clp->class.name = "pvrusb2"; |
860 | clp->class.class_release = pvr2_sysfs_class_release; | 888 | clp->class.class_release = pvr2_sysfs_class_release; |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-tuner.c b/drivers/media/video/pvrusb2/pvrusb2-tuner.c index bb17db3f6434..05e65ce2e3a9 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-tuner.c +++ b/drivers/media/video/pvrusb2/pvrusb2-tuner.c | |||
@@ -93,9 +93,8 @@ int pvr2_i2c_tuner_setup(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp) | |||
93 | struct pvr2_tuner_handler *ctxt; | 93 | struct pvr2_tuner_handler *ctxt; |
94 | if (cp->handler) return 0; | 94 | if (cp->handler) return 0; |
95 | 95 | ||
96 | ctxt = kmalloc(sizeof(*ctxt),GFP_KERNEL); | 96 | ctxt = kzalloc(sizeof(*ctxt),GFP_KERNEL); |
97 | if (!ctxt) return 0; | 97 | if (!ctxt) return 0; |
98 | memset(ctxt,0,sizeof(*ctxt)); | ||
99 | 98 | ||
100 | ctxt->i2c_handler.func_data = ctxt; | 99 | ctxt->i2c_handler.func_data = ctxt; |
101 | ctxt->i2c_handler.func_table = &tuner_funcs; | 100 | ctxt->i2c_handler.func_table = &tuner_funcs; |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c index 6cf17080eb49..4fe4136204c7 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c +++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c | |||
@@ -40,7 +40,10 @@ struct pvr2_v4l2_dev { | |||
40 | struct video_device devbase; /* MUST be first! */ | 40 | struct video_device devbase; /* MUST be first! */ |
41 | struct pvr2_v4l2 *v4lp; | 41 | struct pvr2_v4l2 *v4lp; |
42 | struct pvr2_context_stream *stream; | 42 | struct pvr2_context_stream *stream; |
43 | enum pvr2_config config; | 43 | /* Information about this device: */ |
44 | enum pvr2_config config; /* Expected stream format */ | ||
45 | int v4l_type; /* V4L defined type for this device node */ | ||
46 | enum pvr2_v4l_type minor_type; /* pvr2-understood minor device type */ | ||
44 | }; | 47 | }; |
45 | 48 | ||
46 | struct pvr2_v4l2_fh { | 49 | struct pvr2_v4l2_fh { |
@@ -54,6 +57,7 @@ struct pvr2_v4l2_fh { | |||
54 | struct pvr2_v4l2_fh *vprev; | 57 | struct pvr2_v4l2_fh *vprev; |
55 | wait_queue_head_t wait_data; | 58 | wait_queue_head_t wait_data; |
56 | int fw_mode_flag; | 59 | int fw_mode_flag; |
60 | int prev_input_val; | ||
57 | }; | 61 | }; |
58 | 62 | ||
59 | struct pvr2_v4l2 { | 63 | struct pvr2_v4l2 { |
@@ -63,13 +67,22 @@ struct pvr2_v4l2 { | |||
63 | 67 | ||
64 | struct v4l2_prio_state prio; | 68 | struct v4l2_prio_state prio; |
65 | 69 | ||
66 | /* streams */ | 70 | /* streams - Note that these must be separately, individually, |
67 | struct pvr2_v4l2_dev *vdev; | 71 | * allocated pointers. This is because the v4l core is going to |
72 | * manage their deletion - separately, individually... */ | ||
73 | struct pvr2_v4l2_dev *dev_video; | ||
74 | struct pvr2_v4l2_dev *dev_radio; | ||
68 | }; | 75 | }; |
69 | 76 | ||
70 | static int video_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1}; | 77 | static int video_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1}; |
71 | module_param_array(video_nr, int, NULL, 0444); | 78 | module_param_array(video_nr, int, NULL, 0444); |
72 | MODULE_PARM_DESC(video_nr, "Offset for device's minor"); | 79 | MODULE_PARM_DESC(video_nr, "Offset for device's video dev minor"); |
80 | static int radio_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1}; | ||
81 | module_param_array(radio_nr, int, NULL, 0444); | ||
82 | MODULE_PARM_DESC(radio_nr, "Offset for device's radio dev minor"); | ||
83 | static int vbi_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1}; | ||
84 | module_param_array(vbi_nr, int, NULL, 0444); | ||
85 | MODULE_PARM_DESC(vbi_nr, "Offset for device's vbi dev minor"); | ||
73 | 86 | ||
74 | static struct v4l2_capability pvr_capability ={ | 87 | static struct v4l2_capability pvr_capability ={ |
75 | .driver = "pvrusb2", | 88 | .driver = "pvrusb2", |
@@ -77,30 +90,11 @@ static struct v4l2_capability pvr_capability ={ | |||
77 | .bus_info = "usb", | 90 | .bus_info = "usb", |
78 | .version = KERNEL_VERSION(0,8,0), | 91 | .version = KERNEL_VERSION(0,8,0), |
79 | .capabilities = (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VBI_CAPTURE | | 92 | .capabilities = (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VBI_CAPTURE | |
80 | V4L2_CAP_TUNER | V4L2_CAP_AUDIO | | 93 | V4L2_CAP_TUNER | V4L2_CAP_AUDIO | V4L2_CAP_RADIO | |
81 | V4L2_CAP_READWRITE), | 94 | V4L2_CAP_READWRITE), |
82 | .reserved = {0,0,0,0} | 95 | .reserved = {0,0,0,0} |
83 | }; | 96 | }; |
84 | 97 | ||
85 | static struct v4l2_tuner pvr_v4l2_tuners[]= { | ||
86 | { | ||
87 | .index = 0, | ||
88 | .name = "TV Tuner", | ||
89 | .type = V4L2_TUNER_ANALOG_TV, | ||
90 | .capability = (V4L2_TUNER_CAP_NORM | | ||
91 | V4L2_TUNER_CAP_STEREO | | ||
92 | V4L2_TUNER_CAP_LANG1 | | ||
93 | V4L2_TUNER_CAP_LANG2), | ||
94 | .rangelow = 0, | ||
95 | .rangehigh = 0, | ||
96 | .rxsubchans = V4L2_TUNER_SUB_STEREO, | ||
97 | .audmode = V4L2_TUNER_MODE_STEREO, | ||
98 | .signal = 0, | ||
99 | .afc = 0, | ||
100 | .reserved = {0,0,0,0} | ||
101 | } | ||
102 | }; | ||
103 | |||
104 | static struct v4l2_fmtdesc pvr_fmtdesc [] = { | 98 | static struct v4l2_fmtdesc pvr_fmtdesc [] = { |
105 | { | 99 | { |
106 | .index = 0, | 100 | .index = 0, |
@@ -154,6 +148,18 @@ static struct v4l2_format pvr_format [] = { | |||
154 | } | 148 | } |
155 | }; | 149 | }; |
156 | 150 | ||
151 | |||
152 | static const char *get_v4l_name(int v4l_type) | ||
153 | { | ||
154 | switch (v4l_type) { | ||
155 | case VFL_TYPE_GRABBER: return "video"; | ||
156 | case VFL_TYPE_RADIO: return "radio"; | ||
157 | case VFL_TYPE_VBI: return "vbi"; | ||
158 | default: return "?"; | ||
159 | } | ||
160 | } | ||
161 | |||
162 | |||
157 | /* | 163 | /* |
158 | * pvr_ioctl() | 164 | * pvr_ioctl() |
159 | * | 165 | * |
@@ -315,13 +321,39 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, | |||
315 | 321 | ||
316 | case VIDIOC_ENUMAUDIO: | 322 | case VIDIOC_ENUMAUDIO: |
317 | { | 323 | { |
324 | /* pkt: FIXME: We are returning one "fake" input here | ||
325 | which could very well be called "whatever_we_like". | ||
326 | This is for apps that want to see an audio input | ||
327 | just to feel comfortable, as well as to test if | ||
328 | it can do stereo or sth. There is actually no guarantee | ||
329 | that the actual audio input cannot change behind the app's | ||
330 | back, but most applications should not mind that either. | ||
331 | |||
332 | Hopefully, mplayer people will work with us on this (this | ||
333 | whole mess is to support mplayer pvr://), or Hans will come | ||
334 | up with a more standard way to say "we have inputs but we | ||
335 | don 't want you to change them independent of video" which | ||
336 | will sort this mess. | ||
337 | */ | ||
338 | struct v4l2_audio *vin = arg; | ||
318 | ret = -EINVAL; | 339 | ret = -EINVAL; |
340 | if (vin->index > 0) break; | ||
341 | strncpy(vin->name, "PVRUSB2 Audio",14); | ||
342 | vin->capability = V4L2_AUDCAP_STEREO; | ||
343 | ret = 0; | ||
344 | break; | ||
319 | break; | 345 | break; |
320 | } | 346 | } |
321 | 347 | ||
322 | case VIDIOC_G_AUDIO: | 348 | case VIDIOC_G_AUDIO: |
323 | { | 349 | { |
324 | ret = -EINVAL; | 350 | /* pkt: FIXME: see above comment (VIDIOC_ENUMAUDIO) */ |
351 | struct v4l2_audio *vin = arg; | ||
352 | memset(vin,0,sizeof(*vin)); | ||
353 | vin->index = 0; | ||
354 | strncpy(vin->name, "PVRUSB2 Audio",14); | ||
355 | vin->capability = V4L2_AUDCAP_STEREO; | ||
356 | ret = 0; | ||
325 | break; | 357 | break; |
326 | } | 358 | } |
327 | 359 | ||
@@ -333,34 +365,11 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, | |||
333 | case VIDIOC_G_TUNER: | 365 | case VIDIOC_G_TUNER: |
334 | { | 366 | { |
335 | struct v4l2_tuner *vt = (struct v4l2_tuner *)arg; | 367 | struct v4l2_tuner *vt = (struct v4l2_tuner *)arg; |
336 | unsigned int status_mask; | ||
337 | int val; | ||
338 | if (vt->index !=0) break; | ||
339 | 368 | ||
340 | status_mask = pvr2_hdw_get_signal_status(hdw); | 369 | if (vt->index != 0) break; /* Only answer for the 1st tuner */ |
341 | 370 | ||
342 | memcpy(vt, &pvr_v4l2_tuners[vt->index], | 371 | pvr2_hdw_execute_tuner_poll(hdw); |
343 | sizeof(struct v4l2_tuner)); | 372 | ret = pvr2_hdw_get_tuner_status(hdw,vt); |
344 | |||
345 | vt->signal = 0; | ||
346 | if (status_mask & PVR2_SIGNAL_OK) { | ||
347 | if (status_mask & PVR2_SIGNAL_STEREO) { | ||
348 | vt->rxsubchans = V4L2_TUNER_SUB_STEREO; | ||
349 | } else { | ||
350 | vt->rxsubchans = V4L2_TUNER_SUB_MONO; | ||
351 | } | ||
352 | if (status_mask & PVR2_SIGNAL_SAP) { | ||
353 | vt->rxsubchans |= (V4L2_TUNER_SUB_LANG1 | | ||
354 | V4L2_TUNER_SUB_LANG2); | ||
355 | } | ||
356 | vt->signal = 65535; | ||
357 | } | ||
358 | |||
359 | val = 0; | ||
360 | ret = pvr2_ctrl_get_value( | ||
361 | pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_AUDIOMODE), | ||
362 | &val); | ||
363 | vt->audmode = val; | ||
364 | break; | 373 | break; |
365 | } | 374 | } |
366 | 375 | ||
@@ -374,14 +383,40 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, | |||
374 | ret = pvr2_ctrl_set_value( | 383 | ret = pvr2_ctrl_set_value( |
375 | pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_AUDIOMODE), | 384 | pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_AUDIOMODE), |
376 | vt->audmode); | 385 | vt->audmode); |
386 | break; | ||
377 | } | 387 | } |
378 | 388 | ||
379 | case VIDIOC_S_FREQUENCY: | 389 | case VIDIOC_S_FREQUENCY: |
380 | { | 390 | { |
381 | const struct v4l2_frequency *vf = (struct v4l2_frequency *)arg; | 391 | const struct v4l2_frequency *vf = (struct v4l2_frequency *)arg; |
392 | unsigned long fv; | ||
393 | struct v4l2_tuner vt; | ||
394 | int cur_input; | ||
395 | struct pvr2_ctrl *ctrlp; | ||
396 | ret = pvr2_hdw_get_tuner_status(hdw,&vt); | ||
397 | if (ret != 0) break; | ||
398 | ctrlp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT); | ||
399 | ret = pvr2_ctrl_get_value(ctrlp,&cur_input); | ||
400 | if (ret != 0) break; | ||
401 | if (vf->type == V4L2_TUNER_RADIO) { | ||
402 | if (cur_input != PVR2_CVAL_INPUT_RADIO) { | ||
403 | pvr2_ctrl_set_value(ctrlp, | ||
404 | PVR2_CVAL_INPUT_RADIO); | ||
405 | } | ||
406 | } else { | ||
407 | if (cur_input == PVR2_CVAL_INPUT_RADIO) { | ||
408 | pvr2_ctrl_set_value(ctrlp, | ||
409 | PVR2_CVAL_INPUT_TV); | ||
410 | } | ||
411 | } | ||
412 | fv = vf->frequency; | ||
413 | if (vt.capability & V4L2_TUNER_CAP_LOW) { | ||
414 | fv = (fv * 125) / 2; | ||
415 | } else { | ||
416 | fv = fv * 62500; | ||
417 | } | ||
382 | ret = pvr2_ctrl_set_value( | 418 | ret = pvr2_ctrl_set_value( |
383 | pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY), | 419 | pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY),fv); |
384 | vf->frequency * 62500); | ||
385 | break; | 420 | break; |
386 | } | 421 | } |
387 | 422 | ||
@@ -389,10 +424,27 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, | |||
389 | { | 424 | { |
390 | struct v4l2_frequency *vf = (struct v4l2_frequency *)arg; | 425 | struct v4l2_frequency *vf = (struct v4l2_frequency *)arg; |
391 | int val = 0; | 426 | int val = 0; |
427 | int cur_input; | ||
428 | struct v4l2_tuner vt; | ||
429 | ret = pvr2_hdw_get_tuner_status(hdw,&vt); | ||
430 | if (ret != 0) break; | ||
392 | ret = pvr2_ctrl_get_value( | 431 | ret = pvr2_ctrl_get_value( |
393 | pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY), | 432 | pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY), |
394 | &val); | 433 | &val); |
395 | val /= 62500; | 434 | if (ret != 0) break; |
435 | pvr2_ctrl_get_value( | ||
436 | pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT), | ||
437 | &cur_input); | ||
438 | if (cur_input == PVR2_CVAL_INPUT_RADIO) { | ||
439 | vf->type = V4L2_TUNER_RADIO; | ||
440 | } else { | ||
441 | vf->type = V4L2_TUNER_ANALOG_TV; | ||
442 | } | ||
443 | if (vt.capability & V4L2_TUNER_CAP_LOW) { | ||
444 | val = (val * 2) / 125; | ||
445 | } else { | ||
446 | val /= 62500; | ||
447 | } | ||
396 | vf->frequency = val; | 448 | vf->frequency = val; |
397 | break; | 449 | break; |
398 | } | 450 | } |
@@ -449,7 +501,7 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, | |||
449 | ret = 0; | 501 | ret = 0; |
450 | switch(vf->type) { | 502 | switch(vf->type) { |
451 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: { | 503 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: { |
452 | int lmin,lmax; | 504 | int lmin,lmax,ldef; |
453 | struct pvr2_ctrl *hcp,*vcp; | 505 | struct pvr2_ctrl *hcp,*vcp; |
454 | int h = vf->fmt.pix.height; | 506 | int h = vf->fmt.pix.height; |
455 | int w = vf->fmt.pix.width; | 507 | int w = vf->fmt.pix.width; |
@@ -458,14 +510,20 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, | |||
458 | 510 | ||
459 | lmin = pvr2_ctrl_get_min(hcp); | 511 | lmin = pvr2_ctrl_get_min(hcp); |
460 | lmax = pvr2_ctrl_get_max(hcp); | 512 | lmax = pvr2_ctrl_get_max(hcp); |
461 | if (w < lmin) { | 513 | ldef = pvr2_ctrl_get_def(hcp); |
514 | if (w == -1) { | ||
515 | w = ldef; | ||
516 | } else if (w < lmin) { | ||
462 | w = lmin; | 517 | w = lmin; |
463 | } else if (w > lmax) { | 518 | } else if (w > lmax) { |
464 | w = lmax; | 519 | w = lmax; |
465 | } | 520 | } |
466 | lmin = pvr2_ctrl_get_min(vcp); | 521 | lmin = pvr2_ctrl_get_min(vcp); |
467 | lmax = pvr2_ctrl_get_max(vcp); | 522 | lmax = pvr2_ctrl_get_max(vcp); |
468 | if (h < lmin) { | 523 | ldef = pvr2_ctrl_get_def(vcp); |
524 | if (h == -1) { | ||
525 | h = ldef; | ||
526 | } else if (h < lmin) { | ||
469 | h = lmin; | 527 | h = lmin; |
470 | } else if (h > lmax) { | 528 | } else if (h > lmax) { |
471 | h = lmax; | 529 | h = lmax; |
@@ -494,6 +552,13 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, | |||
494 | 552 | ||
495 | case VIDIOC_STREAMON: | 553 | case VIDIOC_STREAMON: |
496 | { | 554 | { |
555 | if (!fh->dev_info->stream) { | ||
556 | /* No stream defined for this node. This means | ||
557 | that we're not currently allowed to stream from | ||
558 | this node. */ | ||
559 | ret = -EPERM; | ||
560 | break; | ||
561 | } | ||
497 | ret = pvr2_hdw_set_stream_type(hdw,dev_info->config); | 562 | ret = pvr2_hdw_set_stream_type(hdw,dev_info->config); |
498 | if (ret < 0) return ret; | 563 | if (ret < 0) return ret; |
499 | ret = pvr2_hdw_set_streaming(hdw,!0); | 564 | ret = pvr2_hdw_set_streaming(hdw,!0); |
@@ -502,6 +567,13 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, | |||
502 | 567 | ||
503 | case VIDIOC_STREAMOFF: | 568 | case VIDIOC_STREAMOFF: |
504 | { | 569 | { |
570 | if (!fh->dev_info->stream) { | ||
571 | /* No stream defined for this node. This means | ||
572 | that we're not currently allowed to stream from | ||
573 | this node. */ | ||
574 | ret = -EPERM; | ||
575 | break; | ||
576 | } | ||
505 | ret = pvr2_hdw_set_streaming(hdw,0); | 577 | ret = pvr2_hdw_set_streaming(hdw,0); |
506 | break; | 578 | break; |
507 | } | 579 | } |
@@ -599,6 +671,7 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, | |||
599 | struct v4l2_ext_control *ctrl; | 671 | struct v4l2_ext_control *ctrl; |
600 | unsigned int idx; | 672 | unsigned int idx; |
601 | int val; | 673 | int val; |
674 | ret = 0; | ||
602 | for (idx = 0; idx < ctls->count; idx++) { | 675 | for (idx = 0; idx < ctls->count; idx++) { |
603 | ctrl = ctls->controls + idx; | 676 | ctrl = ctls->controls + idx; |
604 | ret = pvr2_ctrl_get_value( | 677 | ret = pvr2_ctrl_get_value( |
@@ -621,6 +694,7 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, | |||
621 | (struct v4l2_ext_controls *)arg; | 694 | (struct v4l2_ext_controls *)arg; |
622 | struct v4l2_ext_control *ctrl; | 695 | struct v4l2_ext_control *ctrl; |
623 | unsigned int idx; | 696 | unsigned int idx; |
697 | ret = 0; | ||
624 | for (idx = 0; idx < ctls->count; idx++) { | 698 | for (idx = 0; idx < ctls->count; idx++) { |
625 | ctrl = ctls->controls + idx; | 699 | ctrl = ctls->controls + idx; |
626 | ret = pvr2_ctrl_set_value( | 700 | ret = pvr2_ctrl_set_value( |
@@ -643,6 +717,7 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, | |||
643 | unsigned int idx; | 717 | unsigned int idx; |
644 | /* For the moment just validate that the requested control | 718 | /* For the moment just validate that the requested control |
645 | actually exists. */ | 719 | actually exists. */ |
720 | ret = 0; | ||
646 | for (idx = 0; idx < ctls->count; idx++) { | 721 | for (idx = 0; idx < ctls->count; idx++) { |
647 | ctrl = ctls->controls + idx; | 722 | ctrl = ctls->controls + idx; |
648 | pctl = pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id); | 723 | pctl = pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id); |
@@ -662,16 +737,16 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, | |||
662 | break; | 737 | break; |
663 | } | 738 | } |
664 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 739 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
665 | case VIDIOC_INT_G_REGISTER: | 740 | case VIDIOC_DBG_S_REGISTER: |
666 | case VIDIOC_INT_S_REGISTER: | 741 | case VIDIOC_DBG_G_REGISTER: |
667 | { | 742 | { |
668 | u32 val; | 743 | u32 val; |
669 | struct v4l2_register *req = (struct v4l2_register *)arg; | 744 | struct v4l2_register *req = (struct v4l2_register *)arg; |
670 | if (cmd == VIDIOC_INT_S_REGISTER) val = req->val; | 745 | if (cmd == VIDIOC_DBG_S_REGISTER) val = req->val; |
671 | ret = pvr2_hdw_register_access( | 746 | ret = pvr2_hdw_register_access( |
672 | hdw,req->i2c_id,req->reg, | 747 | hdw,req->i2c_id,req->reg, |
673 | cmd == VIDIOC_INT_S_REGISTER,&val); | 748 | cmd == VIDIOC_DBG_S_REGISTER,&val); |
674 | if (cmd == VIDIOC_INT_G_REGISTER) req->val = val; | 749 | if (cmd == VIDIOC_DBG_G_REGISTER) req->val = val; |
675 | break; | 750 | break; |
676 | } | 751 | } |
677 | #endif | 752 | #endif |
@@ -707,8 +782,12 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, | |||
707 | 782 | ||
708 | static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip) | 783 | static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip) |
709 | { | 784 | { |
710 | printk(KERN_INFO "pvrusb2: unregistering device video%d [%s]\n", | 785 | int minor_id = dip->devbase.minor; |
711 | dip->devbase.minor,pvr2_config_get_name(dip->config)); | 786 | struct pvr2_hdw *hdw = dip->v4lp->channel.mc_head->hdw; |
787 | enum pvr2_config cfg = dip->config; | ||
788 | int v4l_type = dip->v4l_type; | ||
789 | |||
790 | pvr2_hdw_v4l_store_minor_number(hdw,dip->minor_type,-1); | ||
712 | 791 | ||
713 | /* Paranoia */ | 792 | /* Paranoia */ |
714 | dip->v4lp = NULL; | 793 | dip->v4lp = NULL; |
@@ -717,13 +796,24 @@ static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip) | |||
717 | /* Actual deallocation happens later when all internal references | 796 | /* Actual deallocation happens later when all internal references |
718 | are gone. */ | 797 | are gone. */ |
719 | video_unregister_device(&dip->devbase); | 798 | video_unregister_device(&dip->devbase); |
799 | |||
800 | printk(KERN_INFO "pvrusb2: unregistered device %s%u [%s]\n", | ||
801 | get_v4l_name(v4l_type),minor_id & 0x1f, | ||
802 | pvr2_config_get_name(cfg)); | ||
803 | |||
720 | } | 804 | } |
721 | 805 | ||
722 | 806 | ||
723 | static void pvr2_v4l2_destroy_no_lock(struct pvr2_v4l2 *vp) | 807 | static void pvr2_v4l2_destroy_no_lock(struct pvr2_v4l2 *vp) |
724 | { | 808 | { |
725 | pvr2_hdw_v4l_store_minor_number(vp->channel.mc_head->hdw,-1); | 809 | if (vp->dev_video) { |
726 | pvr2_v4l2_dev_destroy(vp->vdev); | 810 | pvr2_v4l2_dev_destroy(vp->dev_video); |
811 | vp->dev_video = 0; | ||
812 | } | ||
813 | if (vp->dev_radio) { | ||
814 | pvr2_v4l2_dev_destroy(vp->dev_radio); | ||
815 | vp->dev_radio = 0; | ||
816 | } | ||
727 | 817 | ||
728 | pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr2_v4l2 id=%p",vp); | 818 | pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr2_v4l2 id=%p",vp); |
729 | pvr2_channel_done(&vp->channel); | 819 | pvr2_channel_done(&vp->channel); |
@@ -766,23 +856,37 @@ static int pvr2_v4l2_release(struct inode *inode, struct file *file) | |||
766 | struct pvr2_v4l2_fh *fhp = file->private_data; | 856 | struct pvr2_v4l2_fh *fhp = file->private_data; |
767 | struct pvr2_v4l2 *vp = fhp->vhead; | 857 | struct pvr2_v4l2 *vp = fhp->vhead; |
768 | struct pvr2_context *mp = fhp->vhead->channel.mc_head; | 858 | struct pvr2_context *mp = fhp->vhead->channel.mc_head; |
859 | struct pvr2_hdw *hdw = fhp->channel.mc_head->hdw; | ||
769 | 860 | ||
770 | pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_release"); | 861 | pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_release"); |
771 | 862 | ||
772 | if (fhp->rhp) { | 863 | if (fhp->rhp) { |
773 | struct pvr2_stream *sp; | 864 | struct pvr2_stream *sp; |
774 | struct pvr2_hdw *hdw; | ||
775 | hdw = fhp->channel.mc_head->hdw; | ||
776 | pvr2_hdw_set_streaming(hdw,0); | 865 | pvr2_hdw_set_streaming(hdw,0); |
777 | sp = pvr2_ioread_get_stream(fhp->rhp); | 866 | sp = pvr2_ioread_get_stream(fhp->rhp); |
778 | if (sp) pvr2_stream_set_callback(sp,NULL,NULL); | 867 | if (sp) pvr2_stream_set_callback(sp,NULL,NULL); |
779 | pvr2_ioread_destroy(fhp->rhp); | 868 | pvr2_ioread_destroy(fhp->rhp); |
780 | fhp->rhp = NULL; | 869 | fhp->rhp = NULL; |
781 | } | 870 | } |
871 | |||
782 | v4l2_prio_close(&vp->prio, &fhp->prio); | 872 | v4l2_prio_close(&vp->prio, &fhp->prio); |
783 | file->private_data = NULL; | 873 | file->private_data = NULL; |
784 | 874 | ||
785 | pvr2_context_enter(mp); do { | 875 | pvr2_context_enter(mp); do { |
876 | /* Restore the previous input selection, if it makes sense | ||
877 | to do so. */ | ||
878 | if (fhp->dev_info->v4l_type == VFL_TYPE_RADIO) { | ||
879 | struct pvr2_ctrl *cp; | ||
880 | int pval; | ||
881 | cp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT); | ||
882 | pvr2_ctrl_get_value(cp,&pval); | ||
883 | /* Only restore if we're still selecting the radio */ | ||
884 | if (pval == PVR2_CVAL_INPUT_RADIO) { | ||
885 | pvr2_ctrl_set_value(cp,fhp->prev_input_val); | ||
886 | pvr2_hdw_commit_ctl(hdw); | ||
887 | } | ||
888 | } | ||
889 | |||
786 | if (fhp->vnext) { | 890 | if (fhp->vnext) { |
787 | fhp->vnext->vprev = fhp->vprev; | 891 | fhp->vnext->vprev = fhp->vprev; |
788 | } else { | 892 | } else { |
@@ -828,11 +932,10 @@ static int pvr2_v4l2_open(struct inode *inode, struct file *file) | |||
828 | return -EIO; | 932 | return -EIO; |
829 | } | 933 | } |
830 | 934 | ||
831 | fhp = kmalloc(sizeof(*fhp),GFP_KERNEL); | 935 | fhp = kzalloc(sizeof(*fhp),GFP_KERNEL); |
832 | if (!fhp) { | 936 | if (!fhp) { |
833 | return -ENOMEM; | 937 | return -ENOMEM; |
834 | } | 938 | } |
835 | memset(fhp,0,sizeof(*fhp)); | ||
836 | 939 | ||
837 | init_waitqueue_head(&fhp->wait_data); | 940 | init_waitqueue_head(&fhp->wait_data); |
838 | fhp->dev_info = dip; | 941 | fhp->dev_info = dip; |
@@ -840,6 +943,7 @@ static int pvr2_v4l2_open(struct inode *inode, struct file *file) | |||
840 | pvr2_context_enter(vp->channel.mc_head); do { | 943 | pvr2_context_enter(vp->channel.mc_head); do { |
841 | pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_v4l2_fh id=%p",fhp); | 944 | pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_v4l2_fh id=%p",fhp); |
842 | pvr2_channel_init(&fhp->channel,vp->channel.mc_head); | 945 | pvr2_channel_init(&fhp->channel,vp->channel.mc_head); |
946 | |||
843 | fhp->vnext = NULL; | 947 | fhp->vnext = NULL; |
844 | fhp->vprev = vp->vlast; | 948 | fhp->vprev = vp->vlast; |
845 | if (vp->vlast) { | 949 | if (vp->vlast) { |
@@ -849,6 +953,18 @@ static int pvr2_v4l2_open(struct inode *inode, struct file *file) | |||
849 | } | 953 | } |
850 | vp->vlast = fhp; | 954 | vp->vlast = fhp; |
851 | fhp->vhead = vp; | 955 | fhp->vhead = vp; |
956 | |||
957 | /* Opening the /dev/radioX device implies a mode switch. | ||
958 | So execute that here. Note that you can get the | ||
959 | IDENTICAL effect merely by opening the normal video | ||
960 | device and setting the input appropriately. */ | ||
961 | if (dip->v4l_type == VFL_TYPE_RADIO) { | ||
962 | struct pvr2_ctrl *cp; | ||
963 | cp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT); | ||
964 | pvr2_ctrl_get_value(cp,&fhp->prev_input_val); | ||
965 | pvr2_ctrl_set_value(cp,PVR2_CVAL_INPUT_RADIO); | ||
966 | pvr2_hdw_commit_ctl(hdw); | ||
967 | } | ||
852 | } while (0); pvr2_context_exit(vp->channel.mc_head); | 968 | } while (0); pvr2_context_exit(vp->channel.mc_head); |
853 | 969 | ||
854 | fhp->file = file; | 970 | fhp->file = file; |
@@ -873,6 +989,12 @@ static int pvr2_v4l2_iosetup(struct pvr2_v4l2_fh *fh) | |||
873 | struct pvr2_hdw *hdw; | 989 | struct pvr2_hdw *hdw; |
874 | if (fh->rhp) return 0; | 990 | if (fh->rhp) return 0; |
875 | 991 | ||
992 | if (!fh->dev_info->stream) { | ||
993 | /* No stream defined for this node. This means that we're | ||
994 | not currently allowed to stream from this node. */ | ||
995 | return -EPERM; | ||
996 | } | ||
997 | |||
876 | /* First read() attempt. Try to claim the stream and start | 998 | /* First read() attempt. Try to claim the stream and start |
877 | it... */ | 999 | it... */ |
878 | if ((ret = pvr2_channel_claim_stream(&fh->channel, | 1000 | if ((ret = pvr2_channel_claim_stream(&fh->channel, |
@@ -1012,25 +1134,37 @@ static struct video_device vdev_template = { | |||
1012 | 1134 | ||
1013 | static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip, | 1135 | static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip, |
1014 | struct pvr2_v4l2 *vp, | 1136 | struct pvr2_v4l2 *vp, |
1015 | enum pvr2_config cfg) | 1137 | int v4l_type) |
1016 | { | 1138 | { |
1017 | int mindevnum; | 1139 | int mindevnum; |
1018 | int unit_number; | 1140 | int unit_number; |
1019 | int v4l_type; | 1141 | int *nr_ptr = 0; |
1020 | dip->v4lp = vp; | 1142 | dip->v4lp = vp; |
1021 | dip->config = cfg; | ||
1022 | 1143 | ||
1023 | 1144 | ||
1024 | switch (cfg) { | 1145 | dip->v4l_type = v4l_type; |
1025 | case pvr2_config_mpeg: | 1146 | switch (v4l_type) { |
1026 | v4l_type = VFL_TYPE_GRABBER; | 1147 | case VFL_TYPE_GRABBER: |
1027 | dip->stream = &vp->channel.mc_head->video_stream; | 1148 | dip->stream = &vp->channel.mc_head->video_stream; |
1149 | dip->config = pvr2_config_mpeg; | ||
1150 | dip->minor_type = pvr2_v4l_type_video; | ||
1151 | nr_ptr = video_nr; | ||
1152 | if (!dip->stream) { | ||
1153 | err("Failed to set up pvrusb2 v4l video dev" | ||
1154 | " due to missing stream instance"); | ||
1155 | return; | ||
1156 | } | ||
1028 | break; | 1157 | break; |
1029 | case pvr2_config_vbi: | 1158 | case VFL_TYPE_VBI: |
1030 | v4l_type = VFL_TYPE_VBI; | 1159 | dip->config = pvr2_config_vbi; |
1160 | dip->minor_type = pvr2_v4l_type_vbi; | ||
1161 | nr_ptr = vbi_nr; | ||
1031 | break; | 1162 | break; |
1032 | case pvr2_config_radio: | 1163 | case VFL_TYPE_RADIO: |
1033 | v4l_type = VFL_TYPE_RADIO; | 1164 | dip->stream = &vp->channel.mc_head->video_stream; |
1165 | dip->config = pvr2_config_mpeg; | ||
1166 | dip->minor_type = pvr2_v4l_type_radio; | ||
1167 | nr_ptr = radio_nr; | ||
1034 | break; | 1168 | break; |
1035 | default: | 1169 | default: |
1036 | /* Bail out (this should be impossible) */ | 1170 | /* Bail out (this should be impossible) */ |
@@ -1039,30 +1173,27 @@ static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip, | |||
1039 | return; | 1173 | return; |
1040 | } | 1174 | } |
1041 | 1175 | ||
1042 | if (!dip->stream) { | ||
1043 | err("Failed to set up pvrusb2 v4l dev" | ||
1044 | " due to missing stream instance"); | ||
1045 | return; | ||
1046 | } | ||
1047 | |||
1048 | memcpy(&dip->devbase,&vdev_template,sizeof(vdev_template)); | 1176 | memcpy(&dip->devbase,&vdev_template,sizeof(vdev_template)); |
1049 | dip->devbase.release = pvr2_video_device_release; | 1177 | dip->devbase.release = pvr2_video_device_release; |
1050 | 1178 | ||
1051 | mindevnum = -1; | 1179 | mindevnum = -1; |
1052 | unit_number = pvr2_hdw_get_unit_number(vp->channel.mc_head->hdw); | 1180 | unit_number = pvr2_hdw_get_unit_number(vp->channel.mc_head->hdw); |
1053 | if ((unit_number >= 0) && (unit_number < PVR_NUM)) { | 1181 | if (nr_ptr && (unit_number >= 0) && (unit_number < PVR_NUM)) { |
1054 | mindevnum = video_nr[unit_number]; | 1182 | mindevnum = nr_ptr[unit_number]; |
1055 | } | 1183 | } |
1056 | if ((video_register_device(&dip->devbase, v4l_type, mindevnum) < 0) && | 1184 | if ((video_register_device(&dip->devbase, |
1057 | (video_register_device(&dip->devbase, v4l_type, -1) < 0)) { | 1185 | dip->v4l_type, mindevnum) < 0) && |
1058 | err("Failed to register pvrusb2 v4l video device"); | 1186 | (video_register_device(&dip->devbase, |
1059 | } else { | 1187 | dip->v4l_type, -1) < 0)) { |
1060 | printk(KERN_INFO "pvrusb2: registered device video%d [%s]\n", | 1188 | err("Failed to register pvrusb2 v4l device"); |
1061 | dip->devbase.minor,pvr2_config_get_name(dip->config)); | ||
1062 | } | 1189 | } |
1063 | 1190 | ||
1191 | printk(KERN_INFO "pvrusb2: registered device %s%u [%s]\n", | ||
1192 | get_v4l_name(dip->v4l_type),dip->devbase.minor & 0x1f, | ||
1193 | pvr2_config_get_name(dip->config)); | ||
1194 | |||
1064 | pvr2_hdw_v4l_store_minor_number(vp->channel.mc_head->hdw, | 1195 | pvr2_hdw_v4l_store_minor_number(vp->channel.mc_head->hdw, |
1065 | dip->devbase.minor); | 1196 | dip->minor_type,dip->devbase.minor); |
1066 | } | 1197 | } |
1067 | 1198 | ||
1068 | 1199 | ||
@@ -1070,22 +1201,24 @@ struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *mnp) | |||
1070 | { | 1201 | { |
1071 | struct pvr2_v4l2 *vp; | 1202 | struct pvr2_v4l2 *vp; |
1072 | 1203 | ||
1073 | vp = kmalloc(sizeof(*vp),GFP_KERNEL); | 1204 | vp = kzalloc(sizeof(*vp),GFP_KERNEL); |
1074 | if (!vp) return vp; | 1205 | if (!vp) return vp; |
1075 | memset(vp,0,sizeof(*vp)); | 1206 | vp->dev_video = kzalloc(sizeof(*vp->dev_video),GFP_KERNEL); |
1076 | vp->vdev = kmalloc(sizeof(*vp->vdev),GFP_KERNEL); | 1207 | vp->dev_radio = kzalloc(sizeof(*vp->dev_radio),GFP_KERNEL); |
1077 | if (!vp->vdev) { | 1208 | if (!(vp->dev_video && vp->dev_radio)) { |
1209 | kfree(vp->dev_video); | ||
1210 | kfree(vp->dev_radio); | ||
1078 | kfree(vp); | 1211 | kfree(vp); |
1079 | return NULL; | 1212 | return NULL; |
1080 | } | 1213 | } |
1081 | memset(vp->vdev,0,sizeof(*vp->vdev)); | ||
1082 | pvr2_channel_init(&vp->channel,mnp); | 1214 | pvr2_channel_init(&vp->channel,mnp); |
1083 | pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_v4l2 id=%p",vp); | 1215 | pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_v4l2 id=%p",vp); |
1084 | 1216 | ||
1085 | vp->channel.check_func = pvr2_v4l2_internal_check; | 1217 | vp->channel.check_func = pvr2_v4l2_internal_check; |
1086 | 1218 | ||
1087 | /* register streams */ | 1219 | /* register streams */ |
1088 | pvr2_v4l2_dev_init(vp->vdev,vp,pvr2_config_mpeg); | 1220 | pvr2_v4l2_dev_init(vp->dev_video,vp,VFL_TYPE_GRABBER); |
1221 | pvr2_v4l2_dev_init(vp->dev_radio,vp,VFL_TYPE_RADIO); | ||
1089 | 1222 | ||
1090 | return vp; | 1223 | return vp; |
1091 | } | 1224 | } |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c b/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c index 2a826464911a..61efa6f02200 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c +++ b/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c | |||
@@ -66,7 +66,9 @@ static void set_input(struct pvr2_v4l_decoder *ctxt) | |||
66 | route.input = SAA7115_SVIDEO2; | 66 | route.input = SAA7115_SVIDEO2; |
67 | break; | 67 | break; |
68 | case PVR2_CVAL_INPUT_RADIO: | 68 | case PVR2_CVAL_INPUT_RADIO: |
69 | // ????? No idea yet what to do here | 69 | // In radio mode, we mute the video, but point at one |
70 | // spot just to stay consistent | ||
71 | route.input = SAA7115_COMPOSITE5; | ||
70 | default: | 72 | default: |
71 | return; | 73 | return; |
72 | } | 74 | } |
@@ -137,8 +139,7 @@ static int decoder_check(struct pvr2_v4l_decoder *ctxt) | |||
137 | unsigned long msk; | 139 | unsigned long msk; |
138 | unsigned int idx; | 140 | unsigned int idx; |
139 | 141 | ||
140 | for (idx = 0; idx < sizeof(decoder_ops)/sizeof(decoder_ops[0]); | 142 | for (idx = 0; idx < ARRAY_SIZE(decoder_ops); idx++) { |
141 | idx++) { | ||
142 | msk = 1 << idx; | 143 | msk = 1 << idx; |
143 | if (ctxt->stale_mask & msk) continue; | 144 | if (ctxt->stale_mask & msk) continue; |
144 | if (decoder_ops[idx].check(ctxt)) { | 145 | if (decoder_ops[idx].check(ctxt)) { |
@@ -154,8 +155,7 @@ static void decoder_update(struct pvr2_v4l_decoder *ctxt) | |||
154 | unsigned long msk; | 155 | unsigned long msk; |
155 | unsigned int idx; | 156 | unsigned int idx; |
156 | 157 | ||
157 | for (idx = 0; idx < sizeof(decoder_ops)/sizeof(decoder_ops[0]); | 158 | for (idx = 0; idx < ARRAY_SIZE(decoder_ops); idx++) { |
158 | idx++) { | ||
159 | msk = 1 << idx; | 159 | msk = 1 << idx; |
160 | if (!(ctxt->stale_mask & msk)) continue; | 160 | if (!(ctxt->stale_mask & msk)) continue; |
161 | ctxt->stale_mask &= ~msk; | 161 | ctxt->stale_mask &= ~msk; |
@@ -183,18 +183,6 @@ static void decoder_enable(struct pvr2_v4l_decoder *ctxt,int fl) | |||
183 | } | 183 | } |
184 | 184 | ||
185 | 185 | ||
186 | static int decoder_is_tuned(struct pvr2_v4l_decoder *ctxt) | ||
187 | { | ||
188 | struct v4l2_tuner vt; | ||
189 | int ret; | ||
190 | |||
191 | memset(&vt,0,sizeof(vt)); | ||
192 | ret = pvr2_i2c_client_cmd(ctxt->client,VIDIOC_G_TUNER,&vt); | ||
193 | if (ret < 0) return -EINVAL; | ||
194 | return vt.signal ? 1 : 0; | ||
195 | } | ||
196 | |||
197 | |||
198 | static unsigned int decoder_describe(struct pvr2_v4l_decoder *ctxt,char *buf,unsigned int cnt) | 186 | static unsigned int decoder_describe(struct pvr2_v4l_decoder *ctxt,char *buf,unsigned int cnt) |
199 | { | 187 | { |
200 | return scnprintf(buf,cnt,"handler: pvrusb2-video-v4l"); | 188 | return scnprintf(buf,cnt,"handler: pvrusb2-video-v4l"); |
@@ -218,20 +206,17 @@ int pvr2_i2c_decoder_v4l_setup(struct pvr2_hdw *hdw, | |||
218 | if (cp->handler) return 0; | 206 | if (cp->handler) return 0; |
219 | if (!decoder_detect(cp)) return 0; | 207 | if (!decoder_detect(cp)) return 0; |
220 | 208 | ||
221 | ctxt = kmalloc(sizeof(*ctxt),GFP_KERNEL); | 209 | ctxt = kzalloc(sizeof(*ctxt),GFP_KERNEL); |
222 | if (!ctxt) return 0; | 210 | if (!ctxt) return 0; |
223 | memset(ctxt,0,sizeof(*ctxt)); | ||
224 | 211 | ||
225 | ctxt->handler.func_data = ctxt; | 212 | ctxt->handler.func_data = ctxt; |
226 | ctxt->handler.func_table = &hfuncs; | 213 | ctxt->handler.func_table = &hfuncs; |
227 | ctxt->ctrl.ctxt = ctxt; | 214 | ctxt->ctrl.ctxt = ctxt; |
228 | ctxt->ctrl.detach = (void (*)(void *))decoder_detach; | 215 | ctxt->ctrl.detach = (void (*)(void *))decoder_detach; |
229 | ctxt->ctrl.enable = (void (*)(void *,int))decoder_enable; | 216 | ctxt->ctrl.enable = (void (*)(void *,int))decoder_enable; |
230 | ctxt->ctrl.tuned = (int (*)(void *))decoder_is_tuned; | ||
231 | ctxt->client = cp; | 217 | ctxt->client = cp; |
232 | ctxt->hdw = hdw; | 218 | ctxt->hdw = hdw; |
233 | ctxt->stale_mask = (1 << (sizeof(decoder_ops)/ | 219 | ctxt->stale_mask = (1 << ARRAY_SIZE(decoder_ops)) - 1; |
234 | sizeof(decoder_ops[0]))) - 1; | ||
235 | hdw->decoder_ctrl = &ctxt->ctrl; | 220 | hdw->decoder_ctrl = &ctxt->ctrl; |
236 | cp->handler = &ctxt->handler; | 221 | cp->handler = &ctxt->handler; |
237 | pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x saa711x V4L2 handler set up", | 222 | pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x saa711x V4L2 handler set up", |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-wm8775.c b/drivers/media/video/pvrusb2/pvrusb2-wm8775.c index 7794c34c355e..66b4d36ef765 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-wm8775.c +++ b/drivers/media/video/pvrusb2/pvrusb2-wm8775.c | |||
@@ -50,15 +50,21 @@ static void set_input(struct pvr2_v4l_wm8775 *ctxt) | |||
50 | { | 50 | { |
51 | struct v4l2_routing route; | 51 | struct v4l2_routing route; |
52 | struct pvr2_hdw *hdw = ctxt->hdw; | 52 | struct pvr2_hdw *hdw = ctxt->hdw; |
53 | int msk = 0; | ||
54 | 53 | ||
55 | memset(&route,0,sizeof(route)); | 54 | memset(&route,0,sizeof(route)); |
56 | 55 | ||
57 | pvr2_trace(PVR2_TRACE_CHIPS,"i2c wm8775 set_input(val=%d msk=0x%x)", | 56 | switch(hdw->input_val) { |
58 | hdw->input_val,msk); | 57 | case PVR2_CVAL_INPUT_RADIO: |
58 | route.input = 1; | ||
59 | break; | ||
60 | default: | ||
61 | /* All other cases just use the second input */ | ||
62 | route.input = 2; | ||
63 | break; | ||
64 | } | ||
65 | pvr2_trace(PVR2_TRACE_CHIPS,"i2c wm8775 set_input(val=%d route=0x%x)", | ||
66 | hdw->input_val,route.input); | ||
59 | 67 | ||
60 | // Always point to input #1 no matter what | ||
61 | route.input = 2; | ||
62 | pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_S_AUDIO_ROUTING,&route); | 68 | pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_S_AUDIO_ROUTING,&route); |
63 | } | 69 | } |
64 | 70 | ||
@@ -99,8 +105,7 @@ static int wm8775_check(struct pvr2_v4l_wm8775 *ctxt) | |||
99 | unsigned long msk; | 105 | unsigned long msk; |
100 | unsigned int idx; | 106 | unsigned int idx; |
101 | 107 | ||
102 | for (idx = 0; idx < sizeof(wm8775_ops)/sizeof(wm8775_ops[0]); | 108 | for (idx = 0; idx < ARRAY_SIZE(wm8775_ops); idx++) { |
103 | idx++) { | ||
104 | msk = 1 << idx; | 109 | msk = 1 << idx; |
105 | if (ctxt->stale_mask & msk) continue; | 110 | if (ctxt->stale_mask & msk) continue; |
106 | if (wm8775_ops[idx].check(ctxt)) { | 111 | if (wm8775_ops[idx].check(ctxt)) { |
@@ -116,8 +121,7 @@ static void wm8775_update(struct pvr2_v4l_wm8775 *ctxt) | |||
116 | unsigned long msk; | 121 | unsigned long msk; |
117 | unsigned int idx; | 122 | unsigned int idx; |
118 | 123 | ||
119 | for (idx = 0; idx < sizeof(wm8775_ops)/sizeof(wm8775_ops[0]); | 124 | for (idx = 0; idx < ARRAY_SIZE(wm8775_ops); idx++) { |
120 | idx++) { | ||
121 | msk = 1 << idx; | 125 | msk = 1 << idx; |
122 | if (!(ctxt->stale_mask & msk)) continue; | 126 | if (!(ctxt->stale_mask & msk)) continue; |
123 | ctxt->stale_mask &= ~msk; | 127 | ctxt->stale_mask &= ~msk; |
@@ -140,16 +144,14 @@ int pvr2_i2c_wm8775_setup(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp) | |||
140 | 144 | ||
141 | if (cp->handler) return 0; | 145 | if (cp->handler) return 0; |
142 | 146 | ||
143 | ctxt = kmalloc(sizeof(*ctxt),GFP_KERNEL); | 147 | ctxt = kzalloc(sizeof(*ctxt),GFP_KERNEL); |
144 | if (!ctxt) return 0; | 148 | if (!ctxt) return 0; |
145 | memset(ctxt,0,sizeof(*ctxt)); | ||
146 | 149 | ||
147 | ctxt->handler.func_data = ctxt; | 150 | ctxt->handler.func_data = ctxt; |
148 | ctxt->handler.func_table = &hfuncs; | 151 | ctxt->handler.func_table = &hfuncs; |
149 | ctxt->client = cp; | 152 | ctxt->client = cp; |
150 | ctxt->hdw = hdw; | 153 | ctxt->hdw = hdw; |
151 | ctxt->stale_mask = (1 << (sizeof(wm8775_ops)/ | 154 | ctxt->stale_mask = (1 << ARRAY_SIZE(wm8775_ops)) - 1; |
152 | sizeof(wm8775_ops[0]))) - 1; | ||
153 | cp->handler = &ctxt->handler; | 155 | cp->handler = &ctxt->handler; |
154 | pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x wm8775 V4L2 handler set up", | 156 | pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x wm8775 V4L2 handler set up", |
155 | cp->client->addr); | 157 | cp->client->addr); |
diff --git a/drivers/media/video/pwc/Makefile b/drivers/media/video/pwc/Makefile index 9db2260d10cc..f5c8ec261e87 100644 --- a/drivers/media/video/pwc/Makefile +++ b/drivers/media/video/pwc/Makefile | |||
@@ -2,11 +2,3 @@ pwc-objs := pwc-if.o pwc-misc.o pwc-ctrl.o pwc-v4l.o pwc-uncompress.o | |||
2 | pwc-objs += pwc-dec1.o pwc-dec23.o pwc-kiara.o pwc-timon.o | 2 | pwc-objs += pwc-dec1.o pwc-dec23.o pwc-kiara.o pwc-timon.o |
3 | 3 | ||
4 | obj-$(CONFIG_USB_PWC) += pwc.o | 4 | obj-$(CONFIG_USB_PWC) += pwc.o |
5 | |||
6 | ifeq ($(CONFIG_USB_PWC_DEBUG),y) | ||
7 | EXTRA_CFLAGS += -DCONFIG_PWC_DEBUG=1 | ||
8 | else | ||
9 | EXTRA_CFLAGS += -DCONFIG_PWC_DEBUG=0 | ||
10 | endif | ||
11 | |||
12 | |||
diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c index 9825fd348108..27ed76986ca2 100644 --- a/drivers/media/video/pwc/pwc-if.c +++ b/drivers/media/video/pwc/pwc-if.c | |||
@@ -128,7 +128,7 @@ static int default_size = PSZ_QCIF; | |||
128 | static int default_fps = 10; | 128 | static int default_fps = 10; |
129 | static int default_fbufs = 3; /* Default number of frame buffers */ | 129 | static int default_fbufs = 3; /* Default number of frame buffers */ |
130 | int pwc_mbufs = 2; /* Default number of mmap() buffers */ | 130 | int pwc_mbufs = 2; /* Default number of mmap() buffers */ |
131 | #if CONFIG_PWC_DEBUG | 131 | #ifdef CONFIG_USB_PWC_DEBUG |
132 | int pwc_trace = PWC_DEBUG_LEVEL; | 132 | int pwc_trace = PWC_DEBUG_LEVEL; |
133 | #endif | 133 | #endif |
134 | static int power_save = 0; | 134 | static int power_save = 0; |
@@ -1051,7 +1051,7 @@ static void pwc_remove_sysfs_files(struct video_device *vdev) | |||
1051 | video_device_remove_file(vdev, &class_device_attr_button); | 1051 | video_device_remove_file(vdev, &class_device_attr_button); |
1052 | } | 1052 | } |
1053 | 1053 | ||
1054 | #if CONFIG_PWC_DEBUG | 1054 | #ifdef CONFIG_USB_PWC_DEBUG |
1055 | static const char *pwc_sensor_type_to_string(unsigned int sensor_type) | 1055 | static const char *pwc_sensor_type_to_string(unsigned int sensor_type) |
1056 | { | 1056 | { |
1057 | switch(sensor_type) { | 1057 | switch(sensor_type) { |
@@ -1835,7 +1835,7 @@ module_param(size, charp, 0444); | |||
1835 | module_param(fps, int, 0444); | 1835 | module_param(fps, int, 0444); |
1836 | module_param(fbufs, int, 0444); | 1836 | module_param(fbufs, int, 0444); |
1837 | module_param(mbufs, int, 0444); | 1837 | module_param(mbufs, int, 0444); |
1838 | #if CONFIG_PWC_DEBUG | 1838 | #ifdef CONFIG_USB_PWC_DEBUG |
1839 | module_param_named(trace, pwc_trace, int, 0644); | 1839 | module_param_named(trace, pwc_trace, int, 0644); |
1840 | #endif | 1840 | #endif |
1841 | module_param(power_save, int, 0444); | 1841 | module_param(power_save, int, 0444); |
@@ -1908,7 +1908,7 @@ static int __init usb_pwc_init(void) | |||
1908 | default_fbufs = fbufs; | 1908 | default_fbufs = fbufs; |
1909 | PWC_DEBUG_MODULE("Number of frame buffers set to %d.\n", default_fbufs); | 1909 | PWC_DEBUG_MODULE("Number of frame buffers set to %d.\n", default_fbufs); |
1910 | } | 1910 | } |
1911 | #if CONFIG_PWC_DEBUG | 1911 | #ifdef CONFIG_USB_PWC_DEBUG |
1912 | if (pwc_trace >= 0) { | 1912 | if (pwc_trace >= 0) { |
1913 | PWC_DEBUG_MODULE("Trace options: 0x%04x\n", pwc_trace); | 1913 | PWC_DEBUG_MODULE("Trace options: 0x%04x\n", pwc_trace); |
1914 | } | 1914 | } |
diff --git a/drivers/media/video/pwc/pwc-v4l.c b/drivers/media/video/pwc/pwc-v4l.c index b7eb3ce3b968..d5e6bc850643 100644 --- a/drivers/media/video/pwc/pwc-v4l.c +++ b/drivers/media/video/pwc/pwc-v4l.c | |||
@@ -350,7 +350,7 @@ int pwc_video_do_ioctl(struct inode *inode, struct file *file, | |||
350 | if (pdev == NULL) | 350 | if (pdev == NULL) |
351 | return -EFAULT; | 351 | return -EFAULT; |
352 | 352 | ||
353 | #if CONFIG_PWC_DEBUG | 353 | #ifdef CONFIG_USB_PWC_DEBUG |
354 | if (PWC_DEBUG_LEVEL_IOCTL & pwc_trace) | 354 | if (PWC_DEBUG_LEVEL_IOCTL & pwc_trace) |
355 | v4l_printk_ioctl(cmd); | 355 | v4l_printk_ioctl(cmd); |
356 | #endif | 356 | #endif |
diff --git a/drivers/media/video/pwc/pwc.h b/drivers/media/video/pwc/pwc.h index 7e9c4237d1e8..e778a2b8c280 100644 --- a/drivers/media/video/pwc/pwc.h +++ b/drivers/media/video/pwc/pwc.h | |||
@@ -39,11 +39,6 @@ | |||
39 | #include "pwc-uncompress.h" | 39 | #include "pwc-uncompress.h" |
40 | #include <media/pwc-ioctl.h> | 40 | #include <media/pwc-ioctl.h> |
41 | 41 | ||
42 | /* Turn some debugging options on/off */ | ||
43 | #ifndef CONFIG_PWC_DEBUG | ||
44 | #define CONFIG_PWC_DEBUG 1 | ||
45 | #endif | ||
46 | |||
47 | /* Version block */ | 42 | /* Version block */ |
48 | #define PWC_MAJOR 10 | 43 | #define PWC_MAJOR 10 |
49 | #define PWC_MINOR 0 | 44 | #define PWC_MINOR 0 |
@@ -76,7 +71,7 @@ | |||
76 | #define PWC_DEBUG_TRACE(fmt, args...) PWC_DEBUG(TRACE, fmt, ##args) | 71 | #define PWC_DEBUG_TRACE(fmt, args...) PWC_DEBUG(TRACE, fmt, ##args) |
77 | 72 | ||
78 | 73 | ||
79 | #if CONFIG_PWC_DEBUG | 74 | #ifdef CONFIG_USB_PWC_DEBUG |
80 | 75 | ||
81 | #define PWC_DEBUG_LEVEL (PWC_DEBUG_LEVEL_MODULE) | 76 | #define PWC_DEBUG_LEVEL (PWC_DEBUG_LEVEL_MODULE) |
82 | 77 | ||
@@ -270,7 +265,7 @@ extern "C" { | |||
270 | #endif | 265 | #endif |
271 | 266 | ||
272 | /* Global variables */ | 267 | /* Global variables */ |
273 | #if CONFIG_PWC_DEBUG | 268 | #ifdef CONFIG_USB_PWC_DEBUG |
274 | extern int pwc_trace; | 269 | extern int pwc_trace; |
275 | #endif | 270 | #endif |
276 | extern int pwc_mbufs; | 271 | extern int pwc_mbufs; |
diff --git a/drivers/media/video/saa5246a.c b/drivers/media/video/saa5246a.c index 76f5f5d49dae..e20aa3612a7c 100644 --- a/drivers/media/video/saa5246a.c +++ b/drivers/media/video/saa5246a.c | |||
@@ -111,7 +111,7 @@ static int saa5246a_attach(struct i2c_adapter *adap, int addr, int kind) | |||
111 | for (pgbuf = 0; pgbuf < NUM_DAUS; pgbuf++) | 111 | for (pgbuf = 0; pgbuf < NUM_DAUS; pgbuf++) |
112 | { | 112 | { |
113 | memset(t->pgbuf[pgbuf], ' ', sizeof(t->pgbuf[0])); | 113 | memset(t->pgbuf[pgbuf], ' ', sizeof(t->pgbuf[0])); |
114 | t->is_searching[pgbuf] = FALSE; | 114 | t->is_searching[pgbuf] = false; |
115 | } | 115 | } |
116 | vd->priv=t; | 116 | vd->priv=t; |
117 | 117 | ||
@@ -198,7 +198,7 @@ static int i2c_senddata(struct saa5246a_device *t, ...) | |||
198 | 198 | ||
199 | /* Get count number of bytes from I²C-device at address adr, store them in buf. | 199 | /* Get count number of bytes from I²C-device at address adr, store them in buf. |
200 | * Start & stop handshaking is done by this routine, ack will be sent after the | 200 | * Start & stop handshaking is done by this routine, ack will be sent after the |
201 | * last byte to inhibit further sending of data. If uaccess is TRUE, data is | 201 | * last byte to inhibit further sending of data. If uaccess is 'true', data is |
202 | * written to user-space with put_user. Returns -1 if I²C-device didn't send | 202 | * written to user-space with put_user. Returns -1 if I²C-device didn't send |
203 | * acknowledge, 0 otherwise | 203 | * acknowledge, 0 otherwise |
204 | */ | 204 | */ |
@@ -338,7 +338,7 @@ static int saa5246a_request_page(struct saa5246a_device *t, | |||
338 | return -EIO; | 338 | return -EIO; |
339 | } | 339 | } |
340 | 340 | ||
341 | t->is_searching[req->pgbuf] = TRUE; | 341 | t->is_searching[req->pgbuf] = true; |
342 | return 0; | 342 | return 0; |
343 | } | 343 | } |
344 | 344 | ||
@@ -452,7 +452,7 @@ static inline int saa5246a_get_status(struct saa5246a_device *t, | |||
452 | } | 452 | } |
453 | } | 453 | } |
454 | if (!info->hamming && !info->notfound) | 454 | if (!info->hamming && !info->notfound) |
455 | t->is_searching[dau_no] = FALSE; | 455 | t->is_searching[dau_no] = false; |
456 | return 0; | 456 | return 0; |
457 | } | 457 | } |
458 | 458 | ||
@@ -564,7 +564,7 @@ static inline int saa5246a_stop_dau(struct saa5246a_device *t, | |||
564 | { | 564 | { |
565 | return -EIO; | 565 | return -EIO; |
566 | } | 566 | } |
567 | t->is_searching[dau_no] = FALSE; | 567 | t->is_searching[dau_no] = false; |
568 | return 0; | 568 | return 0; |
569 | } | 569 | } |
570 | 570 | ||
diff --git a/drivers/media/video/saa5246a.h b/drivers/media/video/saa5246a.h index 7b91112304e0..64394c036c60 100644 --- a/drivers/media/video/saa5246a.h +++ b/drivers/media/video/saa5246a.h | |||
@@ -41,23 +41,18 @@ | |||
41 | #define POS_HEADER_START 7 | 41 | #define POS_HEADER_START 7 |
42 | #define POS_HEADER_END 31 | 42 | #define POS_HEADER_END 31 |
43 | 43 | ||
44 | /* Returns TRUE if the part of the videotext page described with req contains | 44 | /* Returns 'true' if the part of the videotext page described with req contains |
45 | (at least parts of) the time field */ | 45 | (at least parts of) the time field */ |
46 | #define REQ_CONTAINS_TIME(p_req) \ | 46 | #define REQ_CONTAINS_TIME(p_req) \ |
47 | ((p_req)->start <= POS_TIME_END && \ | 47 | ((p_req)->start <= POS_TIME_END && \ |
48 | (p_req)->end >= POS_TIME_START) | 48 | (p_req)->end >= POS_TIME_START) |
49 | 49 | ||
50 | /* Returns TRUE if the part of the videotext page described with req contains | 50 | /* Returns 'true' if the part of the videotext page described with req contains |
51 | (at least parts of) the page header */ | 51 | (at least parts of) the page header */ |
52 | #define REQ_CONTAINS_HEADER(p_req) \ | 52 | #define REQ_CONTAINS_HEADER(p_req) \ |
53 | ((p_req)->start <= POS_HEADER_END && \ | 53 | ((p_req)->start <= POS_HEADER_END && \ |
54 | (p_req)->end >= POS_HEADER_START) | 54 | (p_req)->end >= POS_HEADER_START) |
55 | 55 | ||
56 | #ifndef FALSE | ||
57 | #define FALSE 0 | ||
58 | #define TRUE 1 | ||
59 | #endif | ||
60 | |||
61 | /*****************************************************************************/ | 56 | /*****************************************************************************/ |
62 | /* Mode register numbers of the SAA5246A */ | 57 | /* Mode register numbers of the SAA5246A */ |
63 | /*****************************************************************************/ | 58 | /*****************************************************************************/ |
diff --git a/drivers/media/video/saa5249.c b/drivers/media/video/saa5249.c index 3e84737878a8..f2a2f34cd626 100644 --- a/drivers/media/video/saa5249.c +++ b/drivers/media/video/saa5249.c | |||
@@ -124,11 +124,6 @@ struct saa5249_device | |||
124 | 124 | ||
125 | /* General defines and debugging support */ | 125 | /* General defines and debugging support */ |
126 | 126 | ||
127 | #ifndef FALSE | ||
128 | #define FALSE 0 | ||
129 | #define TRUE 1 | ||
130 | #endif | ||
131 | |||
132 | #define RESCHED do { cond_resched(); } while(0) | 127 | #define RESCHED do { cond_resched(); } while(0) |
133 | 128 | ||
134 | static struct video_device saa_template; /* Declared near bottom */ | 129 | static struct video_device saa_template; /* Declared near bottom */ |
@@ -183,9 +178,9 @@ static int saa5249_attach(struct i2c_adapter *adap, int addr, int kind) | |||
183 | memset(t->vdau[pgbuf].sregs, 0, sizeof(t->vdau[0].sregs)); | 178 | memset(t->vdau[pgbuf].sregs, 0, sizeof(t->vdau[0].sregs)); |
184 | memset(t->vdau[pgbuf].laststat, 0, sizeof(t->vdau[0].laststat)); | 179 | memset(t->vdau[pgbuf].laststat, 0, sizeof(t->vdau[0].laststat)); |
185 | t->vdau[pgbuf].expire = 0; | 180 | t->vdau[pgbuf].expire = 0; |
186 | t->vdau[pgbuf].clrfound = TRUE; | 181 | t->vdau[pgbuf].clrfound = true; |
187 | t->vdau[pgbuf].stopped = TRUE; | 182 | t->vdau[pgbuf].stopped = true; |
188 | t->is_searching[pgbuf] = FALSE; | 183 | t->is_searching[pgbuf] = false; |
189 | } | 184 | } |
190 | vd->priv=t; | 185 | vd->priv=t; |
191 | 186 | ||
@@ -298,7 +293,7 @@ static int i2c_senddata(struct saa5249_device *t, ...) | |||
298 | 293 | ||
299 | /* Get count number of bytes from I²C-device at address adr, store them in buf. Start & stop | 294 | /* Get count number of bytes from I²C-device at address adr, store them in buf. Start & stop |
300 | * handshaking is done by this routine, ack will be sent after the last byte to inhibit further | 295 | * handshaking is done by this routine, ack will be sent after the last byte to inhibit further |
301 | * sending of data. If uaccess is TRUE, data is written to user-space with put_user. | 296 | * sending of data. If uaccess is 'true', data is written to user-space with put_user. |
302 | * Returns -1 if I²C-device didn't send acknowledge, 0 otherwise | 297 | * Returns -1 if I²C-device didn't send acknowledge, 0 otherwise |
303 | */ | 298 | */ |
304 | 299 | ||
@@ -317,7 +312,7 @@ static int i2c_getdata(struct saa5249_device *t, int count, u8 *buf) | |||
317 | static int do_saa5249_ioctl(struct inode *inode, struct file *file, | 312 | static int do_saa5249_ioctl(struct inode *inode, struct file *file, |
318 | unsigned int cmd, void *arg) | 313 | unsigned int cmd, void *arg) |
319 | { | 314 | { |
320 | static int virtual_mode = FALSE; | 315 | static int virtual_mode = false; |
321 | struct video_device *vd = video_devdata(file); | 316 | struct video_device *vd = video_devdata(file); |
322 | struct saa5249_device *t=vd->priv; | 317 | struct saa5249_device *t=vd->priv; |
323 | 318 | ||
@@ -340,7 +335,7 @@ static int do_saa5249_ioctl(struct inode *inode, struct file *file, | |||
340 | if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS) | 335 | if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS) |
341 | return -EINVAL; | 336 | return -EINVAL; |
342 | memset(t->vdau[req->pgbuf].pgbuf, ' ', sizeof(t->vdau[0].pgbuf)); | 337 | memset(t->vdau[req->pgbuf].pgbuf, ' ', sizeof(t->vdau[0].pgbuf)); |
343 | t->vdau[req->pgbuf].clrfound = TRUE; | 338 | t->vdau[req->pgbuf].clrfound = true; |
344 | return 0; | 339 | return 0; |
345 | } | 340 | } |
346 | 341 | ||
@@ -350,7 +345,7 @@ static int do_saa5249_ioctl(struct inode *inode, struct file *file, | |||
350 | 345 | ||
351 | if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS) | 346 | if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS) |
352 | return -EINVAL; | 347 | return -EINVAL; |
353 | t->vdau[req->pgbuf].clrfound = TRUE; | 348 | t->vdau[req->pgbuf].clrfound = true; |
354 | return 0; | 349 | return 0; |
355 | } | 350 | } |
356 | 351 | ||
@@ -376,9 +371,9 @@ static int do_saa5249_ioctl(struct inode *inode, struct file *file, | |||
376 | t->vdau[req->pgbuf].sregs[4] = (req->pagemask & HR_UNIT ? 0x10 : 0) | (req->hour & 0xf); | 371 | t->vdau[req->pgbuf].sregs[4] = (req->pagemask & HR_UNIT ? 0x10 : 0) | (req->hour & 0xf); |
377 | t->vdau[req->pgbuf].sregs[5] = (req->pagemask & MIN_TEN ? 0x10 : 0) | (req->minute / 0x10); | 372 | t->vdau[req->pgbuf].sregs[5] = (req->pagemask & MIN_TEN ? 0x10 : 0) | (req->minute / 0x10); |
378 | t->vdau[req->pgbuf].sregs[6] = (req->pagemask & MIN_UNIT ? 0x10 : 0) | (req->minute & 0xf); | 373 | t->vdau[req->pgbuf].sregs[6] = (req->pagemask & MIN_UNIT ? 0x10 : 0) | (req->minute & 0xf); |
379 | t->vdau[req->pgbuf].stopped = FALSE; | 374 | t->vdau[req->pgbuf].stopped = false; |
380 | t->vdau[req->pgbuf].clrfound = TRUE; | 375 | t->vdau[req->pgbuf].clrfound = true; |
381 | t->is_searching[req->pgbuf] = TRUE; | 376 | t->is_searching[req->pgbuf] = true; |
382 | return 0; | 377 | return 0; |
383 | } | 378 | } |
384 | 379 | ||
@@ -430,7 +425,7 @@ static int do_saa5249_ioctl(struct inode *inode, struct file *file, | |||
430 | i2c_getdata(t, 40, t->vdau[req->pgbuf].pgbuf + VTX_PAGESIZE + 23 * 40)) | 425 | i2c_getdata(t, 40, t->vdau[req->pgbuf].pgbuf + VTX_PAGESIZE + 23 * 40)) |
431 | return -EIO; | 426 | return -EIO; |
432 | } | 427 | } |
433 | t->vdau[req->pgbuf].clrfound = FALSE; | 428 | t->vdau[req->pgbuf].clrfound = false; |
434 | memcpy(t->vdau[req->pgbuf].laststat, infobits, sizeof(infobits)); | 429 | memcpy(t->vdau[req->pgbuf].laststat, infobits, sizeof(infobits)); |
435 | } | 430 | } |
436 | else | 431 | else |
@@ -474,7 +469,7 @@ static int do_saa5249_ioctl(struct inode *inode, struct file *file, | |||
474 | return -EFAULT; | 469 | return -EFAULT; |
475 | if (!info.hamming && !info.notfound) | 470 | if (!info.hamming && !info.notfound) |
476 | { | 471 | { |
477 | t->is_searching[req->pgbuf] = FALSE; | 472 | t->is_searching[req->pgbuf] = false; |
478 | } | 473 | } |
479 | return 0; | 474 | return 0; |
480 | } | 475 | } |
@@ -530,8 +525,8 @@ static int do_saa5249_ioctl(struct inode *inode, struct file *file, | |||
530 | 525 | ||
531 | if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS) | 526 | if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS) |
532 | return -EINVAL; | 527 | return -EINVAL; |
533 | t->vdau[req->pgbuf].stopped = TRUE; | 528 | t->vdau[req->pgbuf].stopped = true; |
534 | t->is_searching[req->pgbuf] = FALSE; | 529 | t->is_searching[req->pgbuf] = false; |
535 | return 0; | 530 | return 0; |
536 | } | 531 | } |
537 | 532 | ||
@@ -660,11 +655,11 @@ static int saa5249_open(struct inode *inode, struct file *file) | |||
660 | memset(t->vdau[pgbuf].sregs, 0, sizeof(t->vdau[0].sregs)); | 655 | memset(t->vdau[pgbuf].sregs, 0, sizeof(t->vdau[0].sregs)); |
661 | memset(t->vdau[pgbuf].laststat, 0, sizeof(t->vdau[0].laststat)); | 656 | memset(t->vdau[pgbuf].laststat, 0, sizeof(t->vdau[0].laststat)); |
662 | t->vdau[pgbuf].expire = 0; | 657 | t->vdau[pgbuf].expire = 0; |
663 | t->vdau[pgbuf].clrfound = TRUE; | 658 | t->vdau[pgbuf].clrfound = true; |
664 | t->vdau[pgbuf].stopped = TRUE; | 659 | t->vdau[pgbuf].stopped = true; |
665 | t->is_searching[pgbuf] = FALSE; | 660 | t->is_searching[pgbuf] = false; |
666 | } | 661 | } |
667 | t->virtual_mode=FALSE; | 662 | t->virtual_mode = false; |
668 | return 0; | 663 | return 0; |
669 | 664 | ||
670 | fail: | 665 | fail: |
diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c index c2374ed7ba9f..c4f066d6668e 100644 --- a/drivers/media/video/saa7115.c +++ b/drivers/media/video/saa7115.c | |||
@@ -71,6 +71,7 @@ I2C_CLIENT_INSMOD; | |||
71 | struct saa711x_state { | 71 | struct saa711x_state { |
72 | v4l2_std_id std; | 72 | v4l2_std_id std; |
73 | int input; | 73 | int input; |
74 | int output; | ||
74 | int enable; | 75 | int enable; |
75 | int radio; | 76 | int radio; |
76 | int bright; | 77 | int bright; |
@@ -1301,7 +1302,7 @@ static int saa711x_command(struct i2c_client *client, unsigned int cmd, void *ar | |||
1301 | struct v4l2_routing *route = arg; | 1302 | struct v4l2_routing *route = arg; |
1302 | 1303 | ||
1303 | route->input = state->input; | 1304 | route->input = state->input; |
1304 | route->output = 0; | 1305 | route->output = state->output; |
1305 | break; | 1306 | break; |
1306 | } | 1307 | } |
1307 | 1308 | ||
@@ -1309,7 +1310,7 @@ static int saa711x_command(struct i2c_client *client, unsigned int cmd, void *ar | |||
1309 | { | 1310 | { |
1310 | struct v4l2_routing *route = arg; | 1311 | struct v4l2_routing *route = arg; |
1311 | 1312 | ||
1312 | v4l_dbg(1, debug, client, "decoder set input %d\n", route->input); | 1313 | v4l_dbg(1, debug, client, "decoder set input %d output %d\n", route->input, route->output); |
1313 | /* saa7113 does not have these inputs */ | 1314 | /* saa7113 does not have these inputs */ |
1314 | if (state->ident == V4L2_IDENT_SAA7113 && | 1315 | if (state->ident == V4L2_IDENT_SAA7113 && |
1315 | (route->input == SAA7115_COMPOSITE4 || | 1316 | (route->input == SAA7115_COMPOSITE4 || |
@@ -1318,10 +1319,12 @@ static int saa711x_command(struct i2c_client *client, unsigned int cmd, void *ar | |||
1318 | } | 1319 | } |
1319 | if (route->input > SAA7115_SVIDEO3) | 1320 | if (route->input > SAA7115_SVIDEO3) |
1320 | return -EINVAL; | 1321 | return -EINVAL; |
1321 | if (state->input == route->input) | 1322 | if (route->output > SAA7115_IPORT_ON) |
1323 | return -EINVAL; | ||
1324 | if (state->input == route->input && state->output == route->output) | ||
1322 | break; | 1325 | break; |
1323 | v4l_dbg(1, debug, client, "now setting %s input\n", | 1326 | v4l_dbg(1, debug, client, "now setting %s input %s output\n", |
1324 | (route->input >= SAA7115_SVIDEO0) ? "S-Video" : "Composite"); | 1327 | (route->input >= SAA7115_SVIDEO0) ? "S-Video" : "Composite", (route->output == SAA7115_IPORT_ON) ? "iport on" : "iport off"); |
1325 | state->input = route->input; | 1328 | state->input = route->input; |
1326 | 1329 | ||
1327 | /* select mode */ | 1330 | /* select mode */ |
@@ -1333,6 +1336,14 @@ static int saa711x_command(struct i2c_client *client, unsigned int cmd, void *ar | |||
1333 | saa711x_write(client, R_09_LUMA_CNTL, | 1336 | saa711x_write(client, R_09_LUMA_CNTL, |
1334 | (saa711x_read(client, R_09_LUMA_CNTL) & 0x7f) | | 1337 | (saa711x_read(client, R_09_LUMA_CNTL) & 0x7f) | |
1335 | (state->input >= SAA7115_SVIDEO0 ? 0x80 : 0x0)); | 1338 | (state->input >= SAA7115_SVIDEO0 ? 0x80 : 0x0)); |
1339 | |||
1340 | state->output = route->output; | ||
1341 | if (state->ident == V4L2_IDENT_SAA7114 || | ||
1342 | state->ident == V4L2_IDENT_SAA7115) { | ||
1343 | saa711x_write(client, R_83_X_PORT_I_O_ENA_AND_OUT_CLK, | ||
1344 | (saa711x_read(client, R_83_X_PORT_I_O_ENA_AND_OUT_CLK) & 0xfe) | | ||
1345 | (state->output & 0x01)); | ||
1346 | } | ||
1336 | break; | 1347 | break; |
1337 | } | 1348 | } |
1338 | 1349 | ||
@@ -1377,6 +1388,9 @@ static int saa711x_command(struct i2c_client *client, unsigned int cmd, void *ar | |||
1377 | { | 1388 | { |
1378 | struct v4l2_sliced_vbi_data *data = arg; | 1389 | struct v4l2_sliced_vbi_data *data = arg; |
1379 | 1390 | ||
1391 | /* Note: the internal field ID is inverted for NTSC, | ||
1392 | so data->field 0 maps to the saa7115 even field, | ||
1393 | whereas for PAL it maps to the saa7115 odd field. */ | ||
1380 | switch (data->id) { | 1394 | switch (data->id) { |
1381 | case V4L2_SLICED_WSS_625: | 1395 | case V4L2_SLICED_WSS_625: |
1382 | if (saa711x_read(client, 0x6b) & 0xc0) | 1396 | if (saa711x_read(client, 0x6b) & 0xc0) |
@@ -1387,17 +1401,17 @@ static int saa711x_command(struct i2c_client *client, unsigned int cmd, void *ar | |||
1387 | case V4L2_SLICED_CAPTION_525: | 1401 | case V4L2_SLICED_CAPTION_525: |
1388 | if (data->field == 0) { | 1402 | if (data->field == 0) { |
1389 | /* CC */ | 1403 | /* CC */ |
1390 | if (saa711x_read(client, 0x66) & 0xc0) | 1404 | if (saa711x_read(client, 0x66) & 0x30) |
1391 | return -EIO; | 1405 | return -EIO; |
1392 | data->data[0] = saa711x_read(client, 0x67); | 1406 | data->data[0] = saa711x_read(client, 0x69); |
1393 | data->data[1] = saa711x_read(client, 0x68); | 1407 | data->data[1] = saa711x_read(client, 0x6a); |
1394 | return 0; | 1408 | return 0; |
1395 | } | 1409 | } |
1396 | /* XDS */ | 1410 | /* XDS */ |
1397 | if (saa711x_read(client, 0x66) & 0x30) | 1411 | if (saa711x_read(client, 0x66) & 0xc0) |
1398 | return -EIO; | 1412 | return -EIO; |
1399 | data->data[0] = saa711x_read(client, 0x69); | 1413 | data->data[0] = saa711x_read(client, 0x67); |
1400 | data->data[1] = saa711x_read(client, 0x6a); | 1414 | data->data[1] = saa711x_read(client, 0x68); |
1401 | return 0; | 1415 | return 0; |
1402 | default: | 1416 | default: |
1403 | return -EINVAL; | 1417 | return -EINVAL; |
@@ -1406,17 +1420,8 @@ static int saa711x_command(struct i2c_client *client, unsigned int cmd, void *ar | |||
1406 | } | 1420 | } |
1407 | 1421 | ||
1408 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 1422 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
1409 | case VIDIOC_INT_G_REGISTER: | 1423 | case VIDIOC_DBG_G_REGISTER: |
1410 | { | 1424 | case VIDIOC_DBG_S_REGISTER: |
1411 | struct v4l2_register *reg = arg; | ||
1412 | |||
1413 | if (reg->i2c_id != I2C_DRIVERID_SAA711X) | ||
1414 | return -EINVAL; | ||
1415 | reg->val = saa711x_read(client, reg->reg & 0xff); | ||
1416 | break; | ||
1417 | } | ||
1418 | |||
1419 | case VIDIOC_INT_S_REGISTER: | ||
1420 | { | 1425 | { |
1421 | struct v4l2_register *reg = arg; | 1426 | struct v4l2_register *reg = arg; |
1422 | 1427 | ||
@@ -1424,7 +1429,10 @@ static int saa711x_command(struct i2c_client *client, unsigned int cmd, void *ar | |||
1424 | return -EINVAL; | 1429 | return -EINVAL; |
1425 | if (!capable(CAP_SYS_ADMIN)) | 1430 | if (!capable(CAP_SYS_ADMIN)) |
1426 | return -EPERM; | 1431 | return -EPERM; |
1427 | saa711x_write(client, reg->reg & 0xff, reg->val & 0xff); | 1432 | if (cmd == VIDIOC_DBG_G_REGISTER) |
1433 | reg->val = saa711x_read(client, reg->reg & 0xff); | ||
1434 | else | ||
1435 | saa711x_write(client, reg->reg & 0xff, reg->val & 0xff); | ||
1428 | break; | 1436 | break; |
1429 | } | 1437 | } |
1430 | #endif | 1438 | #endif |
@@ -1492,6 +1500,7 @@ static int saa711x_attach(struct i2c_adapter *adapter, int address, int kind) | |||
1492 | return -ENOMEM; | 1500 | return -ENOMEM; |
1493 | } | 1501 | } |
1494 | state->input = -1; | 1502 | state->input = -1; |
1503 | state->output = SAA7115_IPORT_ON; | ||
1495 | state->enable = 1; | 1504 | state->enable = 1; |
1496 | state->radio = 0; | 1505 | state->radio = 0; |
1497 | state->bright = 128; | 1506 | state->bright = 128; |
@@ -1550,7 +1559,7 @@ static int saa711x_attach(struct i2c_adapter *adapter, int address, int kind) | |||
1550 | 1559 | ||
1551 | static int saa711x_probe(struct i2c_adapter *adapter) | 1560 | static int saa711x_probe(struct i2c_adapter *adapter) |
1552 | { | 1561 | { |
1553 | if (adapter->class & I2C_CLASS_TV_ANALOG) | 1562 | if (adapter->class & I2C_CLASS_TV_ANALOG || adapter->class & I2C_CLASS_TV_DIGITAL) |
1554 | return i2c_probe(adapter, &addr_data, &saa711x_attach); | 1563 | return i2c_probe(adapter, &addr_data, &saa711x_attach); |
1555 | return 0; | 1564 | return 0; |
1556 | } | 1565 | } |
diff --git a/drivers/media/video/saa7127.c b/drivers/media/video/saa7127.c index ad401bdefeaf..bd9c4f3ad02e 100644 --- a/drivers/media/video/saa7127.c +++ b/drivers/media/video/saa7127.c | |||
@@ -614,17 +614,8 @@ static int saa7127_command(struct i2c_client *client, | |||
614 | break; | 614 | break; |
615 | 615 | ||
616 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 616 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
617 | case VIDIOC_INT_G_REGISTER: | 617 | case VIDIOC_DBG_G_REGISTER: |
618 | { | 618 | case VIDIOC_DBG_S_REGISTER: |
619 | struct v4l2_register *reg = arg; | ||
620 | |||
621 | if (reg->i2c_id != I2C_DRIVERID_SAA7127) | ||
622 | return -EINVAL; | ||
623 | reg->val = saa7127_read(client, reg->reg & 0xff); | ||
624 | break; | ||
625 | } | ||
626 | |||
627 | case VIDIOC_INT_S_REGISTER: | ||
628 | { | 619 | { |
629 | struct v4l2_register *reg = arg; | 620 | struct v4l2_register *reg = arg; |
630 | 621 | ||
@@ -632,7 +623,10 @@ static int saa7127_command(struct i2c_client *client, | |||
632 | return -EINVAL; | 623 | return -EINVAL; |
633 | if (!capable(CAP_SYS_ADMIN)) | 624 | if (!capable(CAP_SYS_ADMIN)) |
634 | return -EPERM; | 625 | return -EPERM; |
635 | saa7127_write(client, reg->reg & 0xff, reg->val & 0xff); | 626 | if (cmd == VIDIOC_DBG_G_REGISTER) |
627 | reg->val = saa7127_read(client, reg->reg & 0xff); | ||
628 | else | ||
629 | saa7127_write(client, reg->reg & 0xff, reg->val & 0xff); | ||
636 | break; | 630 | break; |
637 | } | 631 | } |
638 | #endif | 632 | #endif |
diff --git a/drivers/media/video/saa7134/Makefile b/drivers/media/video/saa7134/Makefile index 89a1565b4256..c85c8a8ec361 100644 --- a/drivers/media/video/saa7134/Makefile +++ b/drivers/media/video/saa7134/Makefile | |||
@@ -14,7 +14,3 @@ obj-$(CONFIG_VIDEO_SAA7134_DVB) += saa7134-dvb.o | |||
14 | EXTRA_CFLAGS += -Idrivers/media/video | 14 | EXTRA_CFLAGS += -Idrivers/media/video |
15 | EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core | 15 | EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core |
16 | EXTRA_CFLAGS += -Idrivers/media/dvb/frontends | 16 | EXTRA_CFLAGS += -Idrivers/media/dvb/frontends |
17 | |||
18 | extra-cflags-$(CONFIG_VIDEO_BUF_DVB) += -DHAVE_VIDEO_BUF_DVB=1 | ||
19 | |||
20 | EXTRA_CFLAGS += $(extra-cflags-y) $(extra-cflags-m) | ||
diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index ae984bbe36b6..89f32107f46b 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c | |||
@@ -2469,6 +2469,11 @@ struct saa7134_board saa7134_boards[] = { | |||
2469 | .amux = LINE2, | 2469 | .amux = LINE2, |
2470 | .gpio = 0x0200000, | 2470 | .gpio = 0x0200000, |
2471 | },{ | 2471 | },{ |
2472 | .name = name_comp2, | ||
2473 | .vmux = 0, | ||
2474 | .amux = LINE2, | ||
2475 | .gpio = 0x0200000, | ||
2476 | },{ | ||
2472 | .name = name_svideo, | 2477 | .name = name_svideo, |
2473 | .vmux = 8, | 2478 | .vmux = 8, |
2474 | .amux = LINE2, | 2479 | .amux = LINE2, |
@@ -3183,6 +3188,107 @@ struct saa7134_board saa7134_boards[] = { | |||
3183 | .amux = LINE1, | 3188 | .amux = LINE1, |
3184 | }}, | 3189 | }}, |
3185 | }, | 3190 | }, |
3191 | [SAA7134_BOARD_ENCORE_ENLTV] = { | ||
3192 | /* Steven Walter <stevenrwalter@gmail.com> | ||
3193 | Juan Pablo Sormani <sorman@gmail.com> */ | ||
3194 | .name = "Encore ENLTV", | ||
3195 | .audio_clock = 0x00200000, | ||
3196 | .tuner_type = TUNER_TNF_5335MF, | ||
3197 | .radio_type = UNSET, | ||
3198 | .tuner_addr = ADDR_UNSET, | ||
3199 | .radio_addr = ADDR_UNSET, | ||
3200 | .inputs = {{ | ||
3201 | .name = name_tv, | ||
3202 | .vmux = 1, | ||
3203 | .amux = 3, | ||
3204 | .tv = 1, | ||
3205 | },{ | ||
3206 | .name = name_tv_mono, | ||
3207 | .vmux = 7, | ||
3208 | .amux = 4, | ||
3209 | .tv = 1, | ||
3210 | },{ | ||
3211 | .name = name_comp1, | ||
3212 | .vmux = 3, | ||
3213 | .amux = 2, | ||
3214 | },{ | ||
3215 | .name = name_svideo, | ||
3216 | .vmux = 0, | ||
3217 | .amux = 2, | ||
3218 | }}, | ||
3219 | .radio = { | ||
3220 | .name = name_radio, | ||
3221 | .amux = LINE2, | ||
3222 | /* .gpio = 0x00300001,*/ | ||
3223 | .gpio = 0x20000, | ||
3224 | |||
3225 | }, | ||
3226 | .mute = { | ||
3227 | .name = name_mute, | ||
3228 | .amux = 0, | ||
3229 | }, | ||
3230 | }, | ||
3231 | [SAA7134_BOARD_ENCORE_ENLTV_FM] = { | ||
3232 | /* Juan Pablo Sormani <sorman@gmail.com> */ | ||
3233 | .name = "Encore ENLTV-FM", | ||
3234 | .audio_clock = 0x00200000, | ||
3235 | .tuner_type = TUNER_PHILIPS_ATSC, | ||
3236 | .radio_type = UNSET, | ||
3237 | .tuner_addr = ADDR_UNSET, | ||
3238 | .radio_addr = ADDR_UNSET, | ||
3239 | .inputs = {{ | ||
3240 | .name = name_tv, | ||
3241 | .vmux = 1, | ||
3242 | .amux = 3, | ||
3243 | .tv = 1, | ||
3244 | },{ | ||
3245 | .name = name_tv_mono, | ||
3246 | .vmux = 7, | ||
3247 | .amux = 4, | ||
3248 | .tv = 1, | ||
3249 | },{ | ||
3250 | .name = name_comp1, | ||
3251 | .vmux = 3, | ||
3252 | .amux = 2, | ||
3253 | },{ | ||
3254 | .name = name_svideo, | ||
3255 | .vmux = 0, | ||
3256 | .amux = 2, | ||
3257 | }}, | ||
3258 | .radio = { | ||
3259 | .name = name_radio, | ||
3260 | .amux = LINE2, | ||
3261 | .gpio = 0x20000, | ||
3262 | |||
3263 | }, | ||
3264 | .mute = { | ||
3265 | .name = name_mute, | ||
3266 | .amux = 0, | ||
3267 | }, | ||
3268 | }, | ||
3269 | [SAA7134_BOARD_CINERGY_HT_PCI] = { | ||
3270 | .name = "Terratec Cinergy HT PCI", | ||
3271 | .audio_clock = 0x00187de7, | ||
3272 | .tuner_type = TUNER_PHILIPS_TDA8290, | ||
3273 | .radio_type = UNSET, | ||
3274 | .tuner_addr = ADDR_UNSET, | ||
3275 | .radio_addr = ADDR_UNSET, | ||
3276 | .mpeg = SAA7134_MPEG_DVB, | ||
3277 | .inputs = {{ | ||
3278 | .name = name_tv, | ||
3279 | .vmux = 1, | ||
3280 | .amux = TV, | ||
3281 | .tv = 1, | ||
3282 | },{ | ||
3283 | .name = name_comp1, | ||
3284 | .vmux = 0, | ||
3285 | .amux = LINE1, | ||
3286 | },{ | ||
3287 | .name = name_svideo, | ||
3288 | .vmux = 6, | ||
3289 | .amux = LINE1, | ||
3290 | }}, | ||
3291 | }, | ||
3186 | }; | 3292 | }; |
3187 | 3293 | ||
3188 | const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); | 3294 | const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); |
@@ -3822,6 +3928,36 @@ struct pci_device_id saa7134_pci_tbl[] = { | |||
3822 | .subdevice = 0x1172, | 3928 | .subdevice = 0x1172, |
3823 | .driver_data = SAA7134_BOARD_CINERGY_HT_PCMCIA, | 3929 | .driver_data = SAA7134_BOARD_CINERGY_HT_PCMCIA, |
3824 | },{ | 3930 | },{ |
3931 | .vendor = PCI_VENDOR_ID_PHILIPS, | ||
3932 | .device = PCI_DEVICE_ID_PHILIPS_SAA7130, | ||
3933 | .subvendor = PCI_VENDOR_ID_PHILIPS, | ||
3934 | .subdevice = 0x2342, | ||
3935 | .driver_data = SAA7134_BOARD_ENCORE_ENLTV, | ||
3936 | },{ | ||
3937 | .vendor = PCI_VENDOR_ID_PHILIPS, | ||
3938 | .device = PCI_DEVICE_ID_PHILIPS_SAA7130, | ||
3939 | .subvendor = 0x1131, | ||
3940 | .subdevice = 0x2341, | ||
3941 | .driver_data = SAA7134_BOARD_ENCORE_ENLTV, | ||
3942 | },{ | ||
3943 | .vendor = PCI_VENDOR_ID_PHILIPS, | ||
3944 | .device = PCI_DEVICE_ID_PHILIPS_SAA7130, | ||
3945 | .subvendor = 0x3016, | ||
3946 | .subdevice = 0x2344, | ||
3947 | .driver_data = SAA7134_BOARD_ENCORE_ENLTV, | ||
3948 | },{ | ||
3949 | .vendor = PCI_VENDOR_ID_PHILIPS, | ||
3950 | .device = PCI_DEVICE_ID_PHILIPS_SAA7130, | ||
3951 | .subvendor = 0x1131, | ||
3952 | .subdevice = 0x230f, | ||
3953 | .driver_data = SAA7134_BOARD_ENCORE_ENLTV_FM, | ||
3954 | },{ | ||
3955 | .vendor = PCI_VENDOR_ID_PHILIPS, | ||
3956 | .device = PCI_DEVICE_ID_PHILIPS_SAA7133, | ||
3957 | .subvendor = 0x153b, | ||
3958 | .subdevice = 0x1175, | ||
3959 | .driver_data = SAA7134_BOARD_CINERGY_HT_PCI, | ||
3960 | },{ | ||
3825 | /* --- boards without eeprom + subsystem ID --- */ | 3961 | /* --- boards without eeprom + subsystem ID --- */ |
3826 | .vendor = PCI_VENDOR_ID_PHILIPS, | 3962 | .vendor = PCI_VENDOR_ID_PHILIPS, |
3827 | .device = PCI_DEVICE_ID_PHILIPS_SAA7134, | 3963 | .device = PCI_DEVICE_ID_PHILIPS_SAA7134, |
@@ -3926,9 +4062,12 @@ int saa7134_board_init1(struct saa7134_dev *dev) | |||
3926 | case SAA7134_BOARD_KWORLD_TERMINATOR: | 4062 | case SAA7134_BOARD_KWORLD_TERMINATOR: |
3927 | case SAA7134_BOARD_SEDNA_PC_TV_CARDBUS: | 4063 | case SAA7134_BOARD_SEDNA_PC_TV_CARDBUS: |
3928 | case SAA7134_BOARD_FLYDVBT_LR301: | 4064 | case SAA7134_BOARD_FLYDVBT_LR301: |
4065 | case SAA7134_BOARD_ASUSTeK_P7131_DUAL: | ||
3929 | case SAA7134_BOARD_FLYDVBTDUO: | 4066 | case SAA7134_BOARD_FLYDVBTDUO: |
3930 | case SAA7134_BOARD_PROTEUS_2309: | 4067 | case SAA7134_BOARD_PROTEUS_2309: |
3931 | case SAA7134_BOARD_AVERMEDIA_A16AR: | 4068 | case SAA7134_BOARD_AVERMEDIA_A16AR: |
4069 | case SAA7134_BOARD_ENCORE_ENLTV: | ||
4070 | case SAA7134_BOARD_ENCORE_ENLTV_FM: | ||
3932 | dev->has_remote = SAA7134_REMOTE_GPIO; | 4071 | dev->has_remote = SAA7134_REMOTE_GPIO; |
3933 | break; | 4072 | break; |
3934 | case SAA7134_BOARD_FLYDVBS_LR300: | 4073 | case SAA7134_BOARD_FLYDVBS_LR300: |
@@ -4150,6 +4289,7 @@ int saa7134_board_init2(struct saa7134_dev *dev) | |||
4150 | } | 4289 | } |
4151 | break; | 4290 | break; |
4152 | case SAA7134_BOARD_CINERGY_HT_PCMCIA: | 4291 | case SAA7134_BOARD_CINERGY_HT_PCMCIA: |
4292 | case SAA7134_BOARD_CINERGY_HT_PCI: | ||
4153 | /* make the tda10046 find its eeprom */ | 4293 | /* make the tda10046 find its eeprom */ |
4154 | { | 4294 | { |
4155 | u8 data[] = { 0x3c, 0x33, 0x60}; | 4295 | u8 data[] = { 0x3c, 0x33, 0x60}; |
diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index c33f6a69a247..e3059fd33951 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c | |||
@@ -1426,6 +1426,18 @@ static int dvb_init(struct saa7134_dev *dev) | |||
1426 | 1426 | ||
1427 | } | 1427 | } |
1428 | break; | 1428 | break; |
1429 | case SAA7134_BOARD_CINERGY_HT_PCI: | ||
1430 | dev->dvb.frontend = dvb_attach(tda10046_attach, | ||
1431 | &cinergy_ht_config, | ||
1432 | &dev->i2c_adap); | ||
1433 | if (dev->dvb.frontend) { | ||
1434 | dev->dvb.frontend->ops.i2c_gate_ctrl = tda8290_i2c_gate_ctrl; | ||
1435 | dev->dvb.frontend->ops.tuner_ops.init = cinergy_ht_tuner_init; | ||
1436 | dev->dvb.frontend->ops.tuner_ops.sleep = cinergy_ht_tuner_sleep; | ||
1437 | dev->dvb.frontend->ops.tuner_ops.set_params = md8800_dvbt_pll_set; | ||
1438 | |||
1439 | } | ||
1440 | break; | ||
1429 | default: | 1441 | default: |
1430 | printk("%s: Huh? unknown DVB card?\n",dev->name); | 1442 | printk("%s: Huh? unknown DVB card?\n",dev->name); |
1431 | break; | 1443 | break; |
diff --git a/drivers/media/video/saa7134/saa7134-i2c.c b/drivers/media/video/saa7134/saa7134-i2c.c index 6f9fe86fed98..cce8da6a4f94 100644 --- a/drivers/media/video/saa7134/saa7134-i2c.c +++ b/drivers/media/video/saa7134/saa7134-i2c.c | |||
@@ -120,9 +120,9 @@ static inline int i2c_is_error(enum i2c_status status) | |||
120 | case ARB_LOST: | 120 | case ARB_LOST: |
121 | case SEQ_ERR: | 121 | case SEQ_ERR: |
122 | case ST_ERR: | 122 | case ST_ERR: |
123 | return TRUE; | 123 | return true; |
124 | default: | 124 | default: |
125 | return FALSE; | 125 | return false; |
126 | } | 126 | } |
127 | } | 127 | } |
128 | 128 | ||
@@ -131,9 +131,9 @@ static inline int i2c_is_idle(enum i2c_status status) | |||
131 | switch (status) { | 131 | switch (status) { |
132 | case IDLE: | 132 | case IDLE: |
133 | case DONE_STOP: | 133 | case DONE_STOP: |
134 | return TRUE; | 134 | return true; |
135 | default: | 135 | default: |
136 | return FALSE; | 136 | return false; |
137 | } | 137 | } |
138 | } | 138 | } |
139 | 139 | ||
@@ -141,9 +141,9 @@ static inline int i2c_is_busy(enum i2c_status status) | |||
141 | { | 141 | { |
142 | switch (status) { | 142 | switch (status) { |
143 | case BUSY: | 143 | case BUSY: |
144 | return TRUE; | 144 | return true; |
145 | default: | 145 | default: |
146 | return FALSE; | 146 | return false; |
147 | } | 147 | } |
148 | } | 148 | } |
149 | 149 | ||
@@ -159,8 +159,8 @@ static int i2c_is_busy_wait(struct saa7134_dev *dev) | |||
159 | saa_wait(I2C_WAIT_DELAY); | 159 | saa_wait(I2C_WAIT_DELAY); |
160 | } | 160 | } |
161 | if (I2C_WAIT_RETRY == count) | 161 | if (I2C_WAIT_RETRY == count) |
162 | return FALSE; | 162 | return false; |
163 | return TRUE; | 163 | return true; |
164 | } | 164 | } |
165 | 165 | ||
166 | static int i2c_reset(struct saa7134_dev *dev) | 166 | static int i2c_reset(struct saa7134_dev *dev) |
@@ -171,7 +171,7 @@ static int i2c_reset(struct saa7134_dev *dev) | |||
171 | d2printk(KERN_DEBUG "%s: i2c reset\n",dev->name); | 171 | d2printk(KERN_DEBUG "%s: i2c reset\n",dev->name); |
172 | status = i2c_get_status(dev); | 172 | status = i2c_get_status(dev); |
173 | if (!i2c_is_error(status)) | 173 | if (!i2c_is_error(status)) |
174 | return TRUE; | 174 | return true; |
175 | i2c_set_status(dev,status); | 175 | i2c_set_status(dev,status); |
176 | 176 | ||
177 | for (count = 0; count < I2C_WAIT_RETRY; count++) { | 177 | for (count = 0; count < I2C_WAIT_RETRY; count++) { |
@@ -181,13 +181,13 @@ static int i2c_reset(struct saa7134_dev *dev) | |||
181 | udelay(I2C_WAIT_DELAY); | 181 | udelay(I2C_WAIT_DELAY); |
182 | } | 182 | } |
183 | if (I2C_WAIT_RETRY == count) | 183 | if (I2C_WAIT_RETRY == count) |
184 | return FALSE; | 184 | return false; |
185 | 185 | ||
186 | if (!i2c_is_idle(status)) | 186 | if (!i2c_is_idle(status)) |
187 | return FALSE; | 187 | return false; |
188 | 188 | ||
189 | i2c_set_attr(dev,NOP); | 189 | i2c_set_attr(dev,NOP); |
190 | return TRUE; | 190 | return true; |
191 | } | 191 | } |
192 | 192 | ||
193 | static inline int i2c_send_byte(struct saa7134_dev *dev, | 193 | static inline int i2c_send_byte(struct saa7134_dev *dev, |
diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index e4252683a597..46c583f1e788 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c | |||
@@ -40,16 +40,24 @@ static int pinnacle_remote = 0; | |||
40 | module_param(pinnacle_remote, int, 0644); /* Choose Pinnacle PCTV remote */ | 40 | module_param(pinnacle_remote, int, 0644); /* Choose Pinnacle PCTV remote */ |
41 | MODULE_PARM_DESC(pinnacle_remote, "Specify Pinnacle PCTV remote: 0=coloured, 1=grey (defaults to 0)"); | 41 | MODULE_PARM_DESC(pinnacle_remote, "Specify Pinnacle PCTV remote: 0=coloured, 1=grey (defaults to 0)"); |
42 | 42 | ||
43 | static int ir_rc5_remote_gap = 885; | ||
44 | module_param(ir_rc5_remote_gap, int, 0644); | ||
45 | static int ir_rc5_key_timeout = 115; | ||
46 | module_param(ir_rc5_key_timeout, int, 0644); | ||
47 | |||
43 | #define dprintk(fmt, arg...) if (ir_debug) \ | 48 | #define dprintk(fmt, arg...) if (ir_debug) \ |
44 | printk(KERN_DEBUG "%s/ir: " fmt, dev->name , ## arg) | 49 | printk(KERN_DEBUG "%s/ir: " fmt, dev->name , ## arg) |
45 | #define i2cdprintk(fmt, arg...) if (ir_debug) \ | 50 | #define i2cdprintk(fmt, arg...) if (ir_debug) \ |
46 | printk(KERN_DEBUG "%s/ir: " fmt, ir->c.name , ## arg) | 51 | printk(KERN_DEBUG "%s/ir: " fmt, ir->c.name , ## arg) |
47 | 52 | ||
53 | /** rc5 functions */ | ||
54 | static int saa7134_rc5_irq(struct saa7134_dev *dev); | ||
55 | |||
48 | /* -------------------- GPIO generic keycode builder -------------------- */ | 56 | /* -------------------- GPIO generic keycode builder -------------------- */ |
49 | 57 | ||
50 | static int build_key(struct saa7134_dev *dev) | 58 | static int build_key(struct saa7134_dev *dev) |
51 | { | 59 | { |
52 | struct saa7134_ir *ir = dev->remote; | 60 | struct card_ir *ir = dev->remote; |
53 | u32 gpio, data; | 61 | u32 gpio, data; |
54 | 62 | ||
55 | /* rising SAA7134_GPIO_GPRESCAN reads the status */ | 63 | /* rising SAA7134_GPIO_GPRESCAN reads the status */ |
@@ -134,16 +142,19 @@ static int get_key_hvr1110(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) | |||
134 | 142 | ||
135 | void saa7134_input_irq(struct saa7134_dev *dev) | 143 | void saa7134_input_irq(struct saa7134_dev *dev) |
136 | { | 144 | { |
137 | struct saa7134_ir *ir = dev->remote; | 145 | struct card_ir *ir = dev->remote; |
138 | 146 | ||
139 | if (!ir->polling) | 147 | if (!ir->polling && !ir->rc5_gpio) { |
140 | build_key(dev); | 148 | build_key(dev); |
149 | } else if (ir->rc5_gpio) { | ||
150 | saa7134_rc5_irq(dev); | ||
151 | } | ||
141 | } | 152 | } |
142 | 153 | ||
143 | static void saa7134_input_timer(unsigned long data) | 154 | static void saa7134_input_timer(unsigned long data) |
144 | { | 155 | { |
145 | struct saa7134_dev *dev = (struct saa7134_dev*)data; | 156 | struct saa7134_dev *dev = (struct saa7134_dev*)data; |
146 | struct saa7134_ir *ir = dev->remote; | 157 | struct card_ir *ir = dev->remote; |
147 | unsigned long timeout; | 158 | unsigned long timeout; |
148 | 159 | ||
149 | build_key(dev); | 160 | build_key(dev); |
@@ -151,7 +162,7 @@ static void saa7134_input_timer(unsigned long data) | |||
151 | mod_timer(&ir->timer, timeout); | 162 | mod_timer(&ir->timer, timeout); |
152 | } | 163 | } |
153 | 164 | ||
154 | static void saa7134_ir_start(struct saa7134_dev *dev, struct saa7134_ir *ir) | 165 | static void saa7134_ir_start(struct saa7134_dev *dev, struct card_ir *ir) |
155 | { | 166 | { |
156 | if (ir->polling) { | 167 | if (ir->polling) { |
157 | init_timer(&ir->timer); | 168 | init_timer(&ir->timer); |
@@ -159,6 +170,19 @@ static void saa7134_ir_start(struct saa7134_dev *dev, struct saa7134_ir *ir) | |||
159 | ir->timer.data = (unsigned long)dev; | 170 | ir->timer.data = (unsigned long)dev; |
160 | ir->timer.expires = jiffies + HZ; | 171 | ir->timer.expires = jiffies + HZ; |
161 | add_timer(&ir->timer); | 172 | add_timer(&ir->timer); |
173 | } else if (ir->rc5_gpio) { | ||
174 | /* set timer_end for code completion */ | ||
175 | init_timer(&ir->timer_end); | ||
176 | ir->timer_end.function = ir_rc5_timer_end; | ||
177 | ir->timer_end.data = (unsigned long)ir; | ||
178 | init_timer(&ir->timer_keyup); | ||
179 | ir->timer_keyup.function = ir_rc5_timer_keyup; | ||
180 | ir->timer_keyup.data = (unsigned long)ir; | ||
181 | ir->shift_by = 2; | ||
182 | ir->start = 0x2; | ||
183 | ir->addr = 0x17; | ||
184 | ir->rc5_key_timeout = ir_rc5_key_timeout; | ||
185 | ir->rc5_remote_gap = ir_rc5_remote_gap; | ||
162 | } | 186 | } |
163 | } | 187 | } |
164 | 188 | ||
@@ -170,13 +194,14 @@ static void saa7134_ir_stop(struct saa7134_dev *dev) | |||
170 | 194 | ||
171 | int saa7134_input_init1(struct saa7134_dev *dev) | 195 | int saa7134_input_init1(struct saa7134_dev *dev) |
172 | { | 196 | { |
173 | struct saa7134_ir *ir; | 197 | struct card_ir *ir; |
174 | struct input_dev *input_dev; | 198 | struct input_dev *input_dev; |
175 | IR_KEYTAB_TYPE *ir_codes = NULL; | 199 | IR_KEYTAB_TYPE *ir_codes = NULL; |
176 | u32 mask_keycode = 0; | 200 | u32 mask_keycode = 0; |
177 | u32 mask_keydown = 0; | 201 | u32 mask_keydown = 0; |
178 | u32 mask_keyup = 0; | 202 | u32 mask_keyup = 0; |
179 | int polling = 0; | 203 | int polling = 0; |
204 | int rc5_gpio = 0; | ||
180 | int ir_type = IR_TYPE_OTHER; | 205 | int ir_type = IR_TYPE_OTHER; |
181 | int err; | 206 | int err; |
182 | 207 | ||
@@ -295,6 +320,18 @@ int saa7134_input_init1(struct saa7134_dev *dev) | |||
295 | mask_keycode = 0x0001F00; | 320 | mask_keycode = 0x0001F00; |
296 | mask_keydown = 0x0040000; | 321 | mask_keydown = 0x0040000; |
297 | break; | 322 | break; |
323 | case SAA7134_BOARD_ASUSTeK_P7131_DUAL: | ||
324 | ir_codes = ir_codes_asus_pc39; | ||
325 | mask_keydown = 0x0040000; | ||
326 | rc5_gpio = 1; | ||
327 | break; | ||
328 | case SAA7134_BOARD_ENCORE_ENLTV: | ||
329 | case SAA7134_BOARD_ENCORE_ENLTV_FM: | ||
330 | ir_codes = ir_codes_encore_enltv; | ||
331 | mask_keycode = 0x00007f; | ||
332 | mask_keyup = 0x040000; | ||
333 | polling = 50; // ms | ||
334 | break; | ||
298 | } | 335 | } |
299 | if (NULL == ir_codes) { | 336 | if (NULL == ir_codes) { |
300 | printk("%s: Oops: IR config error [card=%d]\n", | 337 | printk("%s: Oops: IR config error [card=%d]\n", |
@@ -316,6 +353,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) | |||
316 | ir->mask_keydown = mask_keydown; | 353 | ir->mask_keydown = mask_keydown; |
317 | ir->mask_keyup = mask_keyup; | 354 | ir->mask_keyup = mask_keyup; |
318 | ir->polling = polling; | 355 | ir->polling = polling; |
356 | ir->rc5_gpio = rc5_gpio; | ||
319 | 357 | ||
320 | /* init input device */ | 358 | /* init input device */ |
321 | snprintf(ir->name, sizeof(ir->name), "saa7134 IR (%s)", | 359 | snprintf(ir->name, sizeof(ir->name), "saa7134 IR (%s)", |
@@ -402,6 +440,49 @@ void saa7134_set_i2c_ir(struct saa7134_dev *dev, struct IR_i2c *ir) | |||
402 | } | 440 | } |
403 | 441 | ||
404 | } | 442 | } |
443 | |||
444 | static int saa7134_rc5_irq(struct saa7134_dev *dev) | ||
445 | { | ||
446 | struct card_ir *ir = dev->remote; | ||
447 | struct timeval tv; | ||
448 | u32 gap; | ||
449 | unsigned long current_jiffies, timeout; | ||
450 | |||
451 | /* get time of bit */ | ||
452 | current_jiffies = jiffies; | ||
453 | do_gettimeofday(&tv); | ||
454 | |||
455 | /* avoid overflow with gap >1s */ | ||
456 | if (tv.tv_sec - ir->base_time.tv_sec > 1) { | ||
457 | gap = 200000; | ||
458 | } else { | ||
459 | gap = 1000000 * (tv.tv_sec - ir->base_time.tv_sec) + | ||
460 | tv.tv_usec - ir->base_time.tv_usec; | ||
461 | } | ||
462 | |||
463 | /* active code => add bit */ | ||
464 | if (ir->active) { | ||
465 | /* only if in the code (otherwise spurious IRQ or timer | ||
466 | late) */ | ||
467 | if (ir->last_bit < 28) { | ||
468 | ir->last_bit = (gap - ir_rc5_remote_gap / 2) / | ||
469 | ir_rc5_remote_gap; | ||
470 | ir->code |= 1 << ir->last_bit; | ||
471 | } | ||
472 | /* starting new code */ | ||
473 | } else { | ||
474 | ir->active = 1; | ||
475 | ir->code = 0; | ||
476 | ir->base_time = tv; | ||
477 | ir->last_bit = 0; | ||
478 | |||
479 | timeout = current_jiffies + (500 + 30 * HZ) / 1000; | ||
480 | mod_timer(&ir->timer_end, timeout); | ||
481 | } | ||
482 | |||
483 | return 1; | ||
484 | } | ||
485 | |||
405 | /* ---------------------------------------------------------------------- | 486 | /* ---------------------------------------------------------------------- |
406 | * Local variables: | 487 | * Local variables: |
407 | * c-basic-offset: 8 | 488 | * c-basic-offset: 8 |
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 88cd1297df13..b3e3957c89b5 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h | |||
@@ -41,14 +41,10 @@ | |||
41 | #include <sound/driver.h> | 41 | #include <sound/driver.h> |
42 | #include <sound/core.h> | 42 | #include <sound/core.h> |
43 | #include <sound/pcm.h> | 43 | #include <sound/pcm.h> |
44 | #if defined(CONFIG_VIDEO_BUF_DVB) || defined(CONFIG_VIDEO_BUF_DVB_MODULE) | ||
44 | #include <media/video-buf-dvb.h> | 45 | #include <media/video-buf-dvb.h> |
45 | |||
46 | #ifndef TRUE | ||
47 | # define TRUE (1==1) | ||
48 | #endif | ||
49 | #ifndef FALSE | ||
50 | # define FALSE (1==0) | ||
51 | #endif | 46 | #endif |
47 | |||
52 | #define UNSET (-1U) | 48 | #define UNSET (-1U) |
53 | 49 | ||
54 | /* ----------------------------------------------------------- */ | 50 | /* ----------------------------------------------------------- */ |
@@ -232,6 +228,9 @@ struct saa7134_format { | |||
232 | #define SAA7134_BOARD_VIDEOMATE_DVBT_200A 103 | 228 | #define SAA7134_BOARD_VIDEOMATE_DVBT_200A 103 |
233 | #define SAA7134_BOARD_HAUPPAUGE_HVR1110 104 | 229 | #define SAA7134_BOARD_HAUPPAUGE_HVR1110 104 |
234 | #define SAA7134_BOARD_CINERGY_HT_PCMCIA 105 | 230 | #define SAA7134_BOARD_CINERGY_HT_PCMCIA 105 |
231 | #define SAA7134_BOARD_ENCORE_ENLTV 106 | ||
232 | #define SAA7134_BOARD_ENCORE_ENLTV_FM 107 | ||
233 | #define SAA7134_BOARD_CINERGY_HT_PCI 108 | ||
235 | 234 | ||
236 | #define SAA7134_MAXBOARDS 8 | 235 | #define SAA7134_MAXBOARDS 8 |
237 | #define SAA7134_INPUT_MAX 8 | 236 | #define SAA7134_INPUT_MAX 8 |
@@ -411,20 +410,6 @@ struct saa7134_dmasound { | |||
411 | struct snd_pcm_substream *substream; | 410 | struct snd_pcm_substream *substream; |
412 | }; | 411 | }; |
413 | 412 | ||
414 | /* IR input */ | ||
415 | struct saa7134_ir { | ||
416 | struct input_dev *dev; | ||
417 | struct ir_input_state ir; | ||
418 | char name[32]; | ||
419 | char phys[32]; | ||
420 | u32 mask_keycode; | ||
421 | u32 mask_keydown; | ||
422 | u32 mask_keyup; | ||
423 | int polling; | ||
424 | u32 last_gpio; | ||
425 | struct timer_list timer; | ||
426 | }; | ||
427 | |||
428 | /* ts/mpeg status */ | 413 | /* ts/mpeg status */ |
429 | struct saa7134_ts { | 414 | struct saa7134_ts { |
430 | /* TS capture */ | 415 | /* TS capture */ |
@@ -463,7 +448,7 @@ struct saa7134_dev { | |||
463 | 448 | ||
464 | /* infrared remote */ | 449 | /* infrared remote */ |
465 | int has_remote; | 450 | int has_remote; |
466 | struct saa7134_ir *remote; | 451 | struct card_ir *remote; |
467 | 452 | ||
468 | /* pci i/o */ | 453 | /* pci i/o */ |
469 | char name[32]; | 454 | char name[32]; |
@@ -543,9 +528,11 @@ struct saa7134_dev { | |||
543 | struct work_struct empress_workqueue; | 528 | struct work_struct empress_workqueue; |
544 | int empress_started; | 529 | int empress_started; |
545 | 530 | ||
531 | #if defined(CONFIG_VIDEO_BUF_DVB) || defined(CONFIG_VIDEO_BUF_DVB_MODULE) | ||
546 | /* SAA7134_MPEG_DVB only */ | 532 | /* SAA7134_MPEG_DVB only */ |
547 | struct videobuf_dvb dvb; | 533 | struct videobuf_dvb dvb; |
548 | int (*original_demod_sleep)(struct dvb_frontend* fe); | 534 | int (*original_demod_sleep)(struct dvb_frontend* fe); |
535 | #endif | ||
549 | }; | 536 | }; |
550 | 537 | ||
551 | /* ----------------------------------------------------------- */ | 538 | /* ----------------------------------------------------------- */ |
@@ -698,6 +685,7 @@ void saa7134_input_fini(struct saa7134_dev *dev); | |||
698 | void saa7134_input_irq(struct saa7134_dev *dev); | 685 | void saa7134_input_irq(struct saa7134_dev *dev); |
699 | void saa7134_set_i2c_ir(struct saa7134_dev *dev, struct IR_i2c *ir); | 686 | void saa7134_set_i2c_ir(struct saa7134_dev *dev, struct IR_i2c *ir); |
700 | 687 | ||
688 | |||
701 | /* | 689 | /* |
702 | * Local variables: | 690 | * Local variables: |
703 | * c-basic-offset: 8 | 691 | * c-basic-offset: 8 |
diff --git a/drivers/media/video/sn9c102/Kconfig b/drivers/media/video/sn9c102/Kconfig index cf552e6b8ecf..1a7ccb666ab0 100644 --- a/drivers/media/video/sn9c102/Kconfig +++ b/drivers/media/video/sn9c102/Kconfig | |||
@@ -1,9 +1,9 @@ | |||
1 | config USB_SN9C102 | 1 | config USB_SN9C102 |
2 | tristate "USB SN9C10x PC Camera Controller support" | 2 | tristate "USB SN9C1xx PC Camera Controller support" |
3 | depends on USB && VIDEO_V4L1 | 3 | depends on USB && VIDEO_V4L1 |
4 | ---help--- | 4 | ---help--- |
5 | Say Y here if you want support for cameras based on SONiX SN9C101, | 5 | Say Y here if you want support for cameras based on SONiX SN9C101, |
6 | SN9C102 or SN9C103 PC Camera Controllers. | 6 | SN9C102, SN9C103, SN9C105 and SN9C120 PC Camera Controllers. |
7 | 7 | ||
8 | See <file:Documentation/video4linux/sn9c102.txt> for more info. | 8 | See <file:Documentation/video4linux/sn9c102.txt> for more info. |
9 | 9 | ||
diff --git a/drivers/media/video/sn9c102/Makefile b/drivers/media/video/sn9c102/Makefile index 536ad3098da4..30e3dfe537fe 100644 --- a/drivers/media/video/sn9c102/Makefile +++ b/drivers/media/video/sn9c102/Makefile | |||
@@ -1,5 +1,5 @@ | |||
1 | sn9c102-objs := sn9c102_core.o sn9c102_hv7131d.o sn9c102_mi0343.o \ | 1 | sn9c102-objs := sn9c102_core.o sn9c102_hv7131d.o sn9c102_mi0343.o \ |
2 | sn9c102_ov7630.o sn9c102_pas106b.o sn9c102_pas202bca.o \ | 2 | sn9c102_ov7630.o sn9c102_ov7660.o sn9c102_pas106b.o \ |
3 | sn9c102_pas202bcb.o sn9c102_tas5110c1b.o \ | 3 | sn9c102_pas202bcb.o sn9c102_tas5110c1b.o \ |
4 | sn9c102_tas5130d1b.o | 4 | sn9c102_tas5130d1b.o |
5 | 5 | ||
diff --git a/drivers/media/video/sn9c102/sn9c102.h b/drivers/media/video/sn9c102/sn9c102.h index 2c6ff396dafc..5428f34e7c5b 100644 --- a/drivers/media/video/sn9c102/sn9c102.h +++ b/drivers/media/video/sn9c102/sn9c102.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /*************************************************************************** | 1 | /*************************************************************************** |
2 | * V4L2 driver for SN9C10x PC Camera Controllers * | 2 | * V4L2 driver for SN9C1xx PC Camera Controllers * |
3 | * * | 3 | * * |
4 | * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it> * | 4 | * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it> * |
5 | * * | 5 | * * |
@@ -37,33 +37,10 @@ | |||
37 | #include <linux/string.h> | 37 | #include <linux/string.h> |
38 | #include <linux/stddef.h> | 38 | #include <linux/stddef.h> |
39 | 39 | ||
40 | #include "sn9c102_config.h" | ||
40 | #include "sn9c102_sensor.h" | 41 | #include "sn9c102_sensor.h" |
42 | #include "sn9c102_devtable.h" | ||
41 | 43 | ||
42 | /*****************************************************************************/ | ||
43 | |||
44 | #define SN9C102_DEBUG | ||
45 | #define SN9C102_DEBUG_LEVEL 2 | ||
46 | #define SN9C102_MAX_DEVICES 64 | ||
47 | #define SN9C102_PRESERVE_IMGSCALE 0 | ||
48 | #define SN9C102_FORCE_MUNMAP 0 | ||
49 | #define SN9C102_MAX_FRAMES 32 | ||
50 | #define SN9C102_URBS 2 | ||
51 | #define SN9C102_ISO_PACKETS 7 | ||
52 | #define SN9C102_ALTERNATE_SETTING 8 | ||
53 | #define SN9C102_URB_TIMEOUT msecs_to_jiffies(2 * SN9C102_ISO_PACKETS) | ||
54 | #define SN9C102_CTRL_TIMEOUT 300 | ||
55 | #define SN9C102_FRAME_TIMEOUT 2 | ||
56 | |||
57 | /*****************************************************************************/ | ||
58 | |||
59 | enum sn9c102_bridge { | ||
60 | BRIDGE_SN9C101 = 0x01, | ||
61 | BRIDGE_SN9C102 = 0x02, | ||
62 | BRIDGE_SN9C103 = 0x04, | ||
63 | }; | ||
64 | |||
65 | SN9C102_ID_TABLE | ||
66 | SN9C102_SENSOR_TABLE | ||
67 | 44 | ||
68 | enum sn9c102_frame_state { | 45 | enum sn9c102_frame_state { |
69 | F_UNUSED, | 46 | F_UNUSED, |
@@ -99,13 +76,11 @@ enum sn9c102_stream_state { | |||
99 | STREAM_ON, | 76 | STREAM_ON, |
100 | }; | 77 | }; |
101 | 78 | ||
102 | typedef char sn9c103_sof_header_t[18]; | 79 | typedef char sn9c102_sof_header_t[62]; |
103 | typedef char sn9c102_sof_header_t[12]; | ||
104 | typedef char sn9c102_eof_header_t[4]; | ||
105 | 80 | ||
106 | struct sn9c102_sysfs_attr { | 81 | struct sn9c102_sysfs_attr { |
107 | u8 reg, i2c_reg; | 82 | u8 reg, i2c_reg; |
108 | sn9c103_sof_header_t frame_header; | 83 | sn9c102_sof_header_t frame_header; |
109 | }; | 84 | }; |
110 | 85 | ||
111 | struct sn9c102_module_param { | 86 | struct sn9c102_module_param { |
@@ -137,8 +112,8 @@ struct sn9c102_device { | |||
137 | struct v4l2_jpegcompression compression; | 112 | struct v4l2_jpegcompression compression; |
138 | 113 | ||
139 | struct sn9c102_sysfs_attr sysfs; | 114 | struct sn9c102_sysfs_attr sysfs; |
140 | sn9c103_sof_header_t sof_header; | 115 | sn9c102_sof_header_t sof_header; |
141 | u16 reg[63]; | 116 | u16 reg[384]; |
142 | 117 | ||
143 | struct sn9c102_module_param module_param; | 118 | struct sn9c102_module_param module_param; |
144 | 119 | ||
@@ -155,10 +130,7 @@ struct sn9c102_device { | |||
155 | struct sn9c102_device* | 130 | struct sn9c102_device* |
156 | sn9c102_match_id(struct sn9c102_device* cam, const struct usb_device_id *id) | 131 | sn9c102_match_id(struct sn9c102_device* cam, const struct usb_device_id *id) |
157 | { | 132 | { |
158 | if (usb_match_id(usb_ifnum_to_if(cam->usbdev, 0), id)) | 133 | return usb_match_id(usb_ifnum_to_if(cam->usbdev, 0), id) ? cam : NULL; |
159 | return cam; | ||
160 | |||
161 | return NULL; | ||
162 | } | 134 | } |
163 | 135 | ||
164 | 136 | ||
@@ -169,6 +141,19 @@ sn9c102_attach_sensor(struct sn9c102_device* cam, | |||
169 | memcpy(&cam->sensor, sensor, sizeof(struct sn9c102_sensor)); | 141 | memcpy(&cam->sensor, sensor, sizeof(struct sn9c102_sensor)); |
170 | } | 142 | } |
171 | 143 | ||
144 | |||
145 | enum sn9c102_bridge | ||
146 | sn9c102_get_bridge(struct sn9c102_device* cam) | ||
147 | { | ||
148 | return cam->bridge; | ||
149 | } | ||
150 | |||
151 | |||
152 | struct sn9c102_sensor* sn9c102_get_sensor(struct sn9c102_device* cam) | ||
153 | { | ||
154 | return &cam->sensor; | ||
155 | } | ||
156 | |||
172 | /*****************************************************************************/ | 157 | /*****************************************************************************/ |
173 | 158 | ||
174 | #undef DBG | 159 | #undef DBG |
diff --git a/drivers/media/video/sn9c102/sn9c102_config.h b/drivers/media/video/sn9c102/sn9c102_config.h new file mode 100644 index 000000000000..0f4e0378b071 --- /dev/null +++ b/drivers/media/video/sn9c102/sn9c102_config.h | |||
@@ -0,0 +1,86 @@ | |||
1 | /*************************************************************************** | ||
2 | * Global parameters for the V4L2 driver for SN9C1xx PC Camera Controllers * | ||
3 | * * | ||
4 | * Copyright (C) 2007 by Luca Risolia <luca.risolia@studio.unibo.it> * | ||
5 | * * | ||
6 | * This program is free software; you can redistribute it and/or modify * | ||
7 | * it under the terms of the GNU General Public License as published by * | ||
8 | * the Free Software Foundation; either version 2 of the License, or * | ||
9 | * (at your option) any later version. * | ||
10 | * * | ||
11 | * This program is distributed in the hope that it will be useful, * | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | ||
14 | * GNU General Public License for more details. * | ||
15 | * * | ||
16 | * You should have received a copy of the GNU General Public License * | ||
17 | * along with this program; if not, write to the Free Software * | ||
18 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * | ||
19 | ***************************************************************************/ | ||
20 | |||
21 | #ifndef _SN9C102_CONFIG_H_ | ||
22 | #define _SN9C102_CONFIG_H_ | ||
23 | |||
24 | #include <linux/types.h> | ||
25 | #include <linux/jiffies.h> | ||
26 | |||
27 | #define SN9C102_DEBUG | ||
28 | #define SN9C102_DEBUG_LEVEL 2 | ||
29 | #define SN9C102_MAX_DEVICES 64 | ||
30 | #define SN9C102_PRESERVE_IMGSCALE 0 | ||
31 | #define SN9C102_FORCE_MUNMAP 0 | ||
32 | #define SN9C102_MAX_FRAMES 32 | ||
33 | #define SN9C102_URBS 2 | ||
34 | #define SN9C102_ISO_PACKETS 7 | ||
35 | #define SN9C102_ALTERNATE_SETTING 8 | ||
36 | #define SN9C102_URB_TIMEOUT msecs_to_jiffies(2 * SN9C102_ISO_PACKETS) | ||
37 | #define SN9C102_CTRL_TIMEOUT 300 | ||
38 | #define SN9C102_FRAME_TIMEOUT 0 | ||
39 | |||
40 | /*****************************************************************************/ | ||
41 | |||
42 | static const u8 SN9C102_Y_QTABLE0[64] = { | ||
43 | 8, 5, 5, 8, 12, 20, 25, 30, | ||
44 | 6, 6, 7, 9, 13, 29, 30, 27, | ||
45 | 7, 6, 8, 12, 20, 28, 34, 28, | ||
46 | 7, 8, 11, 14, 25, 43, 40, 31, | ||
47 | 9, 11, 18, 28, 34, 54, 51, 38, | ||
48 | 12, 17, 27, 32, 40, 52, 56, 46, | ||
49 | 24, 32, 39, 43, 51, 60, 60, 50, | ||
50 | 36, 46, 47, 49, 56, 50, 51, 49 | ||
51 | }; | ||
52 | |||
53 | static const u8 SN9C102_UV_QTABLE0[64] = { | ||
54 | 8, 9, 12, 23, 49, 49, 49, 49, | ||
55 | 9, 10, 13, 33, 49, 49, 49, 49, | ||
56 | 12, 13, 28, 49, 49, 49, 49, 49, | ||
57 | 23, 33, 49, 49, 49, 49, 49, 49, | ||
58 | 49, 49, 49, 49, 49, 49, 49, 49, | ||
59 | 49, 49, 49, 49, 49, 49, 49, 49, | ||
60 | 49, 49, 49, 49, 49, 49, 49, 49, | ||
61 | 49, 49, 49, 49, 49, 49, 49, 49 | ||
62 | }; | ||
63 | |||
64 | static const u8 SN9C102_Y_QTABLE1[64] = { | ||
65 | 16, 11, 10, 16, 24, 40, 51, 61, | ||
66 | 12, 12, 14, 19, 26, 58, 60, 55, | ||
67 | 14, 13, 16, 24, 40, 57, 69, 56, | ||
68 | 14, 17, 22, 29, 51, 87, 80, 62, | ||
69 | 18, 22, 37, 56, 68, 109, 103, 77, | ||
70 | 24, 35, 55, 64, 81, 104, 113, 92, | ||
71 | 49, 64, 78, 87, 103, 121, 120, 101, | ||
72 | 72, 92, 95, 98, 112, 100, 103, 99 | ||
73 | }; | ||
74 | |||
75 | static const u8 SN9C102_UV_QTABLE1[64] = { | ||
76 | 17, 18, 24, 47, 99, 99, 99, 99, | ||
77 | 18, 21, 26, 66, 99, 99, 99, 99, | ||
78 | 24, 26, 56, 99, 99, 99, 99, 99, | ||
79 | 47, 66, 99, 99, 99, 99, 99, 99, | ||
80 | 99, 99, 99, 99, 99, 99, 99, 99, | ||
81 | 99, 99, 99, 99, 99, 99, 99, 99, | ||
82 | 99, 99, 99, 99, 99, 99, 99, 99, | ||
83 | 99, 99, 99, 99, 99, 99, 99, 99 | ||
84 | }; | ||
85 | |||
86 | #endif /* _SN9C102_CONFIG_H_ */ | ||
diff --git a/drivers/media/video/sn9c102/sn9c102_core.c b/drivers/media/video/sn9c102/sn9c102_core.c index 04d4c8f28b89..d0e2b40a7725 100644 --- a/drivers/media/video/sn9c102/sn9c102_core.c +++ b/drivers/media/video/sn9c102/sn9c102_core.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /*************************************************************************** | 1 | /*************************************************************************** |
2 | * V4L2 driver for SN9C10x PC Camera Controllers * | 2 | * V4L2 driver for SN9C1xx PC Camera Controllers * |
3 | * * | 3 | * * |
4 | * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it> * | 4 | * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it> * |
5 | * * | 5 | * * |
6 | * This program is free software; you can redistribute it and/or modify * | 6 | * This program is free software; you can redistribute it and/or modify * |
7 | * it under the terms of the GNU General Public License as published by * | 7 | * it under the terms of the GNU General Public License as published by * |
@@ -43,12 +43,12 @@ | |||
43 | 43 | ||
44 | /*****************************************************************************/ | 44 | /*****************************************************************************/ |
45 | 45 | ||
46 | #define SN9C102_MODULE_NAME "V4L2 driver for SN9C10x PC Camera Controllers" | 46 | #define SN9C102_MODULE_NAME "V4L2 driver for SN9C1xx PC Camera Controllers" |
47 | #define SN9C102_MODULE_AUTHOR "(C) 2004-2006 Luca Risolia" | 47 | #define SN9C102_MODULE_AUTHOR "(C) 2004-2006 Luca Risolia" |
48 | #define SN9C102_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>" | 48 | #define SN9C102_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>" |
49 | #define SN9C102_MODULE_LICENSE "GPL" | 49 | #define SN9C102_MODULE_LICENSE "GPL" |
50 | #define SN9C102_MODULE_VERSION "1:1.27" | 50 | #define SN9C102_MODULE_VERSION "1:1.34" |
51 | #define SN9C102_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 27) | 51 | #define SN9C102_MODULE_VERSION_CODE KERNEL_VERSION(1, 1, 34) |
52 | 52 | ||
53 | /*****************************************************************************/ | 53 | /*****************************************************************************/ |
54 | 54 | ||
@@ -91,7 +91,8 @@ static unsigned int frame_timeout[] = {[0 ... SN9C102_MAX_DEVICES-1] = | |||
91 | SN9C102_FRAME_TIMEOUT}; | 91 | SN9C102_FRAME_TIMEOUT}; |
92 | module_param_array(frame_timeout, uint, NULL, 0644); | 92 | module_param_array(frame_timeout, uint, NULL, 0644); |
93 | MODULE_PARM_DESC(frame_timeout, | 93 | MODULE_PARM_DESC(frame_timeout, |
94 | "\n<n[,...]> Timeout for a video frame in seconds." | 94 | "\n<0|n[,...]> Timeout for a video frame in seconds before" |
95 | "\nreturning an I/O error; 0 for infinity." | ||
95 | "\nThis parameter is specific for each detected camera." | 96 | "\nThis parameter is specific for each detected camera." |
96 | "\nDefault value is "__MODULE_STRING(SN9C102_FRAME_TIMEOUT)"." | 97 | "\nDefault value is "__MODULE_STRING(SN9C102_FRAME_TIMEOUT)"." |
97 | "\n"); | 98 | "\n"); |
@@ -113,32 +114,13 @@ MODULE_PARM_DESC(debug, | |||
113 | 114 | ||
114 | /*****************************************************************************/ | 115 | /*****************************************************************************/ |
115 | 116 | ||
116 | static sn9c102_sof_header_t sn9c102_sof_header[] = { | ||
117 | {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96, 0x00}, | ||
118 | {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96, 0x01}, | ||
119 | }; | ||
120 | |||
121 | static sn9c103_sof_header_t sn9c103_sof_header[] = { | ||
122 | {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96, 0x20}, | ||
123 | }; | ||
124 | |||
125 | static sn9c102_eof_header_t sn9c102_eof_header[] = { | ||
126 | {0x00, 0x00, 0x00, 0x00}, | ||
127 | {0x40, 0x00, 0x00, 0x00}, | ||
128 | {0x80, 0x00, 0x00, 0x00}, | ||
129 | {0xc0, 0x00, 0x00, 0x00}, | ||
130 | }; | ||
131 | |||
132 | /*****************************************************************************/ | ||
133 | |||
134 | static u32 | 117 | static u32 |
135 | sn9c102_request_buffers(struct sn9c102_device* cam, u32 count, | 118 | sn9c102_request_buffers(struct sn9c102_device* cam, u32 count, |
136 | enum sn9c102_io_method io) | 119 | enum sn9c102_io_method io) |
137 | { | 120 | { |
138 | struct v4l2_pix_format* p = &(cam->sensor.pix_format); | 121 | struct v4l2_pix_format* p = &(cam->sensor.pix_format); |
139 | struct v4l2_rect* r = &(cam->sensor.cropcap.bounds); | 122 | struct v4l2_rect* r = &(cam->sensor.cropcap.bounds); |
140 | const size_t imagesize = cam->module_param.force_munmap || | 123 | size_t imagesize = cam->module_param.force_munmap || io == IO_READ ? |
141 | io == IO_READ ? | ||
142 | (p->width * p->height * p->priv) / 8 : | 124 | (p->width * p->height * p->priv) / 8 : |
143 | (r->width * r->height * p->priv) / 8; | 125 | (r->width * r->height * p->priv) / 8; |
144 | void* buff = NULL; | 126 | void* buff = NULL; |
@@ -147,9 +129,13 @@ sn9c102_request_buffers(struct sn9c102_device* cam, u32 count, | |||
147 | if (count > SN9C102_MAX_FRAMES) | 129 | if (count > SN9C102_MAX_FRAMES) |
148 | count = SN9C102_MAX_FRAMES; | 130 | count = SN9C102_MAX_FRAMES; |
149 | 131 | ||
132 | if (cam->bridge == BRIDGE_SN9C105 || cam->bridge == BRIDGE_SN9C120) | ||
133 | imagesize += 589 + 2; /* length of JPEG header + EOI marker */ | ||
134 | |||
150 | cam->nbuffers = count; | 135 | cam->nbuffers = count; |
151 | while (cam->nbuffers > 0) { | 136 | while (cam->nbuffers > 0) { |
152 | if ((buff = vmalloc_32(cam->nbuffers * PAGE_ALIGN(imagesize)))) | 137 | if ((buff = vmalloc_32_user(cam->nbuffers * |
138 | PAGE_ALIGN(imagesize)))) | ||
153 | break; | 139 | break; |
154 | cam->nbuffers--; | 140 | cam->nbuffers--; |
155 | } | 141 | } |
@@ -322,9 +308,21 @@ static int | |||
322 | sn9c102_i2c_detect_read_error(struct sn9c102_device* cam, | 308 | sn9c102_i2c_detect_read_error(struct sn9c102_device* cam, |
323 | struct sn9c102_sensor* sensor) | 309 | struct sn9c102_sensor* sensor) |
324 | { | 310 | { |
325 | int r; | 311 | int r , err = 0; |
312 | |||
326 | r = sn9c102_read_reg(cam, 0x08); | 313 | r = sn9c102_read_reg(cam, 0x08); |
327 | return (r < 0 || (r >= 0 && !(r & 0x08))) ? -EIO : 0; | 314 | if (r < 0) |
315 | err += r; | ||
316 | |||
317 | if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102) { | ||
318 | if (!(r & 0x08)) | ||
319 | err += -1; | ||
320 | } else { | ||
321 | if (r & 0x08) | ||
322 | err += -1; | ||
323 | } | ||
324 | |||
325 | return err ? -EIO : 0; | ||
328 | } | 326 | } |
329 | 327 | ||
330 | 328 | ||
@@ -415,7 +413,7 @@ sn9c102_i2c_try_raw_write(struct sn9c102_device* cam, | |||
415 | data[4] = data3; | 413 | data[4] = data3; |
416 | data[5] = data4; | 414 | data[5] = data4; |
417 | data[6] = data5; | 415 | data[6] = data5; |
418 | data[7] = 0x14; | 416 | data[7] = 0x17; |
419 | res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41, | 417 | res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41, |
420 | 0x08, 0, data, 8, SN9C102_CTRL_TIMEOUT); | 418 | 0x08, 0, data, 8, SN9C102_CTRL_TIMEOUT); |
421 | if (res < 0) | 419 | if (res < 0) |
@@ -467,31 +465,35 @@ int sn9c102_i2c_write(struct sn9c102_device* cam, u8 address, u8 value) | |||
467 | 465 | ||
468 | /*****************************************************************************/ | 466 | /*****************************************************************************/ |
469 | 467 | ||
470 | static void* | 468 | static size_t sn9c102_sof_length(struct sn9c102_device* cam) |
471 | sn9c102_find_sof_header(struct sn9c102_device* cam, void* mem, size_t len) | ||
472 | { | 469 | { |
473 | size_t soflen = 0, i; | ||
474 | u8 j, n = 0; | ||
475 | |||
476 | switch (cam->bridge) { | 470 | switch (cam->bridge) { |
477 | case BRIDGE_SN9C101: | 471 | case BRIDGE_SN9C101: |
478 | case BRIDGE_SN9C102: | 472 | case BRIDGE_SN9C102: |
479 | soflen = sizeof(sn9c102_sof_header_t); | 473 | return 12; |
480 | n = sizeof(sn9c102_sof_header) / soflen; | ||
481 | break; | ||
482 | case BRIDGE_SN9C103: | 474 | case BRIDGE_SN9C103: |
483 | soflen = sizeof(sn9c103_sof_header_t); | 475 | return 18; |
484 | n = sizeof(sn9c103_sof_header) / soflen; | 476 | case BRIDGE_SN9C105: |
477 | case BRIDGE_SN9C120: | ||
478 | return 62; | ||
485 | } | 479 | } |
486 | 480 | ||
481 | return 0; | ||
482 | } | ||
483 | |||
484 | |||
485 | static void* | ||
486 | sn9c102_find_sof_header(struct sn9c102_device* cam, void* mem, size_t len) | ||
487 | { | ||
488 | char sof_header[6] = {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96}; | ||
489 | size_t soflen = 0, i; | ||
490 | |||
491 | soflen = sn9c102_sof_length(cam); | ||
492 | |||
487 | for (i = 0; (len >= soflen) && (i <= len - soflen); i++) | 493 | for (i = 0; (len >= soflen) && (i <= len - soflen); i++) |
488 | for (j = 0; j < n; j++) | 494 | if (!memcmp(mem + i, sof_header, sizeof(sof_header))) { |
489 | /* The invariable part of the header is 6 bytes long */ | 495 | memcpy(cam->sof_header, mem + i, |
490 | if ((cam->bridge != BRIDGE_SN9C103 && | 496 | sizeof(sn9c102_sof_header_t)); |
491 | !memcmp(mem + i, sn9c102_sof_header[j], 6)) || | ||
492 | (cam->bridge == BRIDGE_SN9C103 && | ||
493 | !memcmp(mem + i, sn9c103_sof_header[j], 6))) { | ||
494 | memcpy(cam->sof_header, mem + i, soflen); | ||
495 | /* Skip the header */ | 497 | /* Skip the header */ |
496 | return mem + i + soflen; | 498 | return mem + i + soflen; |
497 | } | 499 | } |
@@ -503,21 +505,123 @@ sn9c102_find_sof_header(struct sn9c102_device* cam, void* mem, size_t len) | |||
503 | static void* | 505 | static void* |
504 | sn9c102_find_eof_header(struct sn9c102_device* cam, void* mem, size_t len) | 506 | sn9c102_find_eof_header(struct sn9c102_device* cam, void* mem, size_t len) |
505 | { | 507 | { |
506 | size_t eoflen = sizeof(sn9c102_eof_header_t), i; | 508 | char eof_header[4][4] = { |
507 | unsigned j, n = sizeof(sn9c102_eof_header) / eoflen; | 509 | {0x00, 0x00, 0x00, 0x00}, |
510 | {0x40, 0x00, 0x00, 0x00}, | ||
511 | {0x80, 0x00, 0x00, 0x00}, | ||
512 | {0xc0, 0x00, 0x00, 0x00}, | ||
513 | }; | ||
514 | size_t i, j; | ||
508 | 515 | ||
509 | if (cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X) | 516 | if (cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X || |
517 | cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_JPEG) | ||
510 | return NULL; /* EOF header does not exist in compressed data */ | 518 | return NULL; /* EOF header does not exist in compressed data */ |
511 | 519 | ||
512 | for (i = 0; (len >= eoflen) && (i <= len - eoflen); i++) | 520 | for (i = 0; (len >= 4) && (i <= len - 4); i++) |
513 | for (j = 0; j < n; j++) | 521 | for (j = 0; j < ARRAY_SIZE(eof_header); j++) |
514 | if (!memcmp(mem + i, sn9c102_eof_header[j], eoflen)) | 522 | if (!memcmp(mem + i, eof_header[j], 4)) |
515 | return mem + i; | 523 | return mem + i; |
516 | 524 | ||
517 | return NULL; | 525 | return NULL; |
518 | } | 526 | } |
519 | 527 | ||
520 | 528 | ||
529 | static void | ||
530 | sn9c102_write_jpegheader(struct sn9c102_device* cam, struct sn9c102_frame_t* f) | ||
531 | { | ||
532 | static u8 jpeg_header[589] = { | ||
533 | 0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x06, 0x04, 0x05, | ||
534 | 0x06, 0x05, 0x04, 0x06, 0x06, 0x05, 0x06, 0x07, 0x07, 0x06, | ||
535 | 0x08, 0x0a, 0x10, 0x0a, 0x0a, 0x09, 0x09, 0x0a, 0x14, 0x0e, | ||
536 | 0x0f, 0x0c, 0x10, 0x17, 0x14, 0x18, 0x18, 0x17, 0x14, 0x16, | ||
537 | 0x16, 0x1a, 0x1d, 0x25, 0x1f, 0x1a, 0x1b, 0x23, 0x1c, 0x16, | ||
538 | 0x16, 0x20, 0x2c, 0x20, 0x23, 0x26, 0x27, 0x29, 0x2a, 0x29, | ||
539 | 0x19, 0x1f, 0x2d, 0x30, 0x2d, 0x28, 0x30, 0x25, 0x28, 0x29, | ||
540 | 0x28, 0x01, 0x07, 0x07, 0x07, 0x0a, 0x08, 0x0a, 0x13, 0x0a, | ||
541 | 0x0a, 0x13, 0x28, 0x1a, 0x16, 0x1a, 0x28, 0x28, 0x28, 0x28, | ||
542 | 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, | ||
543 | 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, | ||
544 | 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, | ||
545 | 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, | ||
546 | 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0xff, 0xc4, 0x01, 0xa2, | ||
547 | 0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, | ||
548 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, | ||
549 | 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x01, | ||
550 | 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, | ||
551 | 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, | ||
552 | 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x10, 0x00, | ||
553 | 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05, 0x05, 0x04, | ||
554 | 0x04, 0x00, 0x00, 0x01, 0x7d, 0x01, 0x02, 0x03, 0x00, 0x04, | ||
555 | 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, | ||
556 | 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, 0x23, | ||
557 | 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, 0x24, 0x33, 0x62, | ||
558 | 0x72, 0x82, 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x25, | ||
559 | 0x26, 0x27, 0x28, 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, | ||
560 | 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, | ||
561 | 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, | ||
562 | 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, | ||
563 | 0x77, 0x78, 0x79, 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, | ||
564 | 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, | ||
565 | 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, | ||
566 | 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, | ||
567 | 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, | ||
568 | 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, 0xe3, | ||
569 | 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1, 0xf2, 0xf3, | ||
570 | 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0x11, 0x00, 0x02, | ||
571 | 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05, 0x04, 0x04, | ||
572 | 0x00, 0x01, 0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, | ||
573 | 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, | ||
574 | 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xa1, 0xb1, | ||
575 | 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, 0x15, 0x62, 0x72, 0xd1, | ||
576 | 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, | ||
577 | 0x1a, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, | ||
578 | 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, | ||
579 | 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, | ||
580 | 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, | ||
581 | 0x77, 0x78, 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, | ||
582 | 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, | ||
583 | 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, | ||
584 | 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, | ||
585 | 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, | ||
586 | 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe2, 0xe3, | ||
587 | 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf2, 0xf3, 0xf4, | ||
588 | 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xff, 0xc0, 0x00, 0x11, | ||
589 | 0x08, 0x01, 0xe0, 0x02, 0x80, 0x03, 0x01, 0x21, 0x00, 0x02, | ||
590 | 0x11, 0x01, 0x03, 0x11, 0x01, 0xff, 0xda, 0x00, 0x0c, 0x03, | ||
591 | 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00 | ||
592 | }; | ||
593 | u8 *pos = f->bufmem; | ||
594 | |||
595 | memcpy(pos, jpeg_header, sizeof(jpeg_header)); | ||
596 | *(pos + 6) = 0x00; | ||
597 | *(pos + 7 + 64) = 0x01; | ||
598 | if (cam->compression.quality == 0) { | ||
599 | memcpy(pos + 7, SN9C102_Y_QTABLE0, 64); | ||
600 | memcpy(pos + 8 + 64, SN9C102_UV_QTABLE0, 64); | ||
601 | } else if (cam->compression.quality == 1) { | ||
602 | memcpy(pos + 7, SN9C102_Y_QTABLE1, 64); | ||
603 | memcpy(pos + 8 + 64, SN9C102_UV_QTABLE1, 64); | ||
604 | } | ||
605 | *(pos + 564) = cam->sensor.pix_format.width & 0xFF; | ||
606 | *(pos + 563) = (cam->sensor.pix_format.width >> 8) & 0xFF; | ||
607 | *(pos + 562) = cam->sensor.pix_format.height & 0xFF; | ||
608 | *(pos + 561) = (cam->sensor.pix_format.height >> 8) & 0xFF; | ||
609 | *(pos + 567) = 0x21; | ||
610 | |||
611 | f->buf.bytesused += sizeof(jpeg_header); | ||
612 | } | ||
613 | |||
614 | |||
615 | static void | ||
616 | sn9c102_write_eoimarker(struct sn9c102_device* cam, struct sn9c102_frame_t* f) | ||
617 | { | ||
618 | static const u8 eoi_marker[2] = {0xff, 0xd9}; | ||
619 | |||
620 | memcpy(f->bufmem + f->buf.bytesused, eoi_marker, sizeof(eoi_marker)); | ||
621 | f->buf.bytesused += sizeof(eoi_marker); | ||
622 | } | ||
623 | |||
624 | |||
521 | static void sn9c102_urb_complete(struct urb *urb) | 625 | static void sn9c102_urb_complete(struct urb *urb) |
522 | { | 626 | { |
523 | struct sn9c102_device* cam = urb->context; | 627 | struct sn9c102_device* cam = urb->context; |
@@ -535,7 +639,7 @@ static void sn9c102_urb_complete(struct urb *urb) | |||
535 | cam->stream = STREAM_OFF; | 639 | cam->stream = STREAM_OFF; |
536 | if ((*f)) | 640 | if ((*f)) |
537 | (*f)->state = F_QUEUED; | 641 | (*f)->state = F_QUEUED; |
538 | DBG(3, "Stream interrupted"); | 642 | DBG(3, "Stream interrupted by application"); |
539 | wake_up(&cam->wait_stream); | 643 | wake_up(&cam->wait_stream); |
540 | } | 644 | } |
541 | 645 | ||
@@ -557,10 +661,9 @@ static void sn9c102_urb_complete(struct urb *urb) | |||
557 | imagesize = (cam->sensor.pix_format.width * | 661 | imagesize = (cam->sensor.pix_format.width * |
558 | cam->sensor.pix_format.height * | 662 | cam->sensor.pix_format.height * |
559 | cam->sensor.pix_format.priv) / 8; | 663 | cam->sensor.pix_format.priv) / 8; |
560 | 664 | if (cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_JPEG) | |
561 | soflen = (cam->bridge) == BRIDGE_SN9C103 ? | 665 | imagesize += 589; /* length of jpeg header */ |
562 | sizeof(sn9c103_sof_header_t) : | 666 | soflen = sn9c102_sof_length(cam); |
563 | sizeof(sn9c102_sof_header_t); | ||
564 | 667 | ||
565 | for (i = 0; i < urb->number_of_packets; i++) { | 668 | for (i = 0; i < urb->number_of_packets; i++) { |
566 | unsigned int img, len, status; | 669 | unsigned int img, len, status; |
@@ -610,12 +713,21 @@ end_of_frame: | |||
610 | (*f)->buf.bytesused += img; | 713 | (*f)->buf.bytesused += img; |
611 | 714 | ||
612 | if ((*f)->buf.bytesused == imagesize || | 715 | if ((*f)->buf.bytesused == imagesize || |
613 | (cam->sensor.pix_format.pixelformat == | 716 | ((cam->sensor.pix_format.pixelformat == |
614 | V4L2_PIX_FMT_SN9C10X && eof)) { | 717 | V4L2_PIX_FMT_SN9C10X || |
718 | cam->sensor.pix_format.pixelformat == | ||
719 | V4L2_PIX_FMT_JPEG) && eof)) { | ||
615 | u32 b; | 720 | u32 b; |
721 | |||
722 | if (cam->sensor.pix_format.pixelformat | ||
723 | == V4L2_PIX_FMT_JPEG) | ||
724 | sn9c102_write_eoimarker(cam, | ||
725 | (*f)); | ||
726 | |||
616 | b = (*f)->buf.bytesused; | 727 | b = (*f)->buf.bytesused; |
617 | (*f)->state = F_DONE; | 728 | (*f)->state = F_DONE; |
618 | (*f)->buf.sequence= ++cam->frame_count; | 729 | (*f)->buf.sequence= ++cam->frame_count; |
730 | |||
619 | spin_lock(&cam->queue_lock); | 731 | spin_lock(&cam->queue_lock); |
620 | list_move_tail(&(*f)->frame, | 732 | list_move_tail(&(*f)->frame, |
621 | &cam->outqueue); | 733 | &cam->outqueue); |
@@ -627,8 +739,10 @@ end_of_frame: | |||
627 | else | 739 | else |
628 | (*f) = NULL; | 740 | (*f) = NULL; |
629 | spin_unlock(&cam->queue_lock); | 741 | spin_unlock(&cam->queue_lock); |
742 | |||
630 | memcpy(cam->sysfs.frame_header, | 743 | memcpy(cam->sysfs.frame_header, |
631 | cam->sof_header, soflen); | 744 | cam->sof_header, soflen); |
745 | |||
632 | DBG(3, "Video frame captured: %lu " | 746 | DBG(3, "Video frame captured: %lu " |
633 | "bytes", (unsigned long)(b)); | 747 | "bytes", (unsigned long)(b)); |
634 | 748 | ||
@@ -661,6 +775,9 @@ start_of_frame: | |||
661 | (*f)->buf.bytesused = 0; | 775 | (*f)->buf.bytesused = 0; |
662 | len -= (sof - pos); | 776 | len -= (sof - pos); |
663 | pos = sof; | 777 | pos = sof; |
778 | if (cam->sensor.pix_format.pixelformat == | ||
779 | V4L2_PIX_FMT_JPEG) | ||
780 | sn9c102_write_jpegheader(cam, (*f)); | ||
664 | DBG(3, "SOF detected: new video frame"); | 781 | DBG(3, "SOF detected: new video frame"); |
665 | if (len) | 782 | if (len) |
666 | goto redo; | 783 | goto redo; |
@@ -671,7 +788,9 @@ start_of_frame: | |||
671 | goto end_of_frame; /* (1) */ | 788 | goto end_of_frame; /* (1) */ |
672 | else { | 789 | else { |
673 | if (cam->sensor.pix_format.pixelformat == | 790 | if (cam->sensor.pix_format.pixelformat == |
674 | V4L2_PIX_FMT_SN9C10X) { | 791 | V4L2_PIX_FMT_SN9C10X || |
792 | cam->sensor.pix_format.pixelformat == | ||
793 | V4L2_PIX_FMT_JPEG) { | ||
675 | eof = sof - soflen; | 794 | eof = sof - soflen; |
676 | goto end_of_frame; | 795 | goto end_of_frame; |
677 | } else { | 796 | } else { |
@@ -701,13 +820,11 @@ static int sn9c102_start_transfer(struct sn9c102_device* cam) | |||
701 | { | 820 | { |
702 | struct usb_device *udev = cam->usbdev; | 821 | struct usb_device *udev = cam->usbdev; |
703 | struct urb* urb; | 822 | struct urb* urb; |
704 | const unsigned int sn9c102_wMaxPacketSize[] = {0, 128, 256, 384, 512, | 823 | struct usb_host_interface* altsetting = usb_altnum_to_altsetting( |
705 | 680, 800, 900, 1023}; | 824 | usb_ifnum_to_if(udev, 0), |
706 | const unsigned int sn9c103_wMaxPacketSize[] = {0, 128, 256, 384, 512, | 825 | SN9C102_ALTERNATE_SETTING); |
707 | 680, 800, 900, 1003}; | 826 | const unsigned int psz = le16_to_cpu(altsetting-> |
708 | const unsigned int psz = (cam->bridge == BRIDGE_SN9C103) ? | 827 | endpoint[0].desc.wMaxPacketSize); |
709 | sn9c103_wMaxPacketSize[SN9C102_ALTERNATE_SETTING] : | ||
710 | sn9c102_wMaxPacketSize[SN9C102_ALTERNATE_SETTING]; | ||
711 | s8 i, j; | 828 | s8 i, j; |
712 | int err = 0; | 829 | int err = 0; |
713 | 830 | ||
@@ -775,7 +892,7 @@ static int sn9c102_start_transfer(struct sn9c102_device* cam) | |||
775 | return 0; | 892 | return 0; |
776 | 893 | ||
777 | free_urbs: | 894 | free_urbs: |
778 | for (i = 0; i < SN9C102_URBS; i++) | 895 | for (i = 0; (i < SN9C102_URBS) && cam->urb[i]; i++) |
779 | usb_free_urb(cam->urb[i]); | 896 | usb_free_urb(cam->urb[i]); |
780 | 897 | ||
781 | free_buffers: | 898 | free_buffers: |
@@ -834,29 +951,29 @@ static int sn9c102_stream_interrupt(struct sn9c102_device* cam) | |||
834 | /*****************************************************************************/ | 951 | /*****************************************************************************/ |
835 | 952 | ||
836 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 953 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
837 | static u8 sn9c102_strtou8(const char* buff, size_t len, ssize_t* count) | 954 | static u16 sn9c102_strtou16(const char* buff, size_t len, ssize_t* count) |
838 | { | 955 | { |
839 | char str[5]; | 956 | char str[7]; |
840 | char* endp; | 957 | char* endp; |
841 | unsigned long val; | 958 | unsigned long val; |
842 | 959 | ||
843 | if (len < 4) { | 960 | if (len < 6) { |
844 | strncpy(str, buff, len); | 961 | strncpy(str, buff, len); |
845 | str[len+1] = '\0'; | 962 | str[len+1] = '\0'; |
846 | } else { | 963 | } else { |
847 | strncpy(str, buff, 4); | 964 | strncpy(str, buff, 4); |
848 | str[4] = '\0'; | 965 | str[6] = '\0'; |
849 | } | 966 | } |
850 | 967 | ||
851 | val = simple_strtoul(str, &endp, 0); | 968 | val = simple_strtoul(str, &endp, 0); |
852 | 969 | ||
853 | *count = 0; | 970 | *count = 0; |
854 | if (val <= 0xff) | 971 | if (val <= 0xffff) |
855 | *count = (ssize_t)(endp - str); | 972 | *count = (ssize_t)(endp - str); |
856 | if ((*count) && (len == *count+1) && (buff[*count] == '\n')) | 973 | if ((*count) && (len == *count+1) && (buff[*count] == '\n')) |
857 | *count += 1; | 974 | *count += 1; |
858 | 975 | ||
859 | return (u8)val; | 976 | return (u16)val; |
860 | } | 977 | } |
861 | 978 | ||
862 | /* | 979 | /* |
@@ -873,7 +990,8 @@ static ssize_t sn9c102_show_reg(struct class_device* cd, char* buf) | |||
873 | if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) | 990 | if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) |
874 | return -ERESTARTSYS; | 991 | return -ERESTARTSYS; |
875 | 992 | ||
876 | cam = video_get_drvdata(to_video_device(cd)); | 993 | cam = video_get_drvdata(container_of(cd, struct video_device, |
994 | class_dev)); | ||
877 | if (!cam) { | 995 | if (!cam) { |
878 | mutex_unlock(&sn9c102_sysfs_lock); | 996 | mutex_unlock(&sn9c102_sysfs_lock); |
879 | return -ENODEV; | 997 | return -ENODEV; |
@@ -891,27 +1009,28 @@ static ssize_t | |||
891 | sn9c102_store_reg(struct class_device* cd, const char* buf, size_t len) | 1009 | sn9c102_store_reg(struct class_device* cd, const char* buf, size_t len) |
892 | { | 1010 | { |
893 | struct sn9c102_device* cam; | 1011 | struct sn9c102_device* cam; |
894 | u8 index; | 1012 | u16 index; |
895 | ssize_t count; | 1013 | ssize_t count; |
896 | 1014 | ||
897 | if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) | 1015 | if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) |
898 | return -ERESTARTSYS; | 1016 | return -ERESTARTSYS; |
899 | 1017 | ||
900 | cam = video_get_drvdata(to_video_device(cd)); | 1018 | cam = video_get_drvdata(container_of(cd, struct video_device, |
1019 | class_dev)); | ||
901 | if (!cam) { | 1020 | if (!cam) { |
902 | mutex_unlock(&sn9c102_sysfs_lock); | 1021 | mutex_unlock(&sn9c102_sysfs_lock); |
903 | return -ENODEV; | 1022 | return -ENODEV; |
904 | } | 1023 | } |
905 | 1024 | ||
906 | index = sn9c102_strtou8(buf, len, &count); | 1025 | index = sn9c102_strtou16(buf, len, &count); |
907 | if (index > 0x1f || !count) { | 1026 | if (index >= ARRAY_SIZE(cam->reg) || !count) { |
908 | mutex_unlock(&sn9c102_sysfs_lock); | 1027 | mutex_unlock(&sn9c102_sysfs_lock); |
909 | return -EINVAL; | 1028 | return -EINVAL; |
910 | } | 1029 | } |
911 | 1030 | ||
912 | cam->sysfs.reg = index; | 1031 | cam->sysfs.reg = index; |
913 | 1032 | ||
914 | DBG(2, "Moved SN9C10X register index to 0x%02X", cam->sysfs.reg); | 1033 | DBG(2, "Moved SN9C1XX register index to 0x%02X", cam->sysfs.reg); |
915 | DBG(3, "Written bytes: %zd", count); | 1034 | DBG(3, "Written bytes: %zd", count); |
916 | 1035 | ||
917 | mutex_unlock(&sn9c102_sysfs_lock); | 1036 | mutex_unlock(&sn9c102_sysfs_lock); |
@@ -929,7 +1048,8 @@ static ssize_t sn9c102_show_val(struct class_device* cd, char* buf) | |||
929 | if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) | 1048 | if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) |
930 | return -ERESTARTSYS; | 1049 | return -ERESTARTSYS; |
931 | 1050 | ||
932 | cam = video_get_drvdata(to_video_device(cd)); | 1051 | cam = video_get_drvdata(container_of(cd, struct video_device, |
1052 | class_dev)); | ||
933 | if (!cam) { | 1053 | if (!cam) { |
934 | mutex_unlock(&sn9c102_sysfs_lock); | 1054 | mutex_unlock(&sn9c102_sysfs_lock); |
935 | return -ENODEV; | 1055 | return -ENODEV; |
@@ -954,20 +1074,21 @@ static ssize_t | |||
954 | sn9c102_store_val(struct class_device* cd, const char* buf, size_t len) | 1074 | sn9c102_store_val(struct class_device* cd, const char* buf, size_t len) |
955 | { | 1075 | { |
956 | struct sn9c102_device* cam; | 1076 | struct sn9c102_device* cam; |
957 | u8 value; | 1077 | u16 value; |
958 | ssize_t count; | 1078 | ssize_t count; |
959 | int err; | 1079 | int err; |
960 | 1080 | ||
961 | if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) | 1081 | if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) |
962 | return -ERESTARTSYS; | 1082 | return -ERESTARTSYS; |
963 | 1083 | ||
964 | cam = video_get_drvdata(to_video_device(cd)); | 1084 | cam = video_get_drvdata(container_of(cd, struct video_device, |
1085 | class_dev)); | ||
965 | if (!cam) { | 1086 | if (!cam) { |
966 | mutex_unlock(&sn9c102_sysfs_lock); | 1087 | mutex_unlock(&sn9c102_sysfs_lock); |
967 | return -ENODEV; | 1088 | return -ENODEV; |
968 | } | 1089 | } |
969 | 1090 | ||
970 | value = sn9c102_strtou8(buf, len, &count); | 1091 | value = sn9c102_strtou16(buf, len, &count); |
971 | if (!count) { | 1092 | if (!count) { |
972 | mutex_unlock(&sn9c102_sysfs_lock); | 1093 | mutex_unlock(&sn9c102_sysfs_lock); |
973 | return -EINVAL; | 1094 | return -EINVAL; |
@@ -979,7 +1100,7 @@ sn9c102_store_val(struct class_device* cd, const char* buf, size_t len) | |||
979 | return -EIO; | 1100 | return -EIO; |
980 | } | 1101 | } |
981 | 1102 | ||
982 | DBG(2, "Written SN9C10X reg. 0x%02X, val. 0x%02X", | 1103 | DBG(2, "Written SN9C1XX reg. 0x%02X, val. 0x%02X", |
983 | cam->sysfs.reg, value); | 1104 | cam->sysfs.reg, value); |
984 | DBG(3, "Written bytes: %zd", count); | 1105 | DBG(3, "Written bytes: %zd", count); |
985 | 1106 | ||
@@ -997,7 +1118,8 @@ static ssize_t sn9c102_show_i2c_reg(struct class_device* cd, char* buf) | |||
997 | if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) | 1118 | if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) |
998 | return -ERESTARTSYS; | 1119 | return -ERESTARTSYS; |
999 | 1120 | ||
1000 | cam = video_get_drvdata(to_video_device(cd)); | 1121 | cam = video_get_drvdata(container_of(cd, struct video_device, |
1122 | class_dev)); | ||
1001 | if (!cam) { | 1123 | if (!cam) { |
1002 | mutex_unlock(&sn9c102_sysfs_lock); | 1124 | mutex_unlock(&sn9c102_sysfs_lock); |
1003 | return -ENODEV; | 1125 | return -ENODEV; |
@@ -1017,19 +1139,20 @@ static ssize_t | |||
1017 | sn9c102_store_i2c_reg(struct class_device* cd, const char* buf, size_t len) | 1139 | sn9c102_store_i2c_reg(struct class_device* cd, const char* buf, size_t len) |
1018 | { | 1140 | { |
1019 | struct sn9c102_device* cam; | 1141 | struct sn9c102_device* cam; |
1020 | u8 index; | 1142 | u16 index; |
1021 | ssize_t count; | 1143 | ssize_t count; |
1022 | 1144 | ||
1023 | if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) | 1145 | if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) |
1024 | return -ERESTARTSYS; | 1146 | return -ERESTARTSYS; |
1025 | 1147 | ||
1026 | cam = video_get_drvdata(to_video_device(cd)); | 1148 | cam = video_get_drvdata(container_of(cd, struct video_device, |
1149 | class_dev)); | ||
1027 | if (!cam) { | 1150 | if (!cam) { |
1028 | mutex_unlock(&sn9c102_sysfs_lock); | 1151 | mutex_unlock(&sn9c102_sysfs_lock); |
1029 | return -ENODEV; | 1152 | return -ENODEV; |
1030 | } | 1153 | } |
1031 | 1154 | ||
1032 | index = sn9c102_strtou8(buf, len, &count); | 1155 | index = sn9c102_strtou16(buf, len, &count); |
1033 | if (!count) { | 1156 | if (!count) { |
1034 | mutex_unlock(&sn9c102_sysfs_lock); | 1157 | mutex_unlock(&sn9c102_sysfs_lock); |
1035 | return -EINVAL; | 1158 | return -EINVAL; |
@@ -1055,7 +1178,8 @@ static ssize_t sn9c102_show_i2c_val(struct class_device* cd, char* buf) | |||
1055 | if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) | 1178 | if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) |
1056 | return -ERESTARTSYS; | 1179 | return -ERESTARTSYS; |
1057 | 1180 | ||
1058 | cam = video_get_drvdata(to_video_device(cd)); | 1181 | cam = video_get_drvdata(container_of(cd, struct video_device, |
1182 | class_dev)); | ||
1059 | if (!cam) { | 1183 | if (!cam) { |
1060 | mutex_unlock(&sn9c102_sysfs_lock); | 1184 | mutex_unlock(&sn9c102_sysfs_lock); |
1061 | return -ENODEV; | 1185 | return -ENODEV; |
@@ -1085,14 +1209,15 @@ static ssize_t | |||
1085 | sn9c102_store_i2c_val(struct class_device* cd, const char* buf, size_t len) | 1209 | sn9c102_store_i2c_val(struct class_device* cd, const char* buf, size_t len) |
1086 | { | 1210 | { |
1087 | struct sn9c102_device* cam; | 1211 | struct sn9c102_device* cam; |
1088 | u8 value; | 1212 | u16 value; |
1089 | ssize_t count; | 1213 | ssize_t count; |
1090 | int err; | 1214 | int err; |
1091 | 1215 | ||
1092 | if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) | 1216 | if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) |
1093 | return -ERESTARTSYS; | 1217 | return -ERESTARTSYS; |
1094 | 1218 | ||
1095 | cam = video_get_drvdata(to_video_device(cd)); | 1219 | cam = video_get_drvdata(container_of(cd, struct video_device, |
1220 | class_dev)); | ||
1096 | if (!cam) { | 1221 | if (!cam) { |
1097 | mutex_unlock(&sn9c102_sysfs_lock); | 1222 | mutex_unlock(&sn9c102_sysfs_lock); |
1098 | return -ENODEV; | 1223 | return -ENODEV; |
@@ -1103,7 +1228,7 @@ sn9c102_store_i2c_val(struct class_device* cd, const char* buf, size_t len) | |||
1103 | return -ENOSYS; | 1228 | return -ENOSYS; |
1104 | } | 1229 | } |
1105 | 1230 | ||
1106 | value = sn9c102_strtou8(buf, len, &count); | 1231 | value = sn9c102_strtou16(buf, len, &count); |
1107 | if (!count) { | 1232 | if (!count) { |
1108 | mutex_unlock(&sn9c102_sysfs_lock); | 1233 | mutex_unlock(&sn9c102_sysfs_lock); |
1109 | return -EINVAL; | 1234 | return -EINVAL; |
@@ -1131,13 +1256,14 @@ sn9c102_store_green(struct class_device* cd, const char* buf, size_t len) | |||
1131 | struct sn9c102_device* cam; | 1256 | struct sn9c102_device* cam; |
1132 | enum sn9c102_bridge bridge; | 1257 | enum sn9c102_bridge bridge; |
1133 | ssize_t res = 0; | 1258 | ssize_t res = 0; |
1134 | u8 value; | 1259 | u16 value; |
1135 | ssize_t count; | 1260 | ssize_t count; |
1136 | 1261 | ||
1137 | if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) | 1262 | if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) |
1138 | return -ERESTARTSYS; | 1263 | return -ERESTARTSYS; |
1139 | 1264 | ||
1140 | cam = video_get_drvdata(to_video_device(cd)); | 1265 | cam = video_get_drvdata(container_of(cd, struct video_device, |
1266 | class_dev)); | ||
1141 | if (!cam) { | 1267 | if (!cam) { |
1142 | mutex_unlock(&sn9c102_sysfs_lock); | 1268 | mutex_unlock(&sn9c102_sysfs_lock); |
1143 | return -ENODEV; | 1269 | return -ENODEV; |
@@ -1147,7 +1273,7 @@ sn9c102_store_green(struct class_device* cd, const char* buf, size_t len) | |||
1147 | 1273 | ||
1148 | mutex_unlock(&sn9c102_sysfs_lock); | 1274 | mutex_unlock(&sn9c102_sysfs_lock); |
1149 | 1275 | ||
1150 | value = sn9c102_strtou8(buf, len, &count); | 1276 | value = sn9c102_strtou16(buf, len, &count); |
1151 | if (!count) | 1277 | if (!count) |
1152 | return -EINVAL; | 1278 | return -EINVAL; |
1153 | 1279 | ||
@@ -1160,9 +1286,11 @@ sn9c102_store_green(struct class_device* cd, const char* buf, size_t len) | |||
1160 | res = sn9c102_store_val(cd, buf, len); | 1286 | res = sn9c102_store_val(cd, buf, len); |
1161 | break; | 1287 | break; |
1162 | case BRIDGE_SN9C103: | 1288 | case BRIDGE_SN9C103: |
1289 | case BRIDGE_SN9C105: | ||
1290 | case BRIDGE_SN9C120: | ||
1163 | if (value > 0x7f) | 1291 | if (value > 0x7f) |
1164 | return -EINVAL; | 1292 | return -EINVAL; |
1165 | if ((res = sn9c102_store_reg(cd, "0x04", 4)) >= 0) | 1293 | if ((res = sn9c102_store_reg(cd, "0x07", 4)) >= 0) |
1166 | res = sn9c102_store_val(cd, buf, len); | 1294 | res = sn9c102_store_val(cd, buf, len); |
1167 | break; | 1295 | break; |
1168 | } | 1296 | } |
@@ -1175,10 +1303,10 @@ static ssize_t | |||
1175 | sn9c102_store_blue(struct class_device* cd, const char* buf, size_t len) | 1303 | sn9c102_store_blue(struct class_device* cd, const char* buf, size_t len) |
1176 | { | 1304 | { |
1177 | ssize_t res = 0; | 1305 | ssize_t res = 0; |
1178 | u8 value; | 1306 | u16 value; |
1179 | ssize_t count; | 1307 | ssize_t count; |
1180 | 1308 | ||
1181 | value = sn9c102_strtou8(buf, len, &count); | 1309 | value = sn9c102_strtou16(buf, len, &count); |
1182 | if (!count || value > 0x7f) | 1310 | if (!count || value > 0x7f) |
1183 | return -EINVAL; | 1311 | return -EINVAL; |
1184 | 1312 | ||
@@ -1193,10 +1321,10 @@ static ssize_t | |||
1193 | sn9c102_store_red(struct class_device* cd, const char* buf, size_t len) | 1321 | sn9c102_store_red(struct class_device* cd, const char* buf, size_t len) |
1194 | { | 1322 | { |
1195 | ssize_t res = 0; | 1323 | ssize_t res = 0; |
1196 | u8 value; | 1324 | u16 value; |
1197 | ssize_t count; | 1325 | ssize_t count; |
1198 | 1326 | ||
1199 | value = sn9c102_strtou8(buf, len, &count); | 1327 | value = sn9c102_strtou16(buf, len, &count); |
1200 | if (!count || value > 0x7f) | 1328 | if (!count || value > 0x7f) |
1201 | return -EINVAL; | 1329 | return -EINVAL; |
1202 | 1330 | ||
@@ -1212,7 +1340,8 @@ static ssize_t sn9c102_show_frame_header(struct class_device* cd, char* buf) | |||
1212 | struct sn9c102_device* cam; | 1340 | struct sn9c102_device* cam; |
1213 | ssize_t count; | 1341 | ssize_t count; |
1214 | 1342 | ||
1215 | cam = video_get_drvdata(to_video_device(cd)); | 1343 | cam = video_get_drvdata(container_of(cd, struct video_device, |
1344 | class_dev)); | ||
1216 | if (!cam) | 1345 | if (!cam) |
1217 | return -ENODEV; | 1346 | return -ENODEV; |
1218 | 1347 | ||
@@ -1243,30 +1372,36 @@ static CLASS_DEVICE_ATTR(frame_header, S_IRUGO, | |||
1243 | static int sn9c102_create_sysfs(struct sn9c102_device* cam) | 1372 | static int sn9c102_create_sysfs(struct sn9c102_device* cam) |
1244 | { | 1373 | { |
1245 | struct video_device *v4ldev = cam->v4ldev; | 1374 | struct video_device *v4ldev = cam->v4ldev; |
1246 | int rc; | 1375 | int err = 0; |
1247 | 1376 | ||
1248 | rc = video_device_create_file(v4ldev, &class_device_attr_reg); | 1377 | if ((err = video_device_create_file(v4ldev, &class_device_attr_reg))) |
1249 | if (rc) goto err; | 1378 | goto err_out; |
1250 | rc = video_device_create_file(v4ldev, &class_device_attr_val); | 1379 | if ((err = video_device_create_file(v4ldev, &class_device_attr_val))) |
1251 | if (rc) goto err_reg; | 1380 | goto err_reg; |
1252 | rc = video_device_create_file(v4ldev, &class_device_attr_frame_header); | 1381 | if ((err = video_device_create_file(v4ldev, |
1253 | if (rc) goto err_val; | 1382 | &class_device_attr_frame_header))) |
1383 | goto err_val; | ||
1254 | 1384 | ||
1255 | if (cam->sensor.sysfs_ops) { | 1385 | if (cam->sensor.sysfs_ops) { |
1256 | rc = video_device_create_file(v4ldev, &class_device_attr_i2c_reg); | 1386 | if ((err = video_device_create_file(v4ldev, |
1257 | if (rc) goto err_frhead; | 1387 | &class_device_attr_i2c_reg))) |
1258 | rc = video_device_create_file(v4ldev, &class_device_attr_i2c_val); | 1388 | goto err_frame_header; |
1259 | if (rc) goto err_i2c_reg; | 1389 | if ((err = video_device_create_file(v4ldev, |
1390 | &class_device_attr_i2c_val))) | ||
1391 | goto err_i2c_reg; | ||
1260 | } | 1392 | } |
1261 | 1393 | ||
1262 | if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102) { | 1394 | if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102) { |
1263 | rc = video_device_create_file(v4ldev, &class_device_attr_green); | 1395 | if ((err = video_device_create_file(v4ldev, |
1264 | if (rc) goto err_i2c_val; | 1396 | &class_device_attr_green))) |
1265 | } else if (cam->bridge == BRIDGE_SN9C103) { | 1397 | goto err_i2c_val; |
1266 | rc = video_device_create_file(v4ldev, &class_device_attr_blue); | 1398 | } else { |
1267 | if (rc) goto err_i2c_val; | 1399 | if ((err = video_device_create_file(v4ldev, |
1268 | rc = video_device_create_file(v4ldev, &class_device_attr_red); | 1400 | &class_device_attr_blue))) |
1269 | if (rc) goto err_blue; | 1401 | goto err_i2c_val; |
1402 | if ((err = video_device_create_file(v4ldev, | ||
1403 | &class_device_attr_red))) | ||
1404 | goto err_blue; | ||
1270 | } | 1405 | } |
1271 | 1406 | ||
1272 | return 0; | 1407 | return 0; |
@@ -1279,14 +1414,14 @@ err_i2c_val: | |||
1279 | err_i2c_reg: | 1414 | err_i2c_reg: |
1280 | if (cam->sensor.sysfs_ops) | 1415 | if (cam->sensor.sysfs_ops) |
1281 | video_device_remove_file(v4ldev, &class_device_attr_i2c_reg); | 1416 | video_device_remove_file(v4ldev, &class_device_attr_i2c_reg); |
1282 | err_frhead: | 1417 | err_frame_header: |
1283 | video_device_remove_file(v4ldev, &class_device_attr_frame_header); | 1418 | video_device_remove_file(v4ldev, &class_device_attr_frame_header); |
1284 | err_val: | 1419 | err_val: |
1285 | video_device_remove_file(v4ldev, &class_device_attr_val); | 1420 | video_device_remove_file(v4ldev, &class_device_attr_val); |
1286 | err_reg: | 1421 | err_reg: |
1287 | video_device_remove_file(v4ldev, &class_device_attr_reg); | 1422 | video_device_remove_file(v4ldev, &class_device_attr_reg); |
1288 | err: | 1423 | err_out: |
1289 | return rc; | 1424 | return err; |
1290 | } | 1425 | } |
1291 | #endif /* CONFIG_VIDEO_ADV_DEBUG */ | 1426 | #endif /* CONFIG_VIDEO_ADV_DEBUG */ |
1292 | 1427 | ||
@@ -1297,10 +1432,36 @@ sn9c102_set_pix_format(struct sn9c102_device* cam, struct v4l2_pix_format* pix) | |||
1297 | { | 1432 | { |
1298 | int err = 0; | 1433 | int err = 0; |
1299 | 1434 | ||
1300 | if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) | 1435 | if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X || |
1301 | err += sn9c102_write_reg(cam, cam->reg[0x18] | 0x80, 0x18); | 1436 | pix->pixelformat == V4L2_PIX_FMT_JPEG) { |
1302 | else | 1437 | switch (cam->bridge) { |
1303 | err += sn9c102_write_reg(cam, cam->reg[0x18] & 0x7f, 0x18); | 1438 | case BRIDGE_SN9C101: |
1439 | case BRIDGE_SN9C102: | ||
1440 | case BRIDGE_SN9C103: | ||
1441 | err += sn9c102_write_reg(cam, cam->reg[0x18] | 0x80, | ||
1442 | 0x18); | ||
1443 | break; | ||
1444 | case BRIDGE_SN9C105: | ||
1445 | case BRIDGE_SN9C120: | ||
1446 | err += sn9c102_write_reg(cam, cam->reg[0x18] & 0x7f, | ||
1447 | 0x18); | ||
1448 | break; | ||
1449 | } | ||
1450 | } else { | ||
1451 | switch (cam->bridge) { | ||
1452 | case BRIDGE_SN9C101: | ||
1453 | case BRIDGE_SN9C102: | ||
1454 | case BRIDGE_SN9C103: | ||
1455 | err += sn9c102_write_reg(cam, cam->reg[0x18] & 0x7f, | ||
1456 | 0x18); | ||
1457 | break; | ||
1458 | case BRIDGE_SN9C105: | ||
1459 | case BRIDGE_SN9C120: | ||
1460 | err += sn9c102_write_reg(cam, cam->reg[0x18] | 0x80, | ||
1461 | 0x18); | ||
1462 | break; | ||
1463 | } | ||
1464 | } | ||
1304 | 1465 | ||
1305 | return err ? -EIO : 0; | 1466 | return err ? -EIO : 0; |
1306 | } | 1467 | } |
@@ -1310,12 +1471,46 @@ static int | |||
1310 | sn9c102_set_compression(struct sn9c102_device* cam, | 1471 | sn9c102_set_compression(struct sn9c102_device* cam, |
1311 | struct v4l2_jpegcompression* compression) | 1472 | struct v4l2_jpegcompression* compression) |
1312 | { | 1473 | { |
1313 | int err = 0; | 1474 | int i, err = 0; |
1314 | 1475 | ||
1476 | switch (cam->bridge) { | ||
1477 | case BRIDGE_SN9C101: | ||
1478 | case BRIDGE_SN9C102: | ||
1479 | case BRIDGE_SN9C103: | ||
1315 | if (compression->quality == 0) | 1480 | if (compression->quality == 0) |
1316 | err += sn9c102_write_reg(cam, cam->reg[0x17] | 0x01, 0x17); | 1481 | err += sn9c102_write_reg(cam, cam->reg[0x17] | 0x01, |
1482 | 0x17); | ||
1317 | else if (compression->quality == 1) | 1483 | else if (compression->quality == 1) |
1318 | err += sn9c102_write_reg(cam, cam->reg[0x17] & 0xfe, 0x17); | 1484 | err += sn9c102_write_reg(cam, cam->reg[0x17] & 0xfe, |
1485 | 0x17); | ||
1486 | break; | ||
1487 | case BRIDGE_SN9C105: | ||
1488 | case BRIDGE_SN9C120: | ||
1489 | if (compression->quality == 0) { | ||
1490 | for (i = 0; i <= 63; i++) { | ||
1491 | err += sn9c102_write_reg(cam, | ||
1492 | SN9C102_Y_QTABLE0[i], | ||
1493 | 0x100 + i); | ||
1494 | err += sn9c102_write_reg(cam, | ||
1495 | SN9C102_UV_QTABLE0[i], | ||
1496 | 0x140 + i); | ||
1497 | } | ||
1498 | err += sn9c102_write_reg(cam, cam->reg[0x18] & 0xbf, | ||
1499 | 0x18); | ||
1500 | } else if (compression->quality == 1) { | ||
1501 | for (i = 0; i <= 63; i++) { | ||
1502 | err += sn9c102_write_reg(cam, | ||
1503 | SN9C102_Y_QTABLE1[i], | ||
1504 | 0x100 + i); | ||
1505 | err += sn9c102_write_reg(cam, | ||
1506 | SN9C102_UV_QTABLE1[i], | ||
1507 | 0x140 + i); | ||
1508 | } | ||
1509 | err += sn9c102_write_reg(cam, cam->reg[0x18] | 0x40, | ||
1510 | 0x18); | ||
1511 | } | ||
1512 | break; | ||
1513 | } | ||
1319 | 1514 | ||
1320 | return err ? -EIO : 0; | 1515 | return err ? -EIO : 0; |
1321 | } | 1516 | } |
@@ -1399,7 +1594,16 @@ static int sn9c102_init(struct sn9c102_device* cam) | |||
1399 | } | 1594 | } |
1400 | 1595 | ||
1401 | if (!(cam->state & DEV_INITIALIZED)) | 1596 | if (!(cam->state & DEV_INITIALIZED)) |
1402 | cam->compression.quality = cam->reg[0x17] & 0x01 ? 0 : 1; | 1597 | if (cam->bridge == BRIDGE_SN9C101 || |
1598 | cam->bridge == BRIDGE_SN9C102 || | ||
1599 | cam->bridge == BRIDGE_SN9C103) { | ||
1600 | cam->compression.quality = cam->reg[0x17] & 0x01 ? | ||
1601 | 0 : 1; | ||
1602 | } else { | ||
1603 | cam->compression.quality = cam->reg[0x18] & 0x40 ? | ||
1604 | 0 : 1; | ||
1605 | err += sn9c102_set_compression(cam, &cam->compression); | ||
1606 | } | ||
1403 | else | 1607 | else |
1404 | err += sn9c102_set_compression(cam, &cam->compression); | 1608 | err += sn9c102_set_compression(cam, &cam->compression); |
1405 | err += sn9c102_set_pix_format(cam, &s->pix_format); | 1609 | err += sn9c102_set_pix_format(cam, &s->pix_format); |
@@ -1408,7 +1612,8 @@ static int sn9c102_init(struct sn9c102_device* cam) | |||
1408 | if (err) | 1612 | if (err) |
1409 | return err; | 1613 | return err; |
1410 | 1614 | ||
1411 | if (s->pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X) | 1615 | if (s->pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X || |
1616 | s->pix_format.pixelformat == V4L2_PIX_FMT_JPEG) | ||
1412 | DBG(3, "Compressed video format is active, quality %d", | 1617 | DBG(3, "Compressed video format is active, quality %d", |
1413 | cam->compression.quality); | 1618 | cam->compression.quality); |
1414 | else | 1619 | else |
@@ -1490,6 +1695,7 @@ static int sn9c102_open(struct inode* inode, struct file* filp) | |||
1490 | 1695 | ||
1491 | if (cam->users) { | 1696 | if (cam->users) { |
1492 | DBG(2, "Device /dev/video%d is busy...", cam->v4ldev->minor); | 1697 | DBG(2, "Device /dev/video%d is busy...", cam->v4ldev->minor); |
1698 | DBG(3, "Simultaneous opens are not supported"); | ||
1493 | if ((filp->f_flags & O_NONBLOCK) || | 1699 | if ((filp->f_flags & O_NONBLOCK) || |
1494 | (filp->f_flags & O_NDELAY)) { | 1700 | (filp->f_flags & O_NDELAY)) { |
1495 | err = -EWOULDBLOCK; | 1701 | err = -EWOULDBLOCK; |
@@ -1628,6 +1834,17 @@ sn9c102_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos) | |||
1628 | mutex_unlock(&cam->fileop_mutex); | 1834 | mutex_unlock(&cam->fileop_mutex); |
1629 | return -EAGAIN; | 1835 | return -EAGAIN; |
1630 | } | 1836 | } |
1837 | if (!cam->module_param.frame_timeout) { | ||
1838 | err = wait_event_interruptible | ||
1839 | ( cam->wait_frame, | ||
1840 | (!list_empty(&cam->outqueue)) || | ||
1841 | (cam->state & DEV_DISCONNECTED) || | ||
1842 | (cam->state & DEV_MISCONFIGURED) ); | ||
1843 | if (err) { | ||
1844 | mutex_unlock(&cam->fileop_mutex); | ||
1845 | return err; | ||
1846 | } | ||
1847 | } else { | ||
1631 | timeout = wait_event_interruptible_timeout | 1848 | timeout = wait_event_interruptible_timeout |
1632 | ( cam->wait_frame, | 1849 | ( cam->wait_frame, |
1633 | (!list_empty(&cam->outqueue)) || | 1850 | (!list_empty(&cam->outqueue)) || |
@@ -1638,12 +1855,18 @@ sn9c102_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos) | |||
1638 | if (timeout < 0) { | 1855 | if (timeout < 0) { |
1639 | mutex_unlock(&cam->fileop_mutex); | 1856 | mutex_unlock(&cam->fileop_mutex); |
1640 | return timeout; | 1857 | return timeout; |
1858 | } else if (timeout == 0 && | ||
1859 | !(cam->state & DEV_DISCONNECTED)) { | ||
1860 | DBG(1, "Video frame timeout elapsed"); | ||
1861 | mutex_unlock(&cam->fileop_mutex); | ||
1862 | return -EIO; | ||
1863 | } | ||
1641 | } | 1864 | } |
1642 | if (cam->state & DEV_DISCONNECTED) { | 1865 | if (cam->state & DEV_DISCONNECTED) { |
1643 | mutex_unlock(&cam->fileop_mutex); | 1866 | mutex_unlock(&cam->fileop_mutex); |
1644 | return -ENODEV; | 1867 | return -ENODEV; |
1645 | } | 1868 | } |
1646 | if (!timeout || (cam->state & DEV_MISCONFIGURED)) { | 1869 | if (cam->state & DEV_MISCONFIGURED) { |
1647 | mutex_unlock(&cam->fileop_mutex); | 1870 | mutex_unlock(&cam->fileop_mutex); |
1648 | return -EIO; | 1871 | return -EIO; |
1649 | } | 1872 | } |
@@ -1940,6 +2163,9 @@ exit: | |||
1940 | if (copy_to_user(arg, &ctrl, sizeof(ctrl))) | 2163 | if (copy_to_user(arg, &ctrl, sizeof(ctrl))) |
1941 | return -EFAULT; | 2164 | return -EFAULT; |
1942 | 2165 | ||
2166 | PDBGG("VIDIOC_G_CTRL: id %lu, value %lu", | ||
2167 | (unsigned long)ctrl.id, (unsigned long)ctrl.value); | ||
2168 | |||
1943 | return err; | 2169 | return err; |
1944 | } | 2170 | } |
1945 | 2171 | ||
@@ -2127,6 +2353,45 @@ sn9c102_vidioc_s_crop(struct sn9c102_device* cam, void __user * arg) | |||
2127 | 2353 | ||
2128 | 2354 | ||
2129 | static int | 2355 | static int |
2356 | sn9c102_vidioc_enum_framesizes(struct sn9c102_device* cam, void __user * arg) | ||
2357 | { | ||
2358 | struct v4l2_frmsizeenum frmsize; | ||
2359 | |||
2360 | if (copy_from_user(&frmsize, arg, sizeof(frmsize))) | ||
2361 | return -EFAULT; | ||
2362 | |||
2363 | if (frmsize.index != 0) | ||
2364 | return -EINVAL; | ||
2365 | |||
2366 | switch (cam->bridge) { | ||
2367 | case BRIDGE_SN9C101: | ||
2368 | case BRIDGE_SN9C102: | ||
2369 | case BRIDGE_SN9C103: | ||
2370 | if (frmsize.pixel_format != V4L2_PIX_FMT_SN9C10X && | ||
2371 | frmsize.pixel_format != V4L2_PIX_FMT_SBGGR8) | ||
2372 | return -EINVAL; | ||
2373 | case BRIDGE_SN9C105: | ||
2374 | case BRIDGE_SN9C120: | ||
2375 | if (frmsize.pixel_format != V4L2_PIX_FMT_JPEG && | ||
2376 | frmsize.pixel_format != V4L2_PIX_FMT_SBGGR8) | ||
2377 | return -EINVAL; | ||
2378 | } | ||
2379 | |||
2380 | frmsize.type = V4L2_FRMSIZE_TYPE_STEPWISE; | ||
2381 | frmsize.stepwise.min_width = frmsize.stepwise.step_width = 16; | ||
2382 | frmsize.stepwise.min_height = frmsize.stepwise.step_height = 16; | ||
2383 | frmsize.stepwise.max_width = cam->sensor.cropcap.bounds.width; | ||
2384 | frmsize.stepwise.max_height = cam->sensor.cropcap.bounds.height; | ||
2385 | memset(&frmsize.reserved, 0, sizeof(frmsize.reserved)); | ||
2386 | |||
2387 | if (copy_to_user(arg, &frmsize, sizeof(frmsize))) | ||
2388 | return -EFAULT; | ||
2389 | |||
2390 | return 0; | ||
2391 | } | ||
2392 | |||
2393 | |||
2394 | static int | ||
2130 | sn9c102_vidioc_enum_fmt(struct sn9c102_device* cam, void __user * arg) | 2395 | sn9c102_vidioc_enum_fmt(struct sn9c102_device* cam, void __user * arg) |
2131 | { | 2396 | { |
2132 | struct v4l2_fmtdesc fmtd; | 2397 | struct v4l2_fmtdesc fmtd; |
@@ -2134,12 +2399,26 @@ sn9c102_vidioc_enum_fmt(struct sn9c102_device* cam, void __user * arg) | |||
2134 | if (copy_from_user(&fmtd, arg, sizeof(fmtd))) | 2399 | if (copy_from_user(&fmtd, arg, sizeof(fmtd))) |
2135 | return -EFAULT; | 2400 | return -EFAULT; |
2136 | 2401 | ||
2402 | if (fmtd.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
2403 | return -EINVAL; | ||
2404 | |||
2137 | if (fmtd.index == 0) { | 2405 | if (fmtd.index == 0) { |
2138 | strcpy(fmtd.description, "bayer rgb"); | 2406 | strcpy(fmtd.description, "bayer rgb"); |
2139 | fmtd.pixelformat = V4L2_PIX_FMT_SBGGR8; | 2407 | fmtd.pixelformat = V4L2_PIX_FMT_SBGGR8; |
2140 | } else if (fmtd.index == 1) { | 2408 | } else if (fmtd.index == 1) { |
2409 | switch (cam->bridge) { | ||
2410 | case BRIDGE_SN9C101: | ||
2411 | case BRIDGE_SN9C102: | ||
2412 | case BRIDGE_SN9C103: | ||
2141 | strcpy(fmtd.description, "compressed"); | 2413 | strcpy(fmtd.description, "compressed"); |
2142 | fmtd.pixelformat = V4L2_PIX_FMT_SN9C10X; | 2414 | fmtd.pixelformat = V4L2_PIX_FMT_SN9C10X; |
2415 | break; | ||
2416 | case BRIDGE_SN9C105: | ||
2417 | case BRIDGE_SN9C120: | ||
2418 | strcpy(fmtd.description, "JPEG"); | ||
2419 | fmtd.pixelformat = V4L2_PIX_FMT_JPEG; | ||
2420 | break; | ||
2421 | } | ||
2143 | fmtd.flags = V4L2_FMT_FLAG_COMPRESSED; | 2422 | fmtd.flags = V4L2_FMT_FLAG_COMPRESSED; |
2144 | } else | 2423 | } else |
2145 | return -EINVAL; | 2424 | return -EINVAL; |
@@ -2166,7 +2445,8 @@ sn9c102_vidioc_g_fmt(struct sn9c102_device* cam, void __user * arg) | |||
2166 | if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | 2445 | if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
2167 | return -EINVAL; | 2446 | return -EINVAL; |
2168 | 2447 | ||
2169 | pfmt->bytesperline = (pfmt->pixelformat==V4L2_PIX_FMT_SN9C10X) | 2448 | pfmt->bytesperline = (pfmt->pixelformat==V4L2_PIX_FMT_SN9C10X || |
2449 | pfmt->pixelformat==V4L2_PIX_FMT_JPEG) | ||
2170 | ? 0 : (pfmt->width * pfmt->priv) / 8; | 2450 | ? 0 : (pfmt->width * pfmt->priv) / 8; |
2171 | pfmt->sizeimage = pfmt->height * ((pfmt->width*pfmt->priv)/8); | 2451 | pfmt->sizeimage = pfmt->height * ((pfmt->width*pfmt->priv)/8); |
2172 | pfmt->field = V4L2_FIELD_NONE; | 2452 | pfmt->field = V4L2_FIELD_NONE; |
@@ -2237,12 +2517,25 @@ sn9c102_vidioc_try_s_fmt(struct sn9c102_device* cam, unsigned int cmd, | |||
2237 | pix->width = rect.width / scale; | 2517 | pix->width = rect.width / scale; |
2238 | pix->height = rect.height / scale; | 2518 | pix->height = rect.height / scale; |
2239 | 2519 | ||
2520 | switch (cam->bridge) { | ||
2521 | case BRIDGE_SN9C101: | ||
2522 | case BRIDGE_SN9C102: | ||
2523 | case BRIDGE_SN9C103: | ||
2240 | if (pix->pixelformat != V4L2_PIX_FMT_SN9C10X && | 2524 | if (pix->pixelformat != V4L2_PIX_FMT_SN9C10X && |
2241 | pix->pixelformat != V4L2_PIX_FMT_SBGGR8) | 2525 | pix->pixelformat != V4L2_PIX_FMT_SBGGR8) |
2242 | pix->pixelformat = pfmt->pixelformat; | 2526 | pix->pixelformat = pfmt->pixelformat; |
2527 | break; | ||
2528 | case BRIDGE_SN9C105: | ||
2529 | case BRIDGE_SN9C120: | ||
2530 | if (pix->pixelformat != V4L2_PIX_FMT_JPEG && | ||
2531 | pix->pixelformat != V4L2_PIX_FMT_SBGGR8) | ||
2532 | pix->pixelformat = pfmt->pixelformat; | ||
2533 | break; | ||
2534 | } | ||
2243 | pix->priv = pfmt->priv; /* bpp */ | 2535 | pix->priv = pfmt->priv; /* bpp */ |
2244 | pix->colorspace = pfmt->colorspace; | 2536 | pix->colorspace = pfmt->colorspace; |
2245 | pix->bytesperline = (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) | 2537 | pix->bytesperline = (pix->pixelformat == V4L2_PIX_FMT_SN9C10X || |
2538 | pix->pixelformat == V4L2_PIX_FMT_JPEG) | ||
2246 | ? 0 : (pix->width * pix->priv) / 8; | 2539 | ? 0 : (pix->width * pix->priv) / 8; |
2247 | pix->sizeimage = pix->height * ((pix->width * pix->priv) / 8); | 2540 | pix->sizeimage = pix->height * ((pix->width * pix->priv) / 8); |
2248 | pix->field = V4L2_FIELD_NONE; | 2541 | pix->field = V4L2_FIELD_NONE; |
@@ -2315,8 +2608,7 @@ sn9c102_vidioc_try_s_fmt(struct sn9c102_device* cam, unsigned int cmd, | |||
2315 | static int | 2608 | static int |
2316 | sn9c102_vidioc_g_jpegcomp(struct sn9c102_device* cam, void __user * arg) | 2609 | sn9c102_vidioc_g_jpegcomp(struct sn9c102_device* cam, void __user * arg) |
2317 | { | 2610 | { |
2318 | if (copy_to_user(arg, &cam->compression, | 2611 | if (copy_to_user(arg, &cam->compression, sizeof(cam->compression))) |
2319 | sizeof(cam->compression))) | ||
2320 | return -EFAULT; | 2612 | return -EFAULT; |
2321 | 2613 | ||
2322 | return 0; | 2614 | return 0; |
@@ -2471,6 +2763,7 @@ sn9c102_vidioc_dqbuf(struct sn9c102_device* cam, struct file* filp, | |||
2471 | struct sn9c102_frame_t *f; | 2763 | struct sn9c102_frame_t *f; |
2472 | unsigned long lock_flags; | 2764 | unsigned long lock_flags; |
2473 | long timeout; | 2765 | long timeout; |
2766 | int err = 0; | ||
2474 | 2767 | ||
2475 | if (copy_from_user(&b, arg, sizeof(b))) | 2768 | if (copy_from_user(&b, arg, sizeof(b))) |
2476 | return -EFAULT; | 2769 | return -EFAULT; |
@@ -2483,6 +2776,15 @@ sn9c102_vidioc_dqbuf(struct sn9c102_device* cam, struct file* filp, | |||
2483 | return -EINVAL; | 2776 | return -EINVAL; |
2484 | if (filp->f_flags & O_NONBLOCK) | 2777 | if (filp->f_flags & O_NONBLOCK) |
2485 | return -EAGAIN; | 2778 | return -EAGAIN; |
2779 | if (!cam->module_param.frame_timeout) { | ||
2780 | err = wait_event_interruptible | ||
2781 | ( cam->wait_frame, | ||
2782 | (!list_empty(&cam->outqueue)) || | ||
2783 | (cam->state & DEV_DISCONNECTED) || | ||
2784 | (cam->state & DEV_MISCONFIGURED) ); | ||
2785 | if (err) | ||
2786 | return err; | ||
2787 | } else { | ||
2486 | timeout = wait_event_interruptible_timeout | 2788 | timeout = wait_event_interruptible_timeout |
2487 | ( cam->wait_frame, | 2789 | ( cam->wait_frame, |
2488 | (!list_empty(&cam->outqueue)) || | 2790 | (!list_empty(&cam->outqueue)) || |
@@ -2492,9 +2794,15 @@ sn9c102_vidioc_dqbuf(struct sn9c102_device* cam, struct file* filp, | |||
2492 | 1000 * msecs_to_jiffies(1) ); | 2794 | 1000 * msecs_to_jiffies(1) ); |
2493 | if (timeout < 0) | 2795 | if (timeout < 0) |
2494 | return timeout; | 2796 | return timeout; |
2797 | else if (timeout == 0 && | ||
2798 | !(cam->state & DEV_DISCONNECTED)) { | ||
2799 | DBG(1, "Video frame timeout elapsed"); | ||
2800 | return -EIO; | ||
2801 | } | ||
2802 | } | ||
2495 | if (cam->state & DEV_DISCONNECTED) | 2803 | if (cam->state & DEV_DISCONNECTED) |
2496 | return -ENODEV; | 2804 | return -ENODEV; |
2497 | if (!timeout || (cam->state & DEV_MISCONFIGURED)) | 2805 | if (cam->state & DEV_MISCONFIGURED) |
2498 | return -EIO; | 2806 | return -EIO; |
2499 | } | 2807 | } |
2500 | 2808 | ||
@@ -2612,6 +2920,70 @@ sn9c102_vidioc_s_parm(struct sn9c102_device* cam, void __user * arg) | |||
2612 | } | 2920 | } |
2613 | 2921 | ||
2614 | 2922 | ||
2923 | static int | ||
2924 | sn9c102_vidioc_enumaudio(struct sn9c102_device* cam, void __user * arg) | ||
2925 | { | ||
2926 | struct v4l2_audio audio; | ||
2927 | |||
2928 | if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102) | ||
2929 | return -EINVAL; | ||
2930 | |||
2931 | if (copy_from_user(&audio, arg, sizeof(audio))) | ||
2932 | return -EFAULT; | ||
2933 | |||
2934 | if (audio.index != 0) | ||
2935 | return -EINVAL; | ||
2936 | |||
2937 | strcpy(audio.name, "Microphone"); | ||
2938 | audio.capability = 0; | ||
2939 | audio.mode = 0; | ||
2940 | |||
2941 | if (copy_to_user(arg, &audio, sizeof(audio))) | ||
2942 | return -EFAULT; | ||
2943 | |||
2944 | return 0; | ||
2945 | } | ||
2946 | |||
2947 | |||
2948 | static int | ||
2949 | sn9c102_vidioc_g_audio(struct sn9c102_device* cam, void __user * arg) | ||
2950 | { | ||
2951 | struct v4l2_audio audio; | ||
2952 | |||
2953 | if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102) | ||
2954 | return -EINVAL; | ||
2955 | |||
2956 | if (copy_from_user(&audio, arg, sizeof(audio))) | ||
2957 | return -EFAULT; | ||
2958 | |||
2959 | memset(&audio, 0, sizeof(audio)); | ||
2960 | strcpy(audio.name, "Microphone"); | ||
2961 | |||
2962 | if (copy_to_user(arg, &audio, sizeof(audio))) | ||
2963 | return -EFAULT; | ||
2964 | |||
2965 | return 0; | ||
2966 | } | ||
2967 | |||
2968 | |||
2969 | static int | ||
2970 | sn9c102_vidioc_s_audio(struct sn9c102_device* cam, void __user * arg) | ||
2971 | { | ||
2972 | struct v4l2_audio audio; | ||
2973 | |||
2974 | if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102) | ||
2975 | return -EINVAL; | ||
2976 | |||
2977 | if (copy_from_user(&audio, arg, sizeof(audio))) | ||
2978 | return -EFAULT; | ||
2979 | |||
2980 | if (audio.index != 0) | ||
2981 | return -EINVAL; | ||
2982 | |||
2983 | return 0; | ||
2984 | } | ||
2985 | |||
2986 | |||
2615 | static int sn9c102_ioctl_v4l2(struct inode* inode, struct file* filp, | 2987 | static int sn9c102_ioctl_v4l2(struct inode* inode, struct file* filp, |
2616 | unsigned int cmd, void __user * arg) | 2988 | unsigned int cmd, void __user * arg) |
2617 | { | 2989 | { |
@@ -2649,6 +3021,9 @@ static int sn9c102_ioctl_v4l2(struct inode* inode, struct file* filp, | |||
2649 | case VIDIOC_S_CROP: | 3021 | case VIDIOC_S_CROP: |
2650 | return sn9c102_vidioc_s_crop(cam, arg); | 3022 | return sn9c102_vidioc_s_crop(cam, arg); |
2651 | 3023 | ||
3024 | case VIDIOC_ENUM_FRAMESIZES: | ||
3025 | return sn9c102_vidioc_enum_framesizes(cam, arg); | ||
3026 | |||
2652 | case VIDIOC_ENUM_FMT: | 3027 | case VIDIOC_ENUM_FMT: |
2653 | return sn9c102_vidioc_enum_fmt(cam, arg); | 3028 | return sn9c102_vidioc_enum_fmt(cam, arg); |
2654 | 3029 | ||
@@ -2689,11 +3064,21 @@ static int sn9c102_ioctl_v4l2(struct inode* inode, struct file* filp, | |||
2689 | case VIDIOC_S_PARM: | 3064 | case VIDIOC_S_PARM: |
2690 | return sn9c102_vidioc_s_parm(cam, arg); | 3065 | return sn9c102_vidioc_s_parm(cam, arg); |
2691 | 3066 | ||
3067 | case VIDIOC_ENUMAUDIO: | ||
3068 | return sn9c102_vidioc_enumaudio(cam, arg); | ||
3069 | |||
3070 | case VIDIOC_G_AUDIO: | ||
3071 | return sn9c102_vidioc_g_audio(cam, arg); | ||
3072 | |||
3073 | case VIDIOC_S_AUDIO: | ||
3074 | return sn9c102_vidioc_s_audio(cam, arg); | ||
3075 | |||
2692 | case VIDIOC_G_STD: | 3076 | case VIDIOC_G_STD: |
2693 | case VIDIOC_S_STD: | 3077 | case VIDIOC_S_STD: |
2694 | case VIDIOC_QUERYSTD: | 3078 | case VIDIOC_QUERYSTD: |
2695 | case VIDIOC_ENUMSTD: | 3079 | case VIDIOC_ENUMSTD: |
2696 | case VIDIOC_QUERYMENU: | 3080 | case VIDIOC_QUERYMENU: |
3081 | case VIDIOC_ENUM_FRAMEINTERVALS: | ||
2697 | return -EINVAL; | 3082 | return -EINVAL; |
2698 | 3083 | ||
2699 | default: | 3084 | default: |
@@ -2741,6 +3126,7 @@ static const struct file_operations sn9c102_fops = { | |||
2741 | .open = sn9c102_open, | 3126 | .open = sn9c102_open, |
2742 | .release = sn9c102_release, | 3127 | .release = sn9c102_release, |
2743 | .ioctl = sn9c102_ioctl, | 3128 | .ioctl = sn9c102_ioctl, |
3129 | .compat_ioctl = v4l_compat_ioctl32, | ||
2744 | .read = sn9c102_read, | 3130 | .read = sn9c102_read, |
2745 | .poll = sn9c102_poll, | 3131 | .poll = sn9c102_poll, |
2746 | .mmap = sn9c102_mmap, | 3132 | .mmap = sn9c102_mmap, |
@@ -2765,7 +3151,7 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) | |||
2765 | cam->usbdev = udev; | 3151 | cam->usbdev = udev; |
2766 | 3152 | ||
2767 | if (!(cam->control_buffer = kzalloc(8, GFP_KERNEL))) { | 3153 | if (!(cam->control_buffer = kzalloc(8, GFP_KERNEL))) { |
2768 | DBG(1, "kmalloc() failed"); | 3154 | DBG(1, "kzalloc() failed"); |
2769 | err = -ENOMEM; | 3155 | err = -ENOMEM; |
2770 | goto fail; | 3156 | goto fail; |
2771 | } | 3157 | } |
@@ -2779,24 +3165,31 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) | |||
2779 | mutex_init(&cam->dev_mutex); | 3165 | mutex_init(&cam->dev_mutex); |
2780 | 3166 | ||
2781 | r = sn9c102_read_reg(cam, 0x00); | 3167 | r = sn9c102_read_reg(cam, 0x00); |
2782 | if (r < 0 || r != 0x10) { | 3168 | if (r < 0 || (r != 0x10 && r != 0x11 && r != 0x12)) { |
2783 | DBG(1, "Sorry, this is not a SN9C10x based camera " | 3169 | DBG(1, "Sorry, this is not a SN9C1xx based camera " |
2784 | "(vid/pid 0x%04X/0x%04X)", id->idVendor, id->idProduct); | 3170 | "(vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct); |
2785 | err = -ENODEV; | 3171 | err = -ENODEV; |
2786 | goto fail; | 3172 | goto fail; |
2787 | } | 3173 | } |
2788 | 3174 | ||
2789 | cam->bridge = (id->idProduct & 0xffc0) == 0x6080 ? | 3175 | cam->bridge = id->driver_info; |
2790 | BRIDGE_SN9C103 : BRIDGE_SN9C102; | ||
2791 | switch (cam->bridge) { | 3176 | switch (cam->bridge) { |
2792 | case BRIDGE_SN9C101: | 3177 | case BRIDGE_SN9C101: |
2793 | case BRIDGE_SN9C102: | 3178 | case BRIDGE_SN9C102: |
2794 | DBG(2, "SN9C10[12] PC Camera Controller detected " | 3179 | DBG(2, "SN9C10[12] PC Camera Controller detected " |
2795 | "(vid/pid 0x%04X/0x%04X)", id->idVendor, id->idProduct); | 3180 | "(vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct); |
2796 | break; | 3181 | break; |
2797 | case BRIDGE_SN9C103: | 3182 | case BRIDGE_SN9C103: |
2798 | DBG(2, "SN9C103 PC Camera Controller detected " | 3183 | DBG(2, "SN9C103 PC Camera Controller detected " |
2799 | "(vid/pid 0x%04X/0x%04X)", id->idVendor, id->idProduct); | 3184 | "(vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct); |
3185 | break; | ||
3186 | case BRIDGE_SN9C105: | ||
3187 | DBG(2, "SN9C105 PC Camera Controller detected " | ||
3188 | "(vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct); | ||
3189 | break; | ||
3190 | case BRIDGE_SN9C120: | ||
3191 | DBG(2, "SN9C120 PC Camera Controller detected " | ||
3192 | "(vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct); | ||
2800 | break; | 3193 | break; |
2801 | } | 3194 | } |
2802 | 3195 | ||
@@ -2816,12 +3209,18 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) | |||
2816 | goto fail; | 3209 | goto fail; |
2817 | } | 3210 | } |
2818 | 3211 | ||
3212 | if (!(cam->bridge & cam->sensor.supported_bridge)) { | ||
3213 | DBG(1, "Bridge not supported"); | ||
3214 | err = -ENODEV; | ||
3215 | goto fail; | ||
3216 | } | ||
3217 | |||
2819 | if (sn9c102_init(cam)) { | 3218 | if (sn9c102_init(cam)) { |
2820 | DBG(1, "Initialization failed. I will retry on open()."); | 3219 | DBG(1, "Initialization failed. I will retry on open()."); |
2821 | cam->state |= DEV_MISCONFIGURED; | 3220 | cam->state |= DEV_MISCONFIGURED; |
2822 | } | 3221 | } |
2823 | 3222 | ||
2824 | strcpy(cam->v4ldev->name, "SN9C10x PC Camera"); | 3223 | strcpy(cam->v4ldev->name, "SN9C1xx PC Camera"); |
2825 | cam->v4ldev->owner = THIS_MODULE; | 3224 | cam->v4ldev->owner = THIS_MODULE; |
2826 | cam->v4ldev->type = VID_TYPE_CAPTURE | VID_TYPE_SCALES; | 3225 | cam->v4ldev->type = VID_TYPE_CAPTURE | VID_TYPE_SCALES; |
2827 | cam->v4ldev->hardware = 0; | 3226 | cam->v4ldev->hardware = 0; |
@@ -2838,7 +3237,10 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) | |||
2838 | DBG(1, "V4L2 device registration failed"); | 3237 | DBG(1, "V4L2 device registration failed"); |
2839 | if (err == -ENFILE && video_nr[dev_nr] == -1) | 3238 | if (err == -ENFILE && video_nr[dev_nr] == -1) |
2840 | DBG(1, "Free /dev/videoX node not found"); | 3239 | DBG(1, "Free /dev/videoX node not found"); |
2841 | goto fail2; | 3240 | video_nr[dev_nr] = -1; |
3241 | dev_nr = (dev_nr < SN9C102_MAX_DEVICES-1) ? dev_nr+1 : 0; | ||
3242 | mutex_unlock(&cam->dev_mutex); | ||
3243 | goto fail; | ||
2842 | } | 3244 | } |
2843 | 3245 | ||
2844 | DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->minor); | 3246 | DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->minor); |
@@ -2850,9 +3252,14 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) | |||
2850 | 3252 | ||
2851 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 3253 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
2852 | err = sn9c102_create_sysfs(cam); | 3254 | err = sn9c102_create_sysfs(cam); |
2853 | if (err) | 3255 | if (!err) |
2854 | goto fail3; | 3256 | DBG(2, "Optional device control through 'sysfs' " |
2855 | DBG(2, "Optional device control through 'sysfs' interface ready"); | 3257 | "interface ready"); |
3258 | else | ||
3259 | DBG(2, "Failed to create optional 'sysfs' interface for " | ||
3260 | "device controlling. Error #%d", err); | ||
3261 | #else | ||
3262 | DBG(2, "Optional device control through 'sysfs' interface disabled"); | ||
2856 | #endif | 3263 | #endif |
2857 | 3264 | ||
2858 | usb_set_intfdata(intf, cam); | 3265 | usb_set_intfdata(intf, cam); |
@@ -2861,14 +3268,6 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) | |||
2861 | 3268 | ||
2862 | return 0; | 3269 | return 0; |
2863 | 3270 | ||
2864 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
2865 | fail3: | ||
2866 | video_unregister_device(cam->v4ldev); | ||
2867 | #endif | ||
2868 | fail2: | ||
2869 | video_nr[dev_nr] = -1; | ||
2870 | dev_nr = (dev_nr < SN9C102_MAX_DEVICES-1) ? dev_nr+1 : 0; | ||
2871 | mutex_unlock(&cam->dev_mutex); | ||
2872 | fail: | 3271 | fail: |
2873 | if (cam) { | 3272 | if (cam) { |
2874 | kfree(cam->control_buffer); | 3273 | kfree(cam->control_buffer); |
diff --git a/drivers/media/video/sn9c102/sn9c102_devtable.h b/drivers/media/video/sn9c102/sn9c102_devtable.h new file mode 100644 index 000000000000..3a682eca6c65 --- /dev/null +++ b/drivers/media/video/sn9c102/sn9c102_devtable.h | |||
@@ -0,0 +1,142 @@ | |||
1 | /*************************************************************************** | ||
2 | * Table of device identifiers of the SN9C1xx PC Camera Controllers * | ||
3 | * * | ||
4 | * Copyright (C) 2007 by Luca Risolia <luca.risolia@studio.unibo.it> * | ||
5 | * * | ||
6 | * This program is free software; you can redistribute it and/or modify * | ||
7 | * it under the terms of the GNU General Public License as published by * | ||
8 | * the Free Software Foundation; either version 2 of the License, or * | ||
9 | * (at your option) any later version. * | ||
10 | * * | ||
11 | * This program is distributed in the hope that it will be useful, * | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | ||
14 | * GNU General Public License for more details. * | ||
15 | * * | ||
16 | * You should have received a copy of the GNU General Public License * | ||
17 | * along with this program; if not, write to the Free Software * | ||
18 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * | ||
19 | ***************************************************************************/ | ||
20 | |||
21 | #ifndef _SN9C102_DEVTABLE_H_ | ||
22 | #define _SN9C102_DEVTABLE_H_ | ||
23 | |||
24 | #include <linux/usb.h> | ||
25 | |||
26 | struct sn9c102_device; | ||
27 | |||
28 | /* | ||
29 | Each SN9C1xx camera has proper PID/VID identifiers. | ||
30 | SN9C103, SN9C105, SN9C120 support multiple interfaces, but we only have to | ||
31 | handle the video class interface. | ||
32 | */ | ||
33 | #define SN9C102_USB_DEVICE(vend, prod, bridge) \ | ||
34 | .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \ | ||
35 | USB_DEVICE_ID_MATCH_INT_CLASS, \ | ||
36 | .idVendor = (vend), \ | ||
37 | .idProduct = (prod), \ | ||
38 | .bInterfaceClass = 0xff, \ | ||
39 | .driver_info = (bridge) | ||
40 | |||
41 | static const struct usb_device_id sn9c102_id_table[] = { | ||
42 | /* SN9C101 and SN9C102 */ | ||
43 | { SN9C102_USB_DEVICE(0x0c45, 0x6001, BRIDGE_SN9C102), }, | ||
44 | { SN9C102_USB_DEVICE(0x0c45, 0x6005, BRIDGE_SN9C102), }, | ||
45 | { SN9C102_USB_DEVICE(0x0c45, 0x6007, BRIDGE_SN9C102), }, | ||
46 | { SN9C102_USB_DEVICE(0x0c45, 0x6009, BRIDGE_SN9C102), }, | ||
47 | { SN9C102_USB_DEVICE(0x0c45, 0x6011, BRIDGE_SN9C102), }, | ||
48 | { SN9C102_USB_DEVICE(0x0c45, 0x600d, BRIDGE_SN9C102), }, | ||
49 | { SN9C102_USB_DEVICE(0x0c45, 0x6019, BRIDGE_SN9C102), }, | ||
50 | { SN9C102_USB_DEVICE(0x0c45, 0x6024, BRIDGE_SN9C102), }, | ||
51 | { SN9C102_USB_DEVICE(0x0c45, 0x6025, BRIDGE_SN9C102), }, | ||
52 | { SN9C102_USB_DEVICE(0x0c45, 0x6028, BRIDGE_SN9C102), }, | ||
53 | { SN9C102_USB_DEVICE(0x0c45, 0x6029, BRIDGE_SN9C102), }, | ||
54 | { SN9C102_USB_DEVICE(0x0c45, 0x602a, BRIDGE_SN9C102), }, | ||
55 | { SN9C102_USB_DEVICE(0x0c45, 0x602b, BRIDGE_SN9C102), }, | ||
56 | { SN9C102_USB_DEVICE(0x0c45, 0x602c, BRIDGE_SN9C102), }, | ||
57 | { SN9C102_USB_DEVICE(0x0c45, 0x602d, BRIDGE_SN9C102), }, | ||
58 | { SN9C102_USB_DEVICE(0x0c45, 0x602e, BRIDGE_SN9C102), }, | ||
59 | { SN9C102_USB_DEVICE(0x0c45, 0x6030, BRIDGE_SN9C102), }, | ||
60 | { SN9C102_USB_DEVICE(0x0c45, 0x603f, BRIDGE_SN9C102), }, | ||
61 | /* SN9C103 */ | ||
62 | { SN9C102_USB_DEVICE(0x0c45, 0x6080, BRIDGE_SN9C103), }, | ||
63 | { SN9C102_USB_DEVICE(0x0c45, 0x6082, BRIDGE_SN9C103), }, | ||
64 | { SN9C102_USB_DEVICE(0x0c45, 0x6083, BRIDGE_SN9C103), }, | ||
65 | { SN9C102_USB_DEVICE(0x0c45, 0x6088, BRIDGE_SN9C103), }, | ||
66 | { SN9C102_USB_DEVICE(0x0c45, 0x608a, BRIDGE_SN9C103), }, | ||
67 | { SN9C102_USB_DEVICE(0x0c45, 0x608b, BRIDGE_SN9C103), }, | ||
68 | { SN9C102_USB_DEVICE(0x0c45, 0x608c, BRIDGE_SN9C103), }, | ||
69 | { SN9C102_USB_DEVICE(0x0c45, 0x608e, BRIDGE_SN9C103), }, | ||
70 | { SN9C102_USB_DEVICE(0x0c45, 0x608f, BRIDGE_SN9C103), }, | ||
71 | { SN9C102_USB_DEVICE(0x0c45, 0x60a0, BRIDGE_SN9C103), }, | ||
72 | { SN9C102_USB_DEVICE(0x0c45, 0x60a2, BRIDGE_SN9C103), }, | ||
73 | { SN9C102_USB_DEVICE(0x0c45, 0x60a3, BRIDGE_SN9C103), }, | ||
74 | { SN9C102_USB_DEVICE(0x0c45, 0x60a8, BRIDGE_SN9C103), }, | ||
75 | { SN9C102_USB_DEVICE(0x0c45, 0x60aa, BRIDGE_SN9C103), }, | ||
76 | { SN9C102_USB_DEVICE(0x0c45, 0x60ab, BRIDGE_SN9C103), }, | ||
77 | { SN9C102_USB_DEVICE(0x0c45, 0x60ac, BRIDGE_SN9C103), }, | ||
78 | { SN9C102_USB_DEVICE(0x0c45, 0x60ae, BRIDGE_SN9C103), }, | ||
79 | { SN9C102_USB_DEVICE(0x0c45, 0x60af, BRIDGE_SN9C103), }, | ||
80 | { SN9C102_USB_DEVICE(0x0c45, 0x60b0, BRIDGE_SN9C103), }, | ||
81 | { SN9C102_USB_DEVICE(0x0c45, 0x60b2, BRIDGE_SN9C103), }, | ||
82 | { SN9C102_USB_DEVICE(0x0c45, 0x60b3, BRIDGE_SN9C103), }, | ||
83 | { SN9C102_USB_DEVICE(0x0c45, 0x60b8, BRIDGE_SN9C103), }, | ||
84 | { SN9C102_USB_DEVICE(0x0c45, 0x60ba, BRIDGE_SN9C103), }, | ||
85 | { SN9C102_USB_DEVICE(0x0c45, 0x60bb, BRIDGE_SN9C103), }, | ||
86 | { SN9C102_USB_DEVICE(0x0c45, 0x60bc, BRIDGE_SN9C103), }, | ||
87 | { SN9C102_USB_DEVICE(0x0c45, 0x60be, BRIDGE_SN9C103), }, | ||
88 | /* SN9C105 */ | ||
89 | { SN9C102_USB_DEVICE(0x0471, 0x0327, BRIDGE_SN9C105), }, | ||
90 | { SN9C102_USB_DEVICE(0x0471, 0x0328, BRIDGE_SN9C105), }, | ||
91 | { SN9C102_USB_DEVICE(0x0c45, 0x60c0, BRIDGE_SN9C105), }, | ||
92 | { SN9C102_USB_DEVICE(0x0c45, 0x60c8, BRIDGE_SN9C105), }, | ||
93 | { SN9C102_USB_DEVICE(0x0c45, 0x60cc, BRIDGE_SN9C105), }, | ||
94 | { SN9C102_USB_DEVICE(0x0c45, 0x60ea, BRIDGE_SN9C105), }, | ||
95 | { SN9C102_USB_DEVICE(0x0c45, 0x60ec, BRIDGE_SN9C105), }, | ||
96 | { SN9C102_USB_DEVICE(0x0c45, 0x60fa, BRIDGE_SN9C105), }, | ||
97 | { SN9C102_USB_DEVICE(0x0c45, 0x60fb, BRIDGE_SN9C105), }, | ||
98 | { SN9C102_USB_DEVICE(0x0c45, 0x60fc, BRIDGE_SN9C105), }, | ||
99 | { SN9C102_USB_DEVICE(0x0c45, 0x60fe, BRIDGE_SN9C105), }, | ||
100 | /* SN9C120 */ | ||
101 | { SN9C102_USB_DEVICE(0x0c45, 0x6130, BRIDGE_SN9C120), }, | ||
102 | { SN9C102_USB_DEVICE(0x0c45, 0x613a, BRIDGE_SN9C120), }, | ||
103 | { SN9C102_USB_DEVICE(0x0c45, 0x613b, BRIDGE_SN9C120), }, | ||
104 | { SN9C102_USB_DEVICE(0x0c45, 0x613c, BRIDGE_SN9C120), }, | ||
105 | { SN9C102_USB_DEVICE(0x0c45, 0x613e, BRIDGE_SN9C120), }, | ||
106 | { } | ||
107 | }; | ||
108 | |||
109 | /* | ||
110 | Probing functions: on success, you must attach the sensor to the camera | ||
111 | by calling sn9c102_attach_sensor(). | ||
112 | To enable the I2C communication, you might need to perform a really basic | ||
113 | initialization of the SN9C1XX chip. | ||
114 | Functions must return 0 on success, the appropriate error otherwise. | ||
115 | */ | ||
116 | extern int sn9c102_probe_hv7131d(struct sn9c102_device* cam); | ||
117 | extern int sn9c102_probe_mi0343(struct sn9c102_device* cam); | ||
118 | extern int sn9c102_probe_ov7630(struct sn9c102_device* cam); | ||
119 | extern int sn9c102_probe_ov7660(struct sn9c102_device* cam); | ||
120 | extern int sn9c102_probe_pas106b(struct sn9c102_device* cam); | ||
121 | extern int sn9c102_probe_pas202bcb(struct sn9c102_device* cam); | ||
122 | extern int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam); | ||
123 | extern int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam); | ||
124 | |||
125 | /* | ||
126 | Add the above entries to this table. Be sure to add the entry in the right | ||
127 | place, since, on failure, the next probing routine is called according to | ||
128 | the order of the list below, from top to bottom. | ||
129 | */ | ||
130 | static int (*sn9c102_sensor_table[])(struct sn9c102_device*) = { | ||
131 | &sn9c102_probe_mi0343, /* strong detection based on SENSOR ids */ | ||
132 | &sn9c102_probe_pas106b, /* strong detection based on SENSOR ids */ | ||
133 | &sn9c102_probe_pas202bcb, /* strong detection based on SENSOR ids */ | ||
134 | &sn9c102_probe_hv7131d, /* strong detection based on SENSOR ids */ | ||
135 | &sn9c102_probe_ov7630, /* strong detection based on SENSOR ids */ | ||
136 | &sn9c102_probe_ov7660, /* strong detection based on SENSOR ids */ | ||
137 | &sn9c102_probe_tas5110c1b, /* detection based on USB pid/vid */ | ||
138 | &sn9c102_probe_tas5130d1b, /* detection based on USB pid/vid */ | ||
139 | NULL, | ||
140 | }; | ||
141 | |||
142 | #endif /* _SN9C102_DEVTABLE_H_ */ | ||
diff --git a/drivers/media/video/sn9c102/sn9c102_hv7131d.c b/drivers/media/video/sn9c102/sn9c102_hv7131d.c index c4117bf64b69..7ae368f60d89 100644 --- a/drivers/media/video/sn9c102/sn9c102_hv7131d.c +++ b/drivers/media/video/sn9c102/sn9c102_hv7131d.c | |||
@@ -1,8 +1,8 @@ | |||
1 | /*************************************************************************** | 1 | /*************************************************************************** |
2 | * Plug-in for HV7131D image sensor connected to the SN9C10x PC Camera * | 2 | * Plug-in for HV7131D image sensor connected to the SN9C1xx PC Camera * |
3 | * Controllers * | 3 | * Controllers * |
4 | * * | 4 | * * |
5 | * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it> * | 5 | * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it> * |
6 | * * | 6 | * * |
7 | * This program is free software; you can redistribute it and/or modify * | 7 | * This program is free software; you can redistribute it and/or modify * |
8 | * it under the terms of the GNU General Public License as published by * | 8 | * it under the terms of the GNU General Public License as published by * |
@@ -124,7 +124,7 @@ static int hv7131d_set_ctrl(struct sn9c102_device* cam, | |||
124 | static int hv7131d_set_crop(struct sn9c102_device* cam, | 124 | static int hv7131d_set_crop(struct sn9c102_device* cam, |
125 | const struct v4l2_rect* rect) | 125 | const struct v4l2_rect* rect) |
126 | { | 126 | { |
127 | struct sn9c102_sensor* s = &hv7131d; | 127 | struct sn9c102_sensor* s = sn9c102_get_sensor(cam); |
128 | int err = 0; | 128 | int err = 0; |
129 | u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 2, | 129 | u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 2, |
130 | v_start = (u8)(rect->top - s->cropcap.bounds.top) + 2; | 130 | v_start = (u8)(rect->top - s->cropcap.bounds.top) + 2; |
@@ -153,6 +153,7 @@ static int hv7131d_set_pix_format(struct sn9c102_device* cam, | |||
153 | static struct sn9c102_sensor hv7131d = { | 153 | static struct sn9c102_sensor hv7131d = { |
154 | .name = "HV7131D", | 154 | .name = "HV7131D", |
155 | .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", | 155 | .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", |
156 | .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103, | ||
156 | .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE, | 157 | .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE, |
157 | .frequency = SN9C102_I2C_100KHZ, | 158 | .frequency = SN9C102_I2C_100KHZ, |
158 | .interface = SN9C102_I2C_2WIRES, | 159 | .interface = SN9C102_I2C_2WIRES, |
diff --git a/drivers/media/video/sn9c102/sn9c102_mi0343.c b/drivers/media/video/sn9c102/sn9c102_mi0343.c index 4169ea4a2e20..a33d1bc10f90 100644 --- a/drivers/media/video/sn9c102/sn9c102_mi0343.c +++ b/drivers/media/video/sn9c102/sn9c102_mi0343.c | |||
@@ -1,8 +1,8 @@ | |||
1 | /*************************************************************************** | 1 | /*************************************************************************** |
2 | * Plug-in for MI-0343 image sensor connected to the SN9C10x PC Camera * | 2 | * Plug-in for MI-0343 image sensor connected to the SN9C1xx PC Camera * |
3 | * Controllers * | 3 | * Controllers * |
4 | * * | 4 | * * |
5 | * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it> * | 5 | * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it> * |
6 | * * | 6 | * * |
7 | * This program is free software; you can redistribute it and/or modify * | 7 | * This program is free software; you can redistribute it and/or modify * |
8 | * it under the terms of the GNU General Public License as published by * | 8 | * it under the terms of the GNU General Public License as published by * |
@@ -201,7 +201,7 @@ static int mi0343_set_ctrl(struct sn9c102_device* cam, | |||
201 | static int mi0343_set_crop(struct sn9c102_device* cam, | 201 | static int mi0343_set_crop(struct sn9c102_device* cam, |
202 | const struct v4l2_rect* rect) | 202 | const struct v4l2_rect* rect) |
203 | { | 203 | { |
204 | struct sn9c102_sensor* s = &mi0343; | 204 | struct sn9c102_sensor* s = sn9c102_get_sensor(cam); |
205 | int err = 0; | 205 | int err = 0; |
206 | u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 0, | 206 | u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 0, |
207 | v_start = (u8)(rect->top - s->cropcap.bounds.top) + 2; | 207 | v_start = (u8)(rect->top - s->cropcap.bounds.top) + 2; |
@@ -237,6 +237,7 @@ static int mi0343_set_pix_format(struct sn9c102_device* cam, | |||
237 | static struct sn9c102_sensor mi0343 = { | 237 | static struct sn9c102_sensor mi0343 = { |
238 | .name = "MI-0343", | 238 | .name = "MI-0343", |
239 | .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", | 239 | .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", |
240 | .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103, | ||
240 | .frequency = SN9C102_I2C_100KHZ, | 241 | .frequency = SN9C102_I2C_100KHZ, |
241 | .interface = SN9C102_I2C_2WIRES, | 242 | .interface = SN9C102_I2C_2WIRES, |
242 | .i2c_slave_id = 0x5d, | 243 | .i2c_slave_id = 0x5d, |
diff --git a/drivers/media/video/sn9c102/sn9c102_ov7630.c b/drivers/media/video/sn9c102/sn9c102_ov7630.c index 3da042021787..7df09ff38e63 100644 --- a/drivers/media/video/sn9c102/sn9c102_ov7630.c +++ b/drivers/media/video/sn9c102/sn9c102_ov7630.c | |||
@@ -1,8 +1,8 @@ | |||
1 | /*************************************************************************** | 1 | /*************************************************************************** |
2 | * Plug-in for OV7630 image sensor connected to the SN9C10x PC Camera * | 2 | * Plug-in for OV7630 image sensor connected to the SN9C1xx PC Camera * |
3 | * Controllers * | 3 | * Controllers * |
4 | * * | 4 | * * |
5 | * Copyright (C) 2005-2006 by Luca Risolia <luca.risolia@studio.unibo.it> * | 5 | * Copyright (C) 2006-2007 by Luca Risolia <luca.risolia@studio.unibo.it> * |
6 | * * | 6 | * * |
7 | * This program is free software; you can redistribute it and/or modify * | 7 | * This program is free software; you can redistribute it and/or modify * |
8 | * it under the terms of the GNU General Public License as published by * | 8 | * it under the terms of the GNU General Public License as published by * |
@@ -29,13 +29,17 @@ static int ov7630_init(struct sn9c102_device* cam) | |||
29 | { | 29 | { |
30 | int err = 0; | 30 | int err = 0; |
31 | 31 | ||
32 | switch (sn9c102_get_bridge(cam)) { | ||
33 | case BRIDGE_SN9C101: | ||
34 | case BRIDGE_SN9C102: | ||
32 | err += sn9c102_write_reg(cam, 0x00, 0x14); | 35 | err += sn9c102_write_reg(cam, 0x00, 0x14); |
33 | err += sn9c102_write_reg(cam, 0x60, 0x17); | 36 | err += sn9c102_write_reg(cam, 0x60, 0x17); |
34 | err += sn9c102_write_reg(cam, 0x0f, 0x18); | 37 | err += sn9c102_write_reg(cam, 0x0f, 0x18); |
35 | err += sn9c102_write_reg(cam, 0x50, 0x19); | 38 | err += sn9c102_write_reg(cam, 0x50, 0x19); |
36 | 39 | ||
37 | err += sn9c102_i2c_write(cam, 0x12, 0x80); | 40 | err += sn9c102_i2c_write(cam, 0x12, 0x8d); |
38 | err += sn9c102_i2c_write(cam, 0x11, 0x01); | 41 | err += sn9c102_i2c_write(cam, 0x12, 0x0d); |
42 | err += sn9c102_i2c_write(cam, 0x11, 0x00); | ||
39 | err += sn9c102_i2c_write(cam, 0x15, 0x34); | 43 | err += sn9c102_i2c_write(cam, 0x15, 0x34); |
40 | err += sn9c102_i2c_write(cam, 0x16, 0x03); | 44 | err += sn9c102_i2c_write(cam, 0x16, 0x03); |
41 | err += sn9c102_i2c_write(cam, 0x17, 0x1c); | 45 | err += sn9c102_i2c_write(cam, 0x17, 0x1c); |
@@ -43,14 +47,72 @@ static int ov7630_init(struct sn9c102_device* cam) | |||
43 | err += sn9c102_i2c_write(cam, 0x19, 0x06); | 47 | err += sn9c102_i2c_write(cam, 0x19, 0x06); |
44 | err += sn9c102_i2c_write(cam, 0x1a, 0xf6); | 48 | err += sn9c102_i2c_write(cam, 0x1a, 0xf6); |
45 | err += sn9c102_i2c_write(cam, 0x1b, 0x04); | 49 | err += sn9c102_i2c_write(cam, 0x1b, 0x04); |
46 | err += sn9c102_i2c_write(cam, 0x20, 0xf6); | 50 | err += sn9c102_i2c_write(cam, 0x20, 0x44); |
51 | err += sn9c102_i2c_write(cam, 0x23, 0xee); | ||
52 | err += sn9c102_i2c_write(cam, 0x26, 0xa0); | ||
53 | err += sn9c102_i2c_write(cam, 0x27, 0x9a); | ||
54 | err += sn9c102_i2c_write(cam, 0x28, 0x20); | ||
55 | err += sn9c102_i2c_write(cam, 0x29, 0x30); | ||
56 | err += sn9c102_i2c_write(cam, 0x2f, 0x3d); | ||
57 | err += sn9c102_i2c_write(cam, 0x30, 0x24); | ||
58 | err += sn9c102_i2c_write(cam, 0x32, 0x86); | ||
59 | err += sn9c102_i2c_write(cam, 0x60, 0xa9); | ||
60 | err += sn9c102_i2c_write(cam, 0x61, 0x42); | ||
61 | err += sn9c102_i2c_write(cam, 0x65, 0x00); | ||
62 | err += sn9c102_i2c_write(cam, 0x69, 0x38); | ||
63 | err += sn9c102_i2c_write(cam, 0x6f, 0x88); | ||
64 | err += sn9c102_i2c_write(cam, 0x70, 0x0b); | ||
65 | err += sn9c102_i2c_write(cam, 0x71, 0x00); | ||
66 | err += sn9c102_i2c_write(cam, 0x74, 0x21); | ||
67 | err += sn9c102_i2c_write(cam, 0x7d, 0xf7); | ||
68 | break; | ||
69 | case BRIDGE_SN9C103: | ||
70 | err += sn9c102_write_reg(cam, 0x00, 0x02); | ||
71 | err += sn9c102_write_reg(cam, 0x00, 0x03); | ||
72 | err += sn9c102_write_reg(cam, 0x1a, 0x04); | ||
73 | err += sn9c102_write_reg(cam, 0x20, 0x05); | ||
74 | err += sn9c102_write_reg(cam, 0x20, 0x06); | ||
75 | err += sn9c102_write_reg(cam, 0x20, 0x07); | ||
76 | err += sn9c102_write_reg(cam, 0x03, 0x10); | ||
77 | err += sn9c102_write_reg(cam, 0x0a, 0x14); | ||
78 | err += sn9c102_write_reg(cam, 0x60, 0x17); | ||
79 | err += sn9c102_write_reg(cam, 0x0f, 0x18); | ||
80 | err += sn9c102_write_reg(cam, 0x50, 0x19); | ||
81 | err += sn9c102_write_reg(cam, 0x1d, 0x1a); | ||
82 | err += sn9c102_write_reg(cam, 0x10, 0x1b); | ||
83 | err += sn9c102_write_reg(cam, 0x02, 0x1c); | ||
84 | err += sn9c102_write_reg(cam, 0x03, 0x1d); | ||
85 | err += sn9c102_write_reg(cam, 0x0f, 0x1e); | ||
86 | err += sn9c102_write_reg(cam, 0x0c, 0x1f); | ||
87 | err += sn9c102_write_reg(cam, 0x00, 0x20); | ||
88 | err += sn9c102_write_reg(cam, 0x10, 0x21); | ||
89 | err += sn9c102_write_reg(cam, 0x20, 0x22); | ||
90 | err += sn9c102_write_reg(cam, 0x30, 0x23); | ||
91 | err += sn9c102_write_reg(cam, 0x40, 0x24); | ||
92 | err += sn9c102_write_reg(cam, 0x50, 0x25); | ||
93 | err += sn9c102_write_reg(cam, 0x60, 0x26); | ||
94 | err += sn9c102_write_reg(cam, 0x70, 0x27); | ||
95 | err += sn9c102_write_reg(cam, 0x80, 0x28); | ||
96 | err += sn9c102_write_reg(cam, 0x90, 0x29); | ||
97 | err += sn9c102_write_reg(cam, 0xa0, 0x2a); | ||
98 | err += sn9c102_write_reg(cam, 0xb0, 0x2b); | ||
99 | err += sn9c102_write_reg(cam, 0xc0, 0x2c); | ||
100 | err += sn9c102_write_reg(cam, 0xd0, 0x2d); | ||
101 | err += sn9c102_write_reg(cam, 0xe0, 0x2e); | ||
102 | err += sn9c102_write_reg(cam, 0xf0, 0x2f); | ||
103 | err += sn9c102_write_reg(cam, 0xff, 0x30); | ||
104 | |||
105 | err += sn9c102_i2c_write(cam, 0x12, 0x8d); | ||
106 | err += sn9c102_i2c_write(cam, 0x12, 0x0d); | ||
107 | err += sn9c102_i2c_write(cam, 0x15, 0x34); | ||
108 | err += sn9c102_i2c_write(cam, 0x11, 0x01); | ||
109 | err += sn9c102_i2c_write(cam, 0x1b, 0x04); | ||
110 | err += sn9c102_i2c_write(cam, 0x20, 0x44); | ||
47 | err += sn9c102_i2c_write(cam, 0x23, 0xee); | 111 | err += sn9c102_i2c_write(cam, 0x23, 0xee); |
48 | err += sn9c102_i2c_write(cam, 0x26, 0xa0); | 112 | err += sn9c102_i2c_write(cam, 0x26, 0xa0); |
49 | err += sn9c102_i2c_write(cam, 0x27, 0x9a); | 113 | err += sn9c102_i2c_write(cam, 0x27, 0x9a); |
50 | err += sn9c102_i2c_write(cam, 0x28, 0xa0); | 114 | err += sn9c102_i2c_write(cam, 0x28, 0x20); |
51 | err += sn9c102_i2c_write(cam, 0x29, 0x30); | 115 | err += sn9c102_i2c_write(cam, 0x29, 0x30); |
52 | err += sn9c102_i2c_write(cam, 0x2a, 0xa0); | ||
53 | err += sn9c102_i2c_write(cam, 0x2b, 0x1f); | ||
54 | err += sn9c102_i2c_write(cam, 0x2f, 0x3d); | 116 | err += sn9c102_i2c_write(cam, 0x2f, 0x3d); |
55 | err += sn9c102_i2c_write(cam, 0x30, 0x24); | 117 | err += sn9c102_i2c_write(cam, 0x30, 0x24); |
56 | err += sn9c102_i2c_write(cam, 0x32, 0x86); | 118 | err += sn9c102_i2c_write(cam, 0x32, 0x86); |
@@ -63,45 +125,97 @@ static int ov7630_init(struct sn9c102_device* cam) | |||
63 | err += sn9c102_i2c_write(cam, 0x71, 0x00); | 125 | err += sn9c102_i2c_write(cam, 0x71, 0x00); |
64 | err += sn9c102_i2c_write(cam, 0x74, 0x21); | 126 | err += sn9c102_i2c_write(cam, 0x74, 0x21); |
65 | err += sn9c102_i2c_write(cam, 0x7d, 0xf7); | 127 | err += sn9c102_i2c_write(cam, 0x7d, 0xf7); |
128 | break; | ||
129 | default: | ||
130 | break; | ||
131 | } | ||
66 | 132 | ||
67 | return err; | 133 | return err; |
68 | } | 134 | } |
69 | 135 | ||
70 | 136 | ||
71 | static int ov7630_set_ctrl(struct sn9c102_device* cam, | 137 | static int ov7630_get_ctrl(struct sn9c102_device* cam, |
72 | const struct v4l2_control* ctrl) | 138 | struct v4l2_control* ctrl) |
73 | { | 139 | { |
74 | int err = 0; | 140 | int err = 0; |
75 | 141 | ||
76 | switch (ctrl->id) { | 142 | switch (ctrl->id) { |
77 | case V4L2_CID_EXPOSURE: | 143 | case V4L2_CID_EXPOSURE: |
78 | err += sn9c102_i2c_write(cam, 0x10, ctrl->value >> 2); | 144 | if ((ctrl->value = sn9c102_i2c_read(cam, 0x10)) < 0) |
79 | err += sn9c102_i2c_write(cam, 0x76, ctrl->value & 0x03); | 145 | return -EIO; |
80 | break; | 146 | break; |
81 | case V4L2_CID_RED_BALANCE: | 147 | case V4L2_CID_RED_BALANCE: |
82 | err += sn9c102_i2c_write(cam, 0x02, ctrl->value); | 148 | ctrl->value = sn9c102_pread_reg(cam, 0x07); |
83 | break; | 149 | break; |
84 | case V4L2_CID_BLUE_BALANCE: | 150 | case V4L2_CID_BLUE_BALANCE: |
85 | err += sn9c102_i2c_write(cam, 0x01, ctrl->value); | 151 | ctrl->value = sn9c102_pread_reg(cam, 0x06); |
152 | break; | ||
153 | case SN9C102_V4L2_CID_GREEN_BALANCE: | ||
154 | ctrl->value = sn9c102_pread_reg(cam, 0x05); | ||
86 | break; | 155 | break; |
87 | case V4L2_CID_GAIN: | 156 | case V4L2_CID_GAIN: |
88 | err += sn9c102_i2c_write(cam, 0x00, ctrl->value); | 157 | if ((ctrl->value = sn9c102_i2c_read(cam, 0x00)) < 0) |
158 | return -EIO; | ||
159 | ctrl->value &= 0x3f; | ||
160 | break; | ||
161 | case V4L2_CID_DO_WHITE_BALANCE: | ||
162 | if ((ctrl->value = sn9c102_i2c_read(cam, 0x0c)) < 0) | ||
163 | return -EIO; | ||
164 | ctrl->value &= 0x3f; | ||
165 | break; | ||
166 | case V4L2_CID_WHITENESS: | ||
167 | if ((ctrl->value = sn9c102_i2c_read(cam, 0x0d)) < 0) | ||
168 | return -EIO; | ||
169 | ctrl->value &= 0x3f; | ||
170 | break; | ||
171 | case V4L2_CID_AUTOGAIN: | ||
172 | if ((ctrl->value = sn9c102_i2c_read(cam, 0x13)) < 0) | ||
173 | return -EIO; | ||
174 | ctrl->value &= 0x01; | ||
175 | break; | ||
176 | case V4L2_CID_VFLIP: | ||
177 | if ((ctrl->value = sn9c102_i2c_read(cam, 0x75)) < 0) | ||
178 | return -EIO; | ||
179 | ctrl->value = (ctrl->value & 0x80) ? 1 : 0; | ||
180 | break; | ||
181 | case SN9C102_V4L2_CID_GAMMA: | ||
182 | if ((ctrl->value = sn9c102_i2c_read(cam, 0x14)) < 0) | ||
183 | return -EIO; | ||
184 | ctrl->value = (ctrl->value & 0x02) ? 1 : 0; | ||
185 | break; | ||
186 | case SN9C102_V4L2_CID_BAND_FILTER: | ||
187 | if ((ctrl->value = sn9c102_i2c_read(cam, 0x2d)) < 0) | ||
188 | return -EIO; | ||
189 | ctrl->value = (ctrl->value & 0x02) ? 1 : 0; | ||
190 | break; | ||
191 | default: | ||
192 | return -EINVAL; | ||
193 | } | ||
194 | |||
195 | return err ? -EIO : 0; | ||
196 | } | ||
197 | |||
198 | |||
199 | static int ov7630_set_ctrl(struct sn9c102_device* cam, | ||
200 | const struct v4l2_control* ctrl) | ||
201 | { | ||
202 | int err = 0; | ||
203 | |||
204 | switch (ctrl->id) { | ||
205 | case V4L2_CID_EXPOSURE: | ||
206 | err += sn9c102_i2c_write(cam, 0x10, ctrl->value); | ||
89 | break; | 207 | break; |
90 | case V4L2_CID_CONTRAST: | 208 | case V4L2_CID_RED_BALANCE: |
91 | err += ctrl->value ? sn9c102_i2c_write(cam, 0x05, | 209 | err += sn9c102_write_reg(cam, ctrl->value, 0x07); |
92 | (ctrl->value-1) | 0x20) | ||
93 | : sn9c102_i2c_write(cam, 0x05, 0x00); | ||
94 | break; | 210 | break; |
95 | case V4L2_CID_BRIGHTNESS: | 211 | case V4L2_CID_BLUE_BALANCE: |
96 | err += sn9c102_i2c_write(cam, 0x06, ctrl->value); | 212 | err += sn9c102_write_reg(cam, ctrl->value, 0x06); |
97 | break; | 213 | break; |
98 | case V4L2_CID_SATURATION: | 214 | case SN9C102_V4L2_CID_GREEN_BALANCE: |
99 | err += sn9c102_i2c_write(cam, 0x03, ctrl->value << 4); | 215 | err += sn9c102_write_reg(cam, ctrl->value, 0x05); |
100 | break; | 216 | break; |
101 | case V4L2_CID_HUE: | 217 | case V4L2_CID_GAIN: |
102 | err += ctrl->value ? sn9c102_i2c_write(cam, 0x04, | 218 | err += sn9c102_i2c_write(cam, 0x00, ctrl->value); |
103 | (ctrl->value-1) | 0x20) | ||
104 | : sn9c102_i2c_write(cam, 0x04, 0x00); | ||
105 | break; | 219 | break; |
106 | case V4L2_CID_DO_WHITE_BALANCE: | 220 | case V4L2_CID_DO_WHITE_BALANCE: |
107 | err += sn9c102_i2c_write(cam, 0x0c, ctrl->value); | 221 | err += sn9c102_i2c_write(cam, 0x0c, ctrl->value); |
@@ -109,23 +223,15 @@ static int ov7630_set_ctrl(struct sn9c102_device* cam, | |||
109 | case V4L2_CID_WHITENESS: | 223 | case V4L2_CID_WHITENESS: |
110 | err += sn9c102_i2c_write(cam, 0x0d, ctrl->value); | 224 | err += sn9c102_i2c_write(cam, 0x0d, ctrl->value); |
111 | break; | 225 | break; |
112 | case V4L2_CID_AUTO_WHITE_BALANCE: | ||
113 | err += sn9c102_i2c_write(cam, 0x12, (ctrl->value << 2) | 0x78); | ||
114 | break; | ||
115 | case V4L2_CID_AUTOGAIN: | 226 | case V4L2_CID_AUTOGAIN: |
116 | err += sn9c102_i2c_write(cam, 0x13, ctrl->value); | 227 | err += sn9c102_i2c_write(cam, 0x13, ctrl->value | |
228 | (ctrl->value << 1)); | ||
117 | break; | 229 | break; |
118 | case V4L2_CID_VFLIP: | 230 | case V4L2_CID_VFLIP: |
119 | err += sn9c102_i2c_write(cam, 0x75, 0x0e | (ctrl->value << 7)); | 231 | err += sn9c102_i2c_write(cam, 0x75, 0x0e | (ctrl->value << 7)); |
120 | break; | 232 | break; |
121 | case V4L2_CID_BLACK_LEVEL: | ||
122 | err += sn9c102_i2c_write(cam, 0x25, ctrl->value); | ||
123 | break; | ||
124 | case SN9C102_V4L2_CID_BRIGHT_LEVEL: | ||
125 | err += sn9c102_i2c_write(cam, 0x24, ctrl->value); | ||
126 | break; | ||
127 | case SN9C102_V4L2_CID_GAMMA: | 233 | case SN9C102_V4L2_CID_GAMMA: |
128 | err += sn9c102_i2c_write(cam, 0x14, (ctrl->value << 2) | 0x80); | 234 | err += sn9c102_i2c_write(cam, 0x14, ctrl->value << 2); |
129 | break; | 235 | break; |
130 | case SN9C102_V4L2_CID_BAND_FILTER: | 236 | case SN9C102_V4L2_CID_BAND_FILTER: |
131 | err += sn9c102_i2c_write(cam, 0x2d, ctrl->value << 2); | 237 | err += sn9c102_i2c_write(cam, 0x2d, ctrl->value << 2); |
@@ -141,10 +247,12 @@ static int ov7630_set_ctrl(struct sn9c102_device* cam, | |||
141 | static int ov7630_set_crop(struct sn9c102_device* cam, | 247 | static int ov7630_set_crop(struct sn9c102_device* cam, |
142 | const struct v4l2_rect* rect) | 248 | const struct v4l2_rect* rect) |
143 | { | 249 | { |
144 | struct sn9c102_sensor* s = &ov7630; | 250 | struct sn9c102_sensor* s = sn9c102_get_sensor(cam); |
145 | int err = 0; | 251 | int err = 0; |
146 | u8 v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1; | 252 | u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 1, |
253 | v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1; | ||
147 | 254 | ||
255 | err += sn9c102_write_reg(cam, h_start, 0x12); | ||
148 | err += sn9c102_write_reg(cam, v_start, 0x13); | 256 | err += sn9c102_write_reg(cam, v_start, 0x13); |
149 | 257 | ||
150 | return err; | 258 | return err; |
@@ -168,7 +276,8 @@ static int ov7630_set_pix_format(struct sn9c102_device* cam, | |||
168 | static struct sn9c102_sensor ov7630 = { | 276 | static struct sn9c102_sensor ov7630 = { |
169 | .name = "OV7630", | 277 | .name = "OV7630", |
170 | .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", | 278 | .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", |
171 | .sysfs_ops = SN9C102_I2C_WRITE, | 279 | .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103, |
280 | .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE, | ||
172 | .frequency = SN9C102_I2C_100KHZ, | 281 | .frequency = SN9C102_I2C_100KHZ, |
173 | .interface = SN9C102_I2C_2WIRES, | 282 | .interface = SN9C102_I2C_2WIRES, |
174 | .i2c_slave_id = 0x21, | 283 | .i2c_slave_id = 0x21, |
@@ -185,73 +294,23 @@ static struct sn9c102_sensor ov7630 = { | |||
185 | .flags = 0, | 294 | .flags = 0, |
186 | }, | 295 | }, |
187 | { | 296 | { |
188 | .id = V4L2_CID_HUE, | ||
189 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
190 | .name = "hue", | ||
191 | .minimum = 0x00, | ||
192 | .maximum = 0x1f+1, | ||
193 | .step = 0x01, | ||
194 | .default_value = 0x00, | ||
195 | .flags = 0, | ||
196 | }, | ||
197 | { | ||
198 | .id = V4L2_CID_SATURATION, | ||
199 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
200 | .name = "saturation", | ||
201 | .minimum = 0x00, | ||
202 | .maximum = 0x0f, | ||
203 | .step = 0x01, | ||
204 | .default_value = 0x08, | ||
205 | .flags = 0, | ||
206 | }, | ||
207 | { | ||
208 | .id = V4L2_CID_CONTRAST, | ||
209 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
210 | .name = "contrast", | ||
211 | .minimum = 0x00, | ||
212 | .maximum = 0x1f+1, | ||
213 | .step = 0x01, | ||
214 | .default_value = 0x00, | ||
215 | .flags = 0, | ||
216 | }, | ||
217 | { | ||
218 | .id = V4L2_CID_EXPOSURE, | 297 | .id = V4L2_CID_EXPOSURE, |
219 | .type = V4L2_CTRL_TYPE_INTEGER, | 298 | .type = V4L2_CTRL_TYPE_INTEGER, |
220 | .name = "exposure", | 299 | .name = "exposure", |
221 | .minimum = 0x000, | ||
222 | .maximum = 0x3ff, | ||
223 | .step = 0x001, | ||
224 | .default_value = 0x83<<2, | ||
225 | .flags = 0, | ||
226 | }, | ||
227 | { | ||
228 | .id = V4L2_CID_RED_BALANCE, | ||
229 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
230 | .name = "red balance", | ||
231 | .minimum = 0x00, | ||
232 | .maximum = 0xff, | ||
233 | .step = 0x01, | ||
234 | .default_value = 0x3a, | ||
235 | .flags = 0, | ||
236 | }, | ||
237 | { | ||
238 | .id = V4L2_CID_BLUE_BALANCE, | ||
239 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
240 | .name = "blue balance", | ||
241 | .minimum = 0x00, | 300 | .minimum = 0x00, |
242 | .maximum = 0xff, | 301 | .maximum = 0xff, |
243 | .step = 0x01, | 302 | .step = 0x01, |
244 | .default_value = 0x77, | 303 | .default_value = 0x60, |
245 | .flags = 0, | 304 | .flags = 0, |
246 | }, | 305 | }, |
247 | { | 306 | { |
248 | .id = V4L2_CID_BRIGHTNESS, | 307 | .id = V4L2_CID_WHITENESS, |
249 | .type = V4L2_CTRL_TYPE_INTEGER, | 308 | .type = V4L2_CTRL_TYPE_INTEGER, |
250 | .name = "brightness", | 309 | .name = "white balance background: red", |
251 | .minimum = 0x00, | 310 | .minimum = 0x00, |
252 | .maximum = 0xff, | 311 | .maximum = 0x3f, |
253 | .step = 0x01, | 312 | .step = 0x01, |
254 | .default_value = 0xa0, | 313 | .default_value = 0x20, |
255 | .flags = 0, | 314 | .flags = 0, |
256 | }, | 315 | }, |
257 | { | 316 | { |
@@ -265,31 +324,31 @@ static struct sn9c102_sensor ov7630 = { | |||
265 | .flags = 0, | 324 | .flags = 0, |
266 | }, | 325 | }, |
267 | { | 326 | { |
268 | .id = V4L2_CID_WHITENESS, | 327 | .id = V4L2_CID_RED_BALANCE, |
269 | .type = V4L2_CTRL_TYPE_INTEGER, | 328 | .type = V4L2_CTRL_TYPE_INTEGER, |
270 | .name = "white balance background: red", | 329 | .name = "red balance", |
271 | .minimum = 0x00, | 330 | .minimum = 0x00, |
272 | .maximum = 0x3f, | 331 | .maximum = 0x7f, |
273 | .step = 0x01, | 332 | .step = 0x01, |
274 | .default_value = 0x20, | 333 | .default_value = 0x20, |
275 | .flags = 0, | 334 | .flags = 0, |
276 | }, | 335 | }, |
277 | { | 336 | { |
278 | .id = V4L2_CID_AUTO_WHITE_BALANCE, | 337 | .id = V4L2_CID_BLUE_BALANCE, |
279 | .type = V4L2_CTRL_TYPE_BOOLEAN, | 338 | .type = V4L2_CTRL_TYPE_INTEGER, |
280 | .name = "auto white balance", | 339 | .name = "blue balance", |
281 | .minimum = 0x00, | 340 | .minimum = 0x00, |
282 | .maximum = 0x01, | 341 | .maximum = 0x7f, |
283 | .step = 0x01, | 342 | .step = 0x01, |
284 | .default_value = 0x01, | 343 | .default_value = 0x20, |
285 | .flags = 0, | 344 | .flags = 0, |
286 | }, | 345 | }, |
287 | { | 346 | { |
288 | .id = V4L2_CID_AUTOGAIN, | 347 | .id = V4L2_CID_AUTOGAIN, |
289 | .type = V4L2_CTRL_TYPE_INTEGER, | 348 | .type = V4L2_CTRL_TYPE_BOOLEAN, |
290 | .name = "gain & exposure mode", | 349 | .name = "auto adjust", |
291 | .minimum = 0x00, | 350 | .minimum = 0x00, |
292 | .maximum = 0x03, | 351 | .maximum = 0x01, |
293 | .step = 0x01, | 352 | .step = 0x01, |
294 | .default_value = 0x00, | 353 | .default_value = 0x00, |
295 | .flags = 0, | 354 | .flags = 0, |
@@ -305,23 +364,13 @@ static struct sn9c102_sensor ov7630 = { | |||
305 | .flags = 0, | 364 | .flags = 0, |
306 | }, | 365 | }, |
307 | { | 366 | { |
308 | .id = V4L2_CID_BLACK_LEVEL, | 367 | .id = SN9C102_V4L2_CID_GREEN_BALANCE, |
309 | .type = V4L2_CTRL_TYPE_INTEGER, | 368 | .type = V4L2_CTRL_TYPE_INTEGER, |
310 | .name = "black pixel ratio", | 369 | .name = "green balance", |
311 | .minimum = 0x01, | 370 | .minimum = 0x00, |
312 | .maximum = 0x9a, | 371 | .maximum = 0x7f, |
313 | .step = 0x01, | ||
314 | .default_value = 0x8a, | ||
315 | .flags = 0, | ||
316 | }, | ||
317 | { | ||
318 | .id = SN9C102_V4L2_CID_BRIGHT_LEVEL, | ||
319 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
320 | .name = "bright pixel ratio", | ||
321 | .minimum = 0x01, | ||
322 | .maximum = 0x9a, | ||
323 | .step = 0x01, | 372 | .step = 0x01, |
324 | .default_value = 0x10, | 373 | .default_value = 0x20, |
325 | .flags = 0, | 374 | .flags = 0, |
326 | }, | 375 | }, |
327 | { | 376 | { |
@@ -345,6 +394,7 @@ static struct sn9c102_sensor ov7630 = { | |||
345 | .flags = 0, | 394 | .flags = 0, |
346 | }, | 395 | }, |
347 | }, | 396 | }, |
397 | .get_ctrl = &ov7630_get_ctrl, | ||
348 | .set_ctrl = &ov7630_set_ctrl, | 398 | .set_ctrl = &ov7630_set_ctrl, |
349 | .cropcap = { | 399 | .cropcap = { |
350 | .bounds = { | 400 | .bounds = { |
@@ -364,7 +414,7 @@ static struct sn9c102_sensor ov7630 = { | |||
364 | .pix_format = { | 414 | .pix_format = { |
365 | .width = 640, | 415 | .width = 640, |
366 | .height = 480, | 416 | .height = 480, |
367 | .pixelformat = V4L2_PIX_FMT_SBGGR8, | 417 | .pixelformat = V4L2_PIX_FMT_SN9C10X, |
368 | .priv = 8, | 418 | .priv = 8, |
369 | }, | 419 | }, |
370 | .set_pix_format = &ov7630_set_pix_format | 420 | .set_pix_format = &ov7630_set_pix_format |
@@ -373,28 +423,36 @@ static struct sn9c102_sensor ov7630 = { | |||
373 | 423 | ||
374 | int sn9c102_probe_ov7630(struct sn9c102_device* cam) | 424 | int sn9c102_probe_ov7630(struct sn9c102_device* cam) |
375 | { | 425 | { |
376 | const struct usb_device_id ov7630_id_table[] = { | 426 | int pid, ver, err = 0; |
377 | { USB_DEVICE(0x0c45, 0x602c), }, | ||
378 | { USB_DEVICE(0x0c45, 0x602d), }, | ||
379 | { USB_DEVICE(0x0c45, 0x608f), }, | ||
380 | { USB_DEVICE(0x0c45, 0x60b0), }, | ||
381 | { } | ||
382 | }; | ||
383 | int err = 0; | ||
384 | |||
385 | if (!sn9c102_match_id(cam, ov7630_id_table)) | ||
386 | return -ENODEV; | ||
387 | 427 | ||
428 | switch (sn9c102_get_bridge(cam)) { | ||
429 | case BRIDGE_SN9C101: | ||
430 | case BRIDGE_SN9C102: | ||
388 | err += sn9c102_write_reg(cam, 0x01, 0x01); | 431 | err += sn9c102_write_reg(cam, 0x01, 0x01); |
389 | err += sn9c102_write_reg(cam, 0x00, 0x01); | 432 | err += sn9c102_write_reg(cam, 0x00, 0x01); |
390 | err += sn9c102_write_reg(cam, 0x28, 0x17); | 433 | err += sn9c102_write_reg(cam, 0x28, 0x17); |
391 | if (err) | 434 | break; |
392 | return -EIO; | 435 | case BRIDGE_SN9C103: /* do _not_ change anything! */ |
436 | err += sn9c102_write_reg(cam, 0x09, 0x01); | ||
437 | err += sn9c102_write_reg(cam, 0x42, 0x01); | ||
438 | err += sn9c102_write_reg(cam, 0x28, 0x17); | ||
439 | err += sn9c102_write_reg(cam, 0x44, 0x02); | ||
440 | pid = sn9c102_i2c_try_read(cam, &ov7630, 0x0a); | ||
441 | if (err || pid < 0) { /* try a different initialization */ | ||
442 | err = sn9c102_write_reg(cam, 0x01, 0x01); | ||
443 | err += sn9c102_write_reg(cam, 0x00, 0x01); | ||
444 | } | ||
445 | break; | ||
446 | default: | ||
447 | break; | ||
448 | } | ||
393 | 449 | ||
394 | err += sn9c102_i2c_try_write(cam, &ov7630, 0x0b, 0); | 450 | pid = sn9c102_i2c_try_read(cam, &ov7630, 0x0a); |
395 | if (err) | 451 | ver = sn9c102_i2c_try_read(cam, &ov7630, 0x0b); |
452 | if (err || pid < 0 || ver < 0) | ||
453 | return -EIO; | ||
454 | if (pid != 0x76 || ver != 0x31) | ||
396 | return -ENODEV; | 455 | return -ENODEV; |
397 | |||
398 | sn9c102_attach_sensor(cam, &ov7630); | 456 | sn9c102_attach_sensor(cam, &ov7630); |
399 | 457 | ||
400 | return 0; | 458 | return 0; |
diff --git a/drivers/media/video/sn9c102/sn9c102_ov7660.c b/drivers/media/video/sn9c102/sn9c102_ov7660.c new file mode 100644 index 000000000000..d670c24d4435 --- /dev/null +++ b/drivers/media/video/sn9c102/sn9c102_ov7660.c | |||
@@ -0,0 +1,592 @@ | |||
1 | /*************************************************************************** | ||
2 | * Plug-in for OV7660 image sensor connected to the SN9C1xx PC Camera * | ||
3 | * Controllers * | ||
4 | * * | ||
5 | * Copyright (C) 2007 by Luca Risolia <luca.risolia@studio.unibo.it> * | ||
6 | * * | ||
7 | * This program is free software; you can redistribute it and/or modify * | ||
8 | * it under the terms of the GNU General Public License as published by * | ||
9 | * the Free Software Foundation; either version 2 of the License, or * | ||
10 | * (at your option) any later version. * | ||
11 | * * | ||
12 | * This program is distributed in the hope that it will be useful, * | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | ||
15 | * GNU General Public License for more details. * | ||
16 | * * | ||
17 | * You should have received a copy of the GNU General Public License * | ||
18 | * along with this program; if not, write to the Free Software * | ||
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * | ||
20 | ***************************************************************************/ | ||
21 | |||
22 | #include "sn9c102_sensor.h" | ||
23 | |||
24 | |||
25 | static struct sn9c102_sensor ov7660; | ||
26 | |||
27 | |||
28 | static int ov7660_init(struct sn9c102_device* cam) | ||
29 | { | ||
30 | int err = 0; | ||
31 | |||
32 | err += sn9c102_write_reg(cam, 0x40, 0x02); | ||
33 | err += sn9c102_write_reg(cam, 0x00, 0x03); | ||
34 | err += sn9c102_write_reg(cam, 0x1a, 0x04); | ||
35 | err += sn9c102_write_reg(cam, 0x03, 0x10); | ||
36 | err += sn9c102_write_reg(cam, 0x08, 0x14); | ||
37 | err += sn9c102_write_reg(cam, 0x20, 0x17); | ||
38 | err += sn9c102_write_reg(cam, 0x8b, 0x18); | ||
39 | err += sn9c102_write_reg(cam, 0x00, 0x19); | ||
40 | err += sn9c102_write_reg(cam, 0x1d, 0x1a); | ||
41 | err += sn9c102_write_reg(cam, 0x10, 0x1b); | ||
42 | err += sn9c102_write_reg(cam, 0x02, 0x1c); | ||
43 | err += sn9c102_write_reg(cam, 0x03, 0x1d); | ||
44 | err += sn9c102_write_reg(cam, 0x0f, 0x1e); | ||
45 | err += sn9c102_write_reg(cam, 0x0c, 0x1f); | ||
46 | err += sn9c102_write_reg(cam, 0x00, 0x20); | ||
47 | err += sn9c102_write_reg(cam, 0x29, 0x21); | ||
48 | err += sn9c102_write_reg(cam, 0x40, 0x22); | ||
49 | err += sn9c102_write_reg(cam, 0x54, 0x23); | ||
50 | err += sn9c102_write_reg(cam, 0x66, 0x24); | ||
51 | err += sn9c102_write_reg(cam, 0x76, 0x25); | ||
52 | err += sn9c102_write_reg(cam, 0x85, 0x26); | ||
53 | err += sn9c102_write_reg(cam, 0x94, 0x27); | ||
54 | err += sn9c102_write_reg(cam, 0xa1, 0x28); | ||
55 | err += sn9c102_write_reg(cam, 0xae, 0x29); | ||
56 | err += sn9c102_write_reg(cam, 0xbb, 0x2a); | ||
57 | err += sn9c102_write_reg(cam, 0xc7, 0x2b); | ||
58 | err += sn9c102_write_reg(cam, 0xd3, 0x2c); | ||
59 | err += sn9c102_write_reg(cam, 0xde, 0x2d); | ||
60 | err += sn9c102_write_reg(cam, 0xea, 0x2e); | ||
61 | err += sn9c102_write_reg(cam, 0xf4, 0x2f); | ||
62 | err += sn9c102_write_reg(cam, 0xff, 0x30); | ||
63 | err += sn9c102_write_reg(cam, 0x00, 0x3F); | ||
64 | err += sn9c102_write_reg(cam, 0xC7, 0x40); | ||
65 | err += sn9c102_write_reg(cam, 0x01, 0x41); | ||
66 | err += sn9c102_write_reg(cam, 0x44, 0x42); | ||
67 | err += sn9c102_write_reg(cam, 0x00, 0x43); | ||
68 | err += sn9c102_write_reg(cam, 0x44, 0x44); | ||
69 | err += sn9c102_write_reg(cam, 0x00, 0x45); | ||
70 | err += sn9c102_write_reg(cam, 0x44, 0x46); | ||
71 | err += sn9c102_write_reg(cam, 0x00, 0x47); | ||
72 | err += sn9c102_write_reg(cam, 0xC7, 0x48); | ||
73 | err += sn9c102_write_reg(cam, 0x01, 0x49); | ||
74 | err += sn9c102_write_reg(cam, 0xC7, 0x4A); | ||
75 | err += sn9c102_write_reg(cam, 0x01, 0x4B); | ||
76 | err += sn9c102_write_reg(cam, 0xC7, 0x4C); | ||
77 | err += sn9c102_write_reg(cam, 0x01, 0x4D); | ||
78 | err += sn9c102_write_reg(cam, 0x44, 0x4E); | ||
79 | err += sn9c102_write_reg(cam, 0x00, 0x4F); | ||
80 | err += sn9c102_write_reg(cam, 0x44, 0x50); | ||
81 | err += sn9c102_write_reg(cam, 0x00, 0x51); | ||
82 | err += sn9c102_write_reg(cam, 0x44, 0x52); | ||
83 | err += sn9c102_write_reg(cam, 0x00, 0x53); | ||
84 | err += sn9c102_write_reg(cam, 0xC7, 0x54); | ||
85 | err += sn9c102_write_reg(cam, 0x01, 0x55); | ||
86 | err += sn9c102_write_reg(cam, 0xC7, 0x56); | ||
87 | err += sn9c102_write_reg(cam, 0x01, 0x57); | ||
88 | err += sn9c102_write_reg(cam, 0xC7, 0x58); | ||
89 | err += sn9c102_write_reg(cam, 0x01, 0x59); | ||
90 | err += sn9c102_write_reg(cam, 0x44, 0x5A); | ||
91 | err += sn9c102_write_reg(cam, 0x00, 0x5B); | ||
92 | err += sn9c102_write_reg(cam, 0x44, 0x5C); | ||
93 | err += sn9c102_write_reg(cam, 0x00, 0x5D); | ||
94 | err += sn9c102_write_reg(cam, 0x44, 0x5E); | ||
95 | err += sn9c102_write_reg(cam, 0x00, 0x5F); | ||
96 | err += sn9c102_write_reg(cam, 0xC7, 0x60); | ||
97 | err += sn9c102_write_reg(cam, 0x01, 0x61); | ||
98 | err += sn9c102_write_reg(cam, 0xC7, 0x62); | ||
99 | err += sn9c102_write_reg(cam, 0x01, 0x63); | ||
100 | err += sn9c102_write_reg(cam, 0xC7, 0x64); | ||
101 | err += sn9c102_write_reg(cam, 0x01, 0x65); | ||
102 | err += sn9c102_write_reg(cam, 0x44, 0x66); | ||
103 | err += sn9c102_write_reg(cam, 0x00, 0x67); | ||
104 | err += sn9c102_write_reg(cam, 0x44, 0x68); | ||
105 | err += sn9c102_write_reg(cam, 0x00, 0x69); | ||
106 | err += sn9c102_write_reg(cam, 0x44, 0x6A); | ||
107 | err += sn9c102_write_reg(cam, 0x00, 0x6B); | ||
108 | err += sn9c102_write_reg(cam, 0xC7, 0x6C); | ||
109 | err += sn9c102_write_reg(cam, 0x01, 0x6D); | ||
110 | err += sn9c102_write_reg(cam, 0xC7, 0x6E); | ||
111 | err += sn9c102_write_reg(cam, 0x01, 0x6F); | ||
112 | err += sn9c102_write_reg(cam, 0xC7, 0x70); | ||
113 | err += sn9c102_write_reg(cam, 0x01, 0x71); | ||
114 | err += sn9c102_write_reg(cam, 0x44, 0x72); | ||
115 | err += sn9c102_write_reg(cam, 0x00, 0x73); | ||
116 | err += sn9c102_write_reg(cam, 0x44, 0x74); | ||
117 | err += sn9c102_write_reg(cam, 0x00, 0x75); | ||
118 | err += sn9c102_write_reg(cam, 0x44, 0x76); | ||
119 | err += sn9c102_write_reg(cam, 0x00, 0x77); | ||
120 | err += sn9c102_write_reg(cam, 0xC7, 0x78); | ||
121 | err += sn9c102_write_reg(cam, 0x01, 0x79); | ||
122 | err += sn9c102_write_reg(cam, 0xC7, 0x7A); | ||
123 | err += sn9c102_write_reg(cam, 0x01, 0x7B); | ||
124 | err += sn9c102_write_reg(cam, 0xC7, 0x7C); | ||
125 | err += sn9c102_write_reg(cam, 0x01, 0x7D); | ||
126 | err += sn9c102_write_reg(cam, 0x44, 0x7E); | ||
127 | err += sn9c102_write_reg(cam, 0x00, 0x7F); | ||
128 | err += sn9c102_write_reg(cam, 0x14, 0x84); | ||
129 | err += sn9c102_write_reg(cam, 0x00, 0x85); | ||
130 | err += sn9c102_write_reg(cam, 0x27, 0x86); | ||
131 | err += sn9c102_write_reg(cam, 0x00, 0x87); | ||
132 | err += sn9c102_write_reg(cam, 0x07, 0x88); | ||
133 | err += sn9c102_write_reg(cam, 0x00, 0x89); | ||
134 | err += sn9c102_write_reg(cam, 0xEC, 0x8A); | ||
135 | err += sn9c102_write_reg(cam, 0x0f, 0x8B); | ||
136 | err += sn9c102_write_reg(cam, 0xD8, 0x8C); | ||
137 | err += sn9c102_write_reg(cam, 0x0f, 0x8D); | ||
138 | err += sn9c102_write_reg(cam, 0x3D, 0x8E); | ||
139 | err += sn9c102_write_reg(cam, 0x00, 0x8F); | ||
140 | err += sn9c102_write_reg(cam, 0x3D, 0x90); | ||
141 | err += sn9c102_write_reg(cam, 0x00, 0x91); | ||
142 | err += sn9c102_write_reg(cam, 0xCD, 0x92); | ||
143 | err += sn9c102_write_reg(cam, 0x0f, 0x93); | ||
144 | err += sn9c102_write_reg(cam, 0xf7, 0x94); | ||
145 | err += sn9c102_write_reg(cam, 0x0f, 0x95); | ||
146 | err += sn9c102_write_reg(cam, 0x0C, 0x96); | ||
147 | err += sn9c102_write_reg(cam, 0x00, 0x97); | ||
148 | err += sn9c102_write_reg(cam, 0x00, 0x98); | ||
149 | err += sn9c102_write_reg(cam, 0x66, 0x99); | ||
150 | err += sn9c102_write_reg(cam, 0x05, 0x9A); | ||
151 | err += sn9c102_write_reg(cam, 0x00, 0x9B); | ||
152 | err += sn9c102_write_reg(cam, 0x04, 0x9C); | ||
153 | err += sn9c102_write_reg(cam, 0x00, 0x9D); | ||
154 | err += sn9c102_write_reg(cam, 0x08, 0x9E); | ||
155 | err += sn9c102_write_reg(cam, 0x00, 0x9F); | ||
156 | err += sn9c102_write_reg(cam, 0x2D, 0xC0); | ||
157 | err += sn9c102_write_reg(cam, 0x2D, 0xC1); | ||
158 | err += sn9c102_write_reg(cam, 0x3A, 0xC2); | ||
159 | err += sn9c102_write_reg(cam, 0x05, 0xC3); | ||
160 | err += sn9c102_write_reg(cam, 0x04, 0xC4); | ||
161 | err += sn9c102_write_reg(cam, 0x3F, 0xC5); | ||
162 | err += sn9c102_write_reg(cam, 0x00, 0xC6); | ||
163 | err += sn9c102_write_reg(cam, 0x00, 0xC7); | ||
164 | err += sn9c102_write_reg(cam, 0x50, 0xC8); | ||
165 | err += sn9c102_write_reg(cam, 0x3C, 0xC9); | ||
166 | err += sn9c102_write_reg(cam, 0x28, 0xCA); | ||
167 | err += sn9c102_write_reg(cam, 0xD8, 0xCB); | ||
168 | err += sn9c102_write_reg(cam, 0x14, 0xCC); | ||
169 | err += sn9c102_write_reg(cam, 0xEC, 0xCD); | ||
170 | err += sn9c102_write_reg(cam, 0x32, 0xCE); | ||
171 | err += sn9c102_write_reg(cam, 0xDD, 0xCF); | ||
172 | err += sn9c102_write_reg(cam, 0x32, 0xD0); | ||
173 | err += sn9c102_write_reg(cam, 0xDD, 0xD1); | ||
174 | err += sn9c102_write_reg(cam, 0x6A, 0xD2); | ||
175 | err += sn9c102_write_reg(cam, 0x50, 0xD3); | ||
176 | err += sn9c102_write_reg(cam, 0x00, 0xD4); | ||
177 | err += sn9c102_write_reg(cam, 0x00, 0xD5); | ||
178 | err += sn9c102_write_reg(cam, 0x00, 0xD6); | ||
179 | |||
180 | err += sn9c102_i2c_write(cam, 0x12, 0x80); | ||
181 | err += sn9c102_i2c_write(cam, 0x11, 0x09); | ||
182 | err += sn9c102_i2c_write(cam, 0x00, 0x0A); | ||
183 | err += sn9c102_i2c_write(cam, 0x01, 0x78); | ||
184 | err += sn9c102_i2c_write(cam, 0x02, 0x90); | ||
185 | err += sn9c102_i2c_write(cam, 0x03, 0x00); | ||
186 | err += sn9c102_i2c_write(cam, 0x04, 0x00); | ||
187 | err += sn9c102_i2c_write(cam, 0x05, 0x08); | ||
188 | err += sn9c102_i2c_write(cam, 0x06, 0x0B); | ||
189 | err += sn9c102_i2c_write(cam, 0x07, 0x00); | ||
190 | err += sn9c102_i2c_write(cam, 0x08, 0x1C); | ||
191 | err += sn9c102_i2c_write(cam, 0x09, 0x01); | ||
192 | err += sn9c102_i2c_write(cam, 0x0A, 0x76); | ||
193 | err += sn9c102_i2c_write(cam, 0x0B, 0x60); | ||
194 | err += sn9c102_i2c_write(cam, 0x0C, 0x00); | ||
195 | err += sn9c102_i2c_write(cam, 0x0D, 0x08); | ||
196 | err += sn9c102_i2c_write(cam, 0x0E, 0x04); | ||
197 | err += sn9c102_i2c_write(cam, 0x0F, 0x6F); | ||
198 | err += sn9c102_i2c_write(cam, 0x10, 0x20); | ||
199 | err += sn9c102_i2c_write(cam, 0x11, 0x03); | ||
200 | err += sn9c102_i2c_write(cam, 0x12, 0x05); | ||
201 | err += sn9c102_i2c_write(cam, 0x13, 0xF8); | ||
202 | err += sn9c102_i2c_write(cam, 0x14, 0x2C); | ||
203 | err += sn9c102_i2c_write(cam, 0x15, 0x00); | ||
204 | err += sn9c102_i2c_write(cam, 0x16, 0x02); | ||
205 | err += sn9c102_i2c_write(cam, 0x17, 0x10); | ||
206 | err += sn9c102_i2c_write(cam, 0x18, 0x60); | ||
207 | err += sn9c102_i2c_write(cam, 0x19, 0x02); | ||
208 | err += sn9c102_i2c_write(cam, 0x1A, 0x7B); | ||
209 | err += sn9c102_i2c_write(cam, 0x1B, 0x02); | ||
210 | err += sn9c102_i2c_write(cam, 0x1C, 0x7F); | ||
211 | err += sn9c102_i2c_write(cam, 0x1D, 0xA2); | ||
212 | err += sn9c102_i2c_write(cam, 0x1E, 0x01); | ||
213 | err += sn9c102_i2c_write(cam, 0x1F, 0x0E); | ||
214 | err += sn9c102_i2c_write(cam, 0x20, 0x05); | ||
215 | err += sn9c102_i2c_write(cam, 0x21, 0x05); | ||
216 | err += sn9c102_i2c_write(cam, 0x22, 0x05); | ||
217 | err += sn9c102_i2c_write(cam, 0x23, 0x05); | ||
218 | err += sn9c102_i2c_write(cam, 0x24, 0x68); | ||
219 | err += sn9c102_i2c_write(cam, 0x25, 0x58); | ||
220 | err += sn9c102_i2c_write(cam, 0x26, 0xD4); | ||
221 | err += sn9c102_i2c_write(cam, 0x27, 0x80); | ||
222 | err += sn9c102_i2c_write(cam, 0x28, 0x80); | ||
223 | err += sn9c102_i2c_write(cam, 0x29, 0x30); | ||
224 | err += sn9c102_i2c_write(cam, 0x2A, 0x00); | ||
225 | err += sn9c102_i2c_write(cam, 0x2B, 0x00); | ||
226 | err += sn9c102_i2c_write(cam, 0x2C, 0x80); | ||
227 | err += sn9c102_i2c_write(cam, 0x2D, 0x00); | ||
228 | err += sn9c102_i2c_write(cam, 0x2E, 0x00); | ||
229 | err += sn9c102_i2c_write(cam, 0x2F, 0x0E); | ||
230 | err += sn9c102_i2c_write(cam, 0x30, 0x08); | ||
231 | err += sn9c102_i2c_write(cam, 0x31, 0x30); | ||
232 | err += sn9c102_i2c_write(cam, 0x32, 0xB4); | ||
233 | err += sn9c102_i2c_write(cam, 0x33, 0x00); | ||
234 | err += sn9c102_i2c_write(cam, 0x34, 0x07); | ||
235 | err += sn9c102_i2c_write(cam, 0x35, 0x84); | ||
236 | err += sn9c102_i2c_write(cam, 0x36, 0x00); | ||
237 | err += sn9c102_i2c_write(cam, 0x37, 0x0C); | ||
238 | err += sn9c102_i2c_write(cam, 0x38, 0x02); | ||
239 | err += sn9c102_i2c_write(cam, 0x39, 0x43); | ||
240 | err += sn9c102_i2c_write(cam, 0x3A, 0x00); | ||
241 | err += sn9c102_i2c_write(cam, 0x3B, 0x02); | ||
242 | err += sn9c102_i2c_write(cam, 0x3C, 0x6C); | ||
243 | err += sn9c102_i2c_write(cam, 0x3D, 0x99); | ||
244 | err += sn9c102_i2c_write(cam, 0x3E, 0x0E); | ||
245 | err += sn9c102_i2c_write(cam, 0x3F, 0x41); | ||
246 | err += sn9c102_i2c_write(cam, 0x40, 0xC1); | ||
247 | err += sn9c102_i2c_write(cam, 0x41, 0x22); | ||
248 | err += sn9c102_i2c_write(cam, 0x42, 0x08); | ||
249 | err += sn9c102_i2c_write(cam, 0x43, 0xF0); | ||
250 | err += sn9c102_i2c_write(cam, 0x44, 0x10); | ||
251 | err += sn9c102_i2c_write(cam, 0x45, 0x78); | ||
252 | err += sn9c102_i2c_write(cam, 0x46, 0xA8); | ||
253 | err += sn9c102_i2c_write(cam, 0x47, 0x60); | ||
254 | err += sn9c102_i2c_write(cam, 0x48, 0x80); | ||
255 | err += sn9c102_i2c_write(cam, 0x49, 0x00); | ||
256 | err += sn9c102_i2c_write(cam, 0x4A, 0x00); | ||
257 | err += sn9c102_i2c_write(cam, 0x4B, 0x00); | ||
258 | err += sn9c102_i2c_write(cam, 0x4C, 0x00); | ||
259 | err += sn9c102_i2c_write(cam, 0x4D, 0x00); | ||
260 | err += sn9c102_i2c_write(cam, 0x4E, 0x00); | ||
261 | err += sn9c102_i2c_write(cam, 0x4F, 0x46); | ||
262 | err += sn9c102_i2c_write(cam, 0x50, 0x36); | ||
263 | err += sn9c102_i2c_write(cam, 0x51, 0x0F); | ||
264 | err += sn9c102_i2c_write(cam, 0x52, 0x17); | ||
265 | err += sn9c102_i2c_write(cam, 0x53, 0x7F); | ||
266 | err += sn9c102_i2c_write(cam, 0x54, 0x96); | ||
267 | err += sn9c102_i2c_write(cam, 0x55, 0x40); | ||
268 | err += sn9c102_i2c_write(cam, 0x56, 0x40); | ||
269 | err += sn9c102_i2c_write(cam, 0x57, 0x40); | ||
270 | err += sn9c102_i2c_write(cam, 0x58, 0x0F); | ||
271 | err += sn9c102_i2c_write(cam, 0x59, 0xBA); | ||
272 | err += sn9c102_i2c_write(cam, 0x5A, 0x9A); | ||
273 | err += sn9c102_i2c_write(cam, 0x5B, 0x22); | ||
274 | err += sn9c102_i2c_write(cam, 0x5C, 0xB9); | ||
275 | err += sn9c102_i2c_write(cam, 0x5D, 0x9B); | ||
276 | err += sn9c102_i2c_write(cam, 0x5E, 0x10); | ||
277 | err += sn9c102_i2c_write(cam, 0x5F, 0xF0); | ||
278 | err += sn9c102_i2c_write(cam, 0x60, 0x05); | ||
279 | err += sn9c102_i2c_write(cam, 0x61, 0x60); | ||
280 | err += sn9c102_i2c_write(cam, 0x62, 0x00); | ||
281 | err += sn9c102_i2c_write(cam, 0x63, 0x00); | ||
282 | err += sn9c102_i2c_write(cam, 0x64, 0x50); | ||
283 | err += sn9c102_i2c_write(cam, 0x65, 0x30); | ||
284 | err += sn9c102_i2c_write(cam, 0x66, 0x00); | ||
285 | err += sn9c102_i2c_write(cam, 0x67, 0x80); | ||
286 | err += sn9c102_i2c_write(cam, 0x68, 0x7A); | ||
287 | err += sn9c102_i2c_write(cam, 0x69, 0x90); | ||
288 | err += sn9c102_i2c_write(cam, 0x6A, 0x80); | ||
289 | err += sn9c102_i2c_write(cam, 0x6B, 0x0A); | ||
290 | err += sn9c102_i2c_write(cam, 0x6C, 0x30); | ||
291 | err += sn9c102_i2c_write(cam, 0x6D, 0x48); | ||
292 | err += sn9c102_i2c_write(cam, 0x6E, 0x80); | ||
293 | err += sn9c102_i2c_write(cam, 0x6F, 0x74); | ||
294 | err += sn9c102_i2c_write(cam, 0x70, 0x64); | ||
295 | err += sn9c102_i2c_write(cam, 0x71, 0x60); | ||
296 | err += sn9c102_i2c_write(cam, 0x72, 0x5C); | ||
297 | err += sn9c102_i2c_write(cam, 0x73, 0x58); | ||
298 | err += sn9c102_i2c_write(cam, 0x74, 0x54); | ||
299 | err += sn9c102_i2c_write(cam, 0x75, 0x4C); | ||
300 | err += sn9c102_i2c_write(cam, 0x76, 0x40); | ||
301 | err += sn9c102_i2c_write(cam, 0x77, 0x38); | ||
302 | err += sn9c102_i2c_write(cam, 0x78, 0x34); | ||
303 | err += sn9c102_i2c_write(cam, 0x79, 0x30); | ||
304 | err += sn9c102_i2c_write(cam, 0x7A, 0x2F); | ||
305 | err += sn9c102_i2c_write(cam, 0x7B, 0x2B); | ||
306 | err += sn9c102_i2c_write(cam, 0x7C, 0x03); | ||
307 | err += sn9c102_i2c_write(cam, 0x7D, 0x07); | ||
308 | err += sn9c102_i2c_write(cam, 0x7E, 0x17); | ||
309 | err += sn9c102_i2c_write(cam, 0x7F, 0x34); | ||
310 | err += sn9c102_i2c_write(cam, 0x80, 0x41); | ||
311 | err += sn9c102_i2c_write(cam, 0x81, 0x4D); | ||
312 | err += sn9c102_i2c_write(cam, 0x82, 0x58); | ||
313 | err += sn9c102_i2c_write(cam, 0x83, 0x63); | ||
314 | err += sn9c102_i2c_write(cam, 0x84, 0x6E); | ||
315 | err += sn9c102_i2c_write(cam, 0x85, 0x77); | ||
316 | err += sn9c102_i2c_write(cam, 0x86, 0x87); | ||
317 | err += sn9c102_i2c_write(cam, 0x87, 0x95); | ||
318 | err += sn9c102_i2c_write(cam, 0x88, 0xAF); | ||
319 | err += sn9c102_i2c_write(cam, 0x89, 0xC7); | ||
320 | err += sn9c102_i2c_write(cam, 0x8A, 0xDF); | ||
321 | err += sn9c102_i2c_write(cam, 0x8B, 0x99); | ||
322 | err += sn9c102_i2c_write(cam, 0x8C, 0x99); | ||
323 | err += sn9c102_i2c_write(cam, 0x8D, 0xCF); | ||
324 | err += sn9c102_i2c_write(cam, 0x8E, 0x20); | ||
325 | err += sn9c102_i2c_write(cam, 0x8F, 0x26); | ||
326 | err += sn9c102_i2c_write(cam, 0x90, 0x10); | ||
327 | err += sn9c102_i2c_write(cam, 0x91, 0x0C); | ||
328 | err += sn9c102_i2c_write(cam, 0x92, 0x25); | ||
329 | err += sn9c102_i2c_write(cam, 0x93, 0x00); | ||
330 | err += sn9c102_i2c_write(cam, 0x94, 0x50); | ||
331 | err += sn9c102_i2c_write(cam, 0x95, 0x50); | ||
332 | err += sn9c102_i2c_write(cam, 0x96, 0x00); | ||
333 | err += sn9c102_i2c_write(cam, 0x97, 0x01); | ||
334 | err += sn9c102_i2c_write(cam, 0x98, 0x10); | ||
335 | err += sn9c102_i2c_write(cam, 0x99, 0x40); | ||
336 | err += sn9c102_i2c_write(cam, 0x9A, 0x40); | ||
337 | err += sn9c102_i2c_write(cam, 0x9B, 0x20); | ||
338 | err += sn9c102_i2c_write(cam, 0x9C, 0x00); | ||
339 | err += sn9c102_i2c_write(cam, 0x9D, 0x99); | ||
340 | err += sn9c102_i2c_write(cam, 0x9E, 0x7F); | ||
341 | err += sn9c102_i2c_write(cam, 0x9F, 0x00); | ||
342 | err += sn9c102_i2c_write(cam, 0xA0, 0x00); | ||
343 | err += sn9c102_i2c_write(cam, 0xA1, 0x00); | ||
344 | |||
345 | return err; | ||
346 | } | ||
347 | |||
348 | |||
349 | static int ov7660_get_ctrl(struct sn9c102_device* cam, | ||
350 | struct v4l2_control* ctrl) | ||
351 | { | ||
352 | int err = 0; | ||
353 | |||
354 | switch (ctrl->id) { | ||
355 | case V4L2_CID_EXPOSURE: | ||
356 | if ((ctrl->value = sn9c102_i2c_read(cam, 0x10)) < 0) | ||
357 | return -EIO; | ||
358 | break; | ||
359 | case V4L2_CID_DO_WHITE_BALANCE: | ||
360 | ctrl->value = sn9c102_pread_reg(cam, 0x02); | ||
361 | ctrl->value = (ctrl->value & 0x04) ? 1 : 0; | ||
362 | break; | ||
363 | case V4L2_CID_RED_BALANCE: | ||
364 | ctrl->value = sn9c102_pread_reg(cam, 0x05); | ||
365 | ctrl->value &= 0x7f; | ||
366 | break; | ||
367 | case V4L2_CID_BLUE_BALANCE: | ||
368 | ctrl->value = sn9c102_pread_reg(cam, 0x06); | ||
369 | ctrl->value &= 0x7f; | ||
370 | break; | ||
371 | case SN9C102_V4L2_CID_GREEN_BALANCE: | ||
372 | ctrl->value = sn9c102_pread_reg(cam, 0x07); | ||
373 | ctrl->value &= 0x7f; | ||
374 | break; | ||
375 | case V4L2_CID_GAIN: | ||
376 | if ((ctrl->value = sn9c102_i2c_read(cam, 0x00)) < 0) | ||
377 | return -EIO; | ||
378 | ctrl->value &= 0x7f; | ||
379 | break; | ||
380 | case V4L2_CID_AUTOGAIN: | ||
381 | if ((ctrl->value = sn9c102_i2c_read(cam, 0x13)) < 0) | ||
382 | return -EIO; | ||
383 | ctrl->value &= 0x01; | ||
384 | break; | ||
385 | default: | ||
386 | return -EINVAL; | ||
387 | } | ||
388 | |||
389 | return err ? -EIO : 0; | ||
390 | } | ||
391 | |||
392 | |||
393 | static int ov7660_set_ctrl(struct sn9c102_device* cam, | ||
394 | const struct v4l2_control* ctrl) | ||
395 | { | ||
396 | int err = 0; | ||
397 | |||
398 | switch (ctrl->id) { | ||
399 | case V4L2_CID_EXPOSURE: | ||
400 | err += sn9c102_i2c_write(cam, 0x10, ctrl->value); | ||
401 | break; | ||
402 | case V4L2_CID_DO_WHITE_BALANCE: | ||
403 | err += sn9c102_write_reg(cam, 0x43 | (ctrl->value << 2), 0x02); | ||
404 | break; | ||
405 | case V4L2_CID_RED_BALANCE: | ||
406 | err += sn9c102_write_reg(cam, ctrl->value, 0x05); | ||
407 | break; | ||
408 | case V4L2_CID_BLUE_BALANCE: | ||
409 | err += sn9c102_write_reg(cam, ctrl->value, 0x06); | ||
410 | break; | ||
411 | case SN9C102_V4L2_CID_GREEN_BALANCE: | ||
412 | err += sn9c102_write_reg(cam, ctrl->value, 0x07); | ||
413 | break; | ||
414 | case V4L2_CID_GAIN: | ||
415 | err += sn9c102_i2c_write(cam, 0x00, ctrl->value); | ||
416 | break; | ||
417 | case V4L2_CID_AUTOGAIN: | ||
418 | err += sn9c102_i2c_write(cam, 0x13, 0xf0 | ctrl->value | | ||
419 | (ctrl->value << 1)); | ||
420 | break; | ||
421 | default: | ||
422 | return -EINVAL; | ||
423 | } | ||
424 | |||
425 | return err ? -EIO : 0; | ||
426 | } | ||
427 | |||
428 | |||
429 | static int ov7660_set_crop(struct sn9c102_device* cam, | ||
430 | const struct v4l2_rect* rect) | ||
431 | { | ||
432 | struct sn9c102_sensor* s = sn9c102_get_sensor(cam); | ||
433 | int err = 0; | ||
434 | u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 1, | ||
435 | v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1; | ||
436 | |||
437 | err += sn9c102_write_reg(cam, h_start, 0x12); | ||
438 | err += sn9c102_write_reg(cam, v_start, 0x13); | ||
439 | |||
440 | return err; | ||
441 | } | ||
442 | |||
443 | |||
444 | static int ov7660_set_pix_format(struct sn9c102_device* cam, | ||
445 | const struct v4l2_pix_format* pix) | ||
446 | { | ||
447 | int r0, err = 0; | ||
448 | |||
449 | r0 = sn9c102_pread_reg(cam, 0x01); | ||
450 | |||
451 | if (pix->pixelformat == V4L2_PIX_FMT_JPEG) { | ||
452 | err += sn9c102_write_reg(cam, r0 | 0x40, 0x01); | ||
453 | err += sn9c102_write_reg(cam, 0xa2, 0x17); | ||
454 | err += sn9c102_i2c_write(cam, 0x11, 0x00); | ||
455 | } else { | ||
456 | err += sn9c102_write_reg(cam, r0 | 0x40, 0x01); | ||
457 | err += sn9c102_write_reg(cam, 0xa2, 0x17); | ||
458 | err += sn9c102_i2c_write(cam, 0x11, 0x0d); | ||
459 | } | ||
460 | |||
461 | return err; | ||
462 | } | ||
463 | |||
464 | |||
465 | static struct sn9c102_sensor ov7660 = { | ||
466 | .name = "OV7660", | ||
467 | .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", | ||
468 | .supported_bridge = BRIDGE_SN9C105 | BRIDGE_SN9C120, | ||
469 | .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE, | ||
470 | .frequency = SN9C102_I2C_100KHZ, | ||
471 | .interface = SN9C102_I2C_2WIRES, | ||
472 | .i2c_slave_id = 0x21, | ||
473 | .init = &ov7660_init, | ||
474 | .qctrl = { | ||
475 | { | ||
476 | .id = V4L2_CID_GAIN, | ||
477 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
478 | .name = "global gain", | ||
479 | .minimum = 0x00, | ||
480 | .maximum = 0x7f, | ||
481 | .step = 0x01, | ||
482 | .default_value = 0x0a, | ||
483 | .flags = 0, | ||
484 | }, | ||
485 | { | ||
486 | .id = V4L2_CID_EXPOSURE, | ||
487 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
488 | .name = "exposure", | ||
489 | .minimum = 0x00, | ||
490 | .maximum = 0xff, | ||
491 | .step = 0x01, | ||
492 | .default_value = 0x50, | ||
493 | .flags = 0, | ||
494 | }, | ||
495 | { | ||
496 | .id = V4L2_CID_DO_WHITE_BALANCE, | ||
497 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
498 | .name = "night mode", | ||
499 | .minimum = 0x00, | ||
500 | .maximum = 0x01, | ||
501 | .step = 0x01, | ||
502 | .default_value = 0x00, | ||
503 | .flags = 0, | ||
504 | }, | ||
505 | { | ||
506 | .id = V4L2_CID_RED_BALANCE, | ||
507 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
508 | .name = "red balance", | ||
509 | .minimum = 0x00, | ||
510 | .maximum = 0x7f, | ||
511 | .step = 0x01, | ||
512 | .default_value = 0x1f, | ||
513 | .flags = 0, | ||
514 | }, | ||
515 | { | ||
516 | .id = V4L2_CID_BLUE_BALANCE, | ||
517 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
518 | .name = "blue balance", | ||
519 | .minimum = 0x00, | ||
520 | .maximum = 0x7f, | ||
521 | .step = 0x01, | ||
522 | .default_value = 0x1e, | ||
523 | .flags = 0, | ||
524 | }, | ||
525 | { | ||
526 | .id = V4L2_CID_AUTOGAIN, | ||
527 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
528 | .name = "auto adjust", | ||
529 | .minimum = 0x00, | ||
530 | .maximum = 0x01, | ||
531 | .step = 0x01, | ||
532 | .default_value = 0x00, | ||
533 | .flags = 0, | ||
534 | }, | ||
535 | { | ||
536 | .id = SN9C102_V4L2_CID_GREEN_BALANCE, | ||
537 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
538 | .name = "green balance", | ||
539 | .minimum = 0x00, | ||
540 | .maximum = 0x7f, | ||
541 | .step = 0x01, | ||
542 | .default_value = 0x20, | ||
543 | .flags = 0, | ||
544 | }, | ||
545 | }, | ||
546 | .get_ctrl = &ov7660_get_ctrl, | ||
547 | .set_ctrl = &ov7660_set_ctrl, | ||
548 | .cropcap = { | ||
549 | .bounds = { | ||
550 | .left = 0, | ||
551 | .top = 0, | ||
552 | .width = 640, | ||
553 | .height = 480, | ||
554 | }, | ||
555 | .defrect = { | ||
556 | .left = 0, | ||
557 | .top = 0, | ||
558 | .width = 640, | ||
559 | .height = 480, | ||
560 | }, | ||
561 | }, | ||
562 | .set_crop = &ov7660_set_crop, | ||
563 | .pix_format = { | ||
564 | .width = 640, | ||
565 | .height = 480, | ||
566 | .pixelformat = V4L2_PIX_FMT_JPEG, | ||
567 | .priv = 8, | ||
568 | }, | ||
569 | .set_pix_format = &ov7660_set_pix_format | ||
570 | }; | ||
571 | |||
572 | |||
573 | int sn9c102_probe_ov7660(struct sn9c102_device* cam) | ||
574 | { | ||
575 | int pid, ver, err = 0; | ||
576 | |||
577 | err += sn9c102_write_reg(cam, 0x01, 0xf1); | ||
578 | err += sn9c102_write_reg(cam, 0x00, 0xf1); | ||
579 | err += sn9c102_write_reg(cam, 0x01, 0x01); | ||
580 | err += sn9c102_write_reg(cam, 0x00, 0x01); | ||
581 | err += sn9c102_write_reg(cam, 0x28, 0x17); | ||
582 | |||
583 | pid = sn9c102_i2c_try_read(cam, &ov7660, 0x0a); | ||
584 | ver = sn9c102_i2c_try_read(cam, &ov7660, 0x0b); | ||
585 | if (err || pid < 0 || ver < 0) | ||
586 | return -EIO; | ||
587 | if (pid != 0x76 || ver != 0x60) | ||
588 | return -ENODEV; | ||
589 | sn9c102_attach_sensor(cam, &ov7660); | ||
590 | |||
591 | return 0; | ||
592 | } | ||
diff --git a/drivers/media/video/sn9c102/sn9c102_pas106b.c b/drivers/media/video/sn9c102/sn9c102_pas106b.c index 9915944235e8..8d79a5fae5de 100644 --- a/drivers/media/video/sn9c102/sn9c102_pas106b.c +++ b/drivers/media/video/sn9c102/sn9c102_pas106b.c | |||
@@ -1,8 +1,8 @@ | |||
1 | /*************************************************************************** | 1 | /*************************************************************************** |
2 | * Plug-in for PAS106B image sensor connected to the SN9C10x PC Camera * | 2 | * Plug-in for PAS106B image sensor connected to the SN9C1xx PC Camera * |
3 | * Controllers * | 3 | * Controllers * |
4 | * * | 4 | * * |
5 | * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it> * | 5 | * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it> * |
6 | * * | 6 | * * |
7 | * This program is free software; you can redistribute it and/or modify * | 7 | * This program is free software; you can redistribute it and/or modify * |
8 | * it under the terms of the GNU General Public License as published by * | 8 | * it under the terms of the GNU General Public License as published by * |
@@ -143,7 +143,7 @@ static int pas106b_set_ctrl(struct sn9c102_device* cam, | |||
143 | static int pas106b_set_crop(struct sn9c102_device* cam, | 143 | static int pas106b_set_crop(struct sn9c102_device* cam, |
144 | const struct v4l2_rect* rect) | 144 | const struct v4l2_rect* rect) |
145 | { | 145 | { |
146 | struct sn9c102_sensor* s = &pas106b; | 146 | struct sn9c102_sensor* s = sn9c102_get_sensor(cam); |
147 | int err = 0; | 147 | int err = 0; |
148 | u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 4, | 148 | u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 4, |
149 | v_start = (u8)(rect->top - s->cropcap.bounds.top) + 3; | 149 | v_start = (u8)(rect->top - s->cropcap.bounds.top) + 3; |
@@ -172,6 +172,7 @@ static int pas106b_set_pix_format(struct sn9c102_device* cam, | |||
172 | static struct sn9c102_sensor pas106b = { | 172 | static struct sn9c102_sensor pas106b = { |
173 | .name = "PAS106B", | 173 | .name = "PAS106B", |
174 | .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", | 174 | .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", |
175 | .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103, | ||
175 | .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE, | 176 | .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE, |
176 | .frequency = SN9C102_I2C_400KHZ | SN9C102_I2C_100KHZ, | 177 | .frequency = SN9C102_I2C_400KHZ | SN9C102_I2C_100KHZ, |
177 | .interface = SN9C102_I2C_2WIRES, | 178 | .interface = SN9C102_I2C_2WIRES, |
diff --git a/drivers/media/video/sn9c102/sn9c102_pas202bca.c b/drivers/media/video/sn9c102/sn9c102_pas202bca.c deleted file mode 100644 index c8f1ae2152b8..000000000000 --- a/drivers/media/video/sn9c102/sn9c102_pas202bca.c +++ /dev/null | |||
@@ -1,238 +0,0 @@ | |||
1 | /*************************************************************************** | ||
2 | * Plug-in for PAS202BCA image sensor connected to the SN9C10x PC Camera * | ||
3 | * Controllers * | ||
4 | * * | ||
5 | * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it> * | ||
6 | * * | ||
7 | * This program is free software; you can redistribute it and/or modify * | ||
8 | * it under the terms of the GNU General Public License as published by * | ||
9 | * the Free Software Foundation; either version 2 of the License, or * | ||
10 | * (at your option) any later version. * | ||
11 | * * | ||
12 | * This program is distributed in the hope that it will be useful, * | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | ||
15 | * GNU General Public License for more details. * | ||
16 | * * | ||
17 | * You should have received a copy of the GNU General Public License * | ||
18 | * along with this program; if not, write to the Free Software * | ||
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * | ||
20 | ***************************************************************************/ | ||
21 | |||
22 | #include <linux/delay.h> | ||
23 | #include "sn9c102_sensor.h" | ||
24 | |||
25 | |||
26 | static struct sn9c102_sensor pas202bca; | ||
27 | |||
28 | |||
29 | static int pas202bca_init(struct sn9c102_device* cam) | ||
30 | { | ||
31 | int err = 0; | ||
32 | |||
33 | err += sn9c102_write_reg(cam, 0x00, 0x10); | ||
34 | err += sn9c102_write_reg(cam, 0x00, 0x11); | ||
35 | err += sn9c102_write_reg(cam, 0x00, 0x14); | ||
36 | err += sn9c102_write_reg(cam, 0x20, 0x17); | ||
37 | err += sn9c102_write_reg(cam, 0x30, 0x19); | ||
38 | err += sn9c102_write_reg(cam, 0x09, 0x18); | ||
39 | |||
40 | err += sn9c102_i2c_write(cam, 0x02, 0x14); | ||
41 | err += sn9c102_i2c_write(cam, 0x03, 0x40); | ||
42 | err += sn9c102_i2c_write(cam, 0x0d, 0x2c); | ||
43 | err += sn9c102_i2c_write(cam, 0x0e, 0x01); | ||
44 | err += sn9c102_i2c_write(cam, 0x0f, 0xa9); | ||
45 | err += sn9c102_i2c_write(cam, 0x10, 0x08); | ||
46 | err += sn9c102_i2c_write(cam, 0x13, 0x63); | ||
47 | err += sn9c102_i2c_write(cam, 0x15, 0x70); | ||
48 | err += sn9c102_i2c_write(cam, 0x11, 0x01); | ||
49 | |||
50 | msleep(400); | ||
51 | |||
52 | return err; | ||
53 | } | ||
54 | |||
55 | |||
56 | static int pas202bca_set_pix_format(struct sn9c102_device* cam, | ||
57 | const struct v4l2_pix_format* pix) | ||
58 | { | ||
59 | int err = 0; | ||
60 | |||
61 | if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) | ||
62 | err += sn9c102_write_reg(cam, 0x24, 0x17); | ||
63 | else | ||
64 | err += sn9c102_write_reg(cam, 0x20, 0x17); | ||
65 | |||
66 | return err; | ||
67 | } | ||
68 | |||
69 | |||
70 | static int pas202bca_set_ctrl(struct sn9c102_device* cam, | ||
71 | const struct v4l2_control* ctrl) | ||
72 | { | ||
73 | int err = 0; | ||
74 | |||
75 | switch (ctrl->id) { | ||
76 | case V4L2_CID_EXPOSURE: | ||
77 | err += sn9c102_i2c_write(cam, 0x04, ctrl->value >> 6); | ||
78 | err += sn9c102_i2c_write(cam, 0x05, ctrl->value & 0x3f); | ||
79 | break; | ||
80 | case V4L2_CID_RED_BALANCE: | ||
81 | err += sn9c102_i2c_write(cam, 0x09, ctrl->value); | ||
82 | break; | ||
83 | case V4L2_CID_BLUE_BALANCE: | ||
84 | err += sn9c102_i2c_write(cam, 0x07, ctrl->value); | ||
85 | break; | ||
86 | case V4L2_CID_GAIN: | ||
87 | err += sn9c102_i2c_write(cam, 0x10, ctrl->value); | ||
88 | break; | ||
89 | case SN9C102_V4L2_CID_GREEN_BALANCE: | ||
90 | err += sn9c102_i2c_write(cam, 0x08, ctrl->value); | ||
91 | break; | ||
92 | case SN9C102_V4L2_CID_DAC_MAGNITUDE: | ||
93 | err += sn9c102_i2c_write(cam, 0x0c, ctrl->value); | ||
94 | break; | ||
95 | default: | ||
96 | return -EINVAL; | ||
97 | } | ||
98 | err += sn9c102_i2c_write(cam, 0x11, 0x01); | ||
99 | |||
100 | return err ? -EIO : 0; | ||
101 | } | ||
102 | |||
103 | |||
104 | static int pas202bca_set_crop(struct sn9c102_device* cam, | ||
105 | const struct v4l2_rect* rect) | ||
106 | { | ||
107 | struct sn9c102_sensor* s = &pas202bca; | ||
108 | int err = 0; | ||
109 | u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 3, | ||
110 | v_start = (u8)(rect->top - s->cropcap.bounds.top) + 3; | ||
111 | |||
112 | err += sn9c102_write_reg(cam, h_start, 0x12); | ||
113 | err += sn9c102_write_reg(cam, v_start, 0x13); | ||
114 | |||
115 | return err; | ||
116 | } | ||
117 | |||
118 | |||
119 | static struct sn9c102_sensor pas202bca = { | ||
120 | .name = "PAS202BCA", | ||
121 | .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", | ||
122 | .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE, | ||
123 | .frequency = SN9C102_I2C_400KHZ | SN9C102_I2C_100KHZ, | ||
124 | .interface = SN9C102_I2C_2WIRES, | ||
125 | .i2c_slave_id = 0x40, | ||
126 | .init = &pas202bca_init, | ||
127 | .qctrl = { | ||
128 | { | ||
129 | .id = V4L2_CID_EXPOSURE, | ||
130 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
131 | .name = "exposure", | ||
132 | .minimum = 0x01e5, | ||
133 | .maximum = 0x3fff, | ||
134 | .step = 0x0001, | ||
135 | .default_value = 0x01e5, | ||
136 | .flags = 0, | ||
137 | }, | ||
138 | { | ||
139 | .id = V4L2_CID_GAIN, | ||
140 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
141 | .name = "global gain", | ||
142 | .minimum = 0x00, | ||
143 | .maximum = 0x1f, | ||
144 | .step = 0x01, | ||
145 | .default_value = 0x0c, | ||
146 | .flags = 0, | ||
147 | }, | ||
148 | { | ||
149 | .id = V4L2_CID_RED_BALANCE, | ||
150 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
151 | .name = "red balance", | ||
152 | .minimum = 0x00, | ||
153 | .maximum = 0x0f, | ||
154 | .step = 0x01, | ||
155 | .default_value = 0x01, | ||
156 | .flags = 0, | ||
157 | }, | ||
158 | { | ||
159 | .id = V4L2_CID_BLUE_BALANCE, | ||
160 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
161 | .name = "blue balance", | ||
162 | .minimum = 0x00, | ||
163 | .maximum = 0x0f, | ||
164 | .step = 0x01, | ||
165 | .default_value = 0x05, | ||
166 | .flags = 0, | ||
167 | }, | ||
168 | { | ||
169 | .id = SN9C102_V4L2_CID_GREEN_BALANCE, | ||
170 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
171 | .name = "green balance", | ||
172 | .minimum = 0x00, | ||
173 | .maximum = 0x0f, | ||
174 | .step = 0x01, | ||
175 | .default_value = 0x00, | ||
176 | .flags = 0, | ||
177 | }, | ||
178 | { | ||
179 | .id = SN9C102_V4L2_CID_DAC_MAGNITUDE, | ||
180 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
181 | .name = "DAC magnitude", | ||
182 | .minimum = 0x00, | ||
183 | .maximum = 0xff, | ||
184 | .step = 0x01, | ||
185 | .default_value = 0x04, | ||
186 | .flags = 0, | ||
187 | }, | ||
188 | }, | ||
189 | .set_ctrl = &pas202bca_set_ctrl, | ||
190 | .cropcap = { | ||
191 | .bounds = { | ||
192 | .left = 0, | ||
193 | .top = 0, | ||
194 | .width = 640, | ||
195 | .height = 480, | ||
196 | }, | ||
197 | .defrect = { | ||
198 | .left = 0, | ||
199 | .top = 0, | ||
200 | .width = 640, | ||
201 | .height = 480, | ||
202 | }, | ||
203 | }, | ||
204 | .set_crop = &pas202bca_set_crop, | ||
205 | .pix_format = { | ||
206 | .width = 640, | ||
207 | .height = 480, | ||
208 | .pixelformat = V4L2_PIX_FMT_SBGGR8, | ||
209 | .priv = 8, | ||
210 | }, | ||
211 | .set_pix_format = &pas202bca_set_pix_format | ||
212 | }; | ||
213 | |||
214 | |||
215 | int sn9c102_probe_pas202bca(struct sn9c102_device* cam) | ||
216 | { | ||
217 | const struct usb_device_id pas202bca_id_table[] = { | ||
218 | { USB_DEVICE(0x0c45, 0x60af), }, | ||
219 | { } | ||
220 | }; | ||
221 | int err = 0; | ||
222 | |||
223 | if (!sn9c102_match_id(cam,pas202bca_id_table)) | ||
224 | return -ENODEV; | ||
225 | |||
226 | err += sn9c102_write_reg(cam, 0x01, 0x01); | ||
227 | err += sn9c102_write_reg(cam, 0x40, 0x01); | ||
228 | err += sn9c102_write_reg(cam, 0x28, 0x17); | ||
229 | if (err) | ||
230 | return -EIO; | ||
231 | |||
232 | if (sn9c102_i2c_try_write(cam, &pas202bca, 0x10, 0)) /* try to write */ | ||
233 | return -ENODEV; | ||
234 | |||
235 | sn9c102_attach_sensor(cam, &pas202bca); | ||
236 | |||
237 | return 0; | ||
238 | } | ||
diff --git a/drivers/media/video/sn9c102/sn9c102_pas202bcb.c b/drivers/media/video/sn9c102/sn9c102_pas202bcb.c index e3c1178e339c..7894f01b56e8 100644 --- a/drivers/media/video/sn9c102/sn9c102_pas202bcb.c +++ b/drivers/media/video/sn9c102/sn9c102_pas202bcb.c | |||
@@ -1,13 +1,13 @@ | |||
1 | /*************************************************************************** | 1 | /*************************************************************************** |
2 | * Plug-in for PAS202BCB image sensor connected to the SN9C10x PC Camera * | 2 | * Plug-in for PAS202BCB image sensor connected to the SN9C1xx PC Camera * |
3 | * Controllers * | 3 | * Controllers * |
4 | * * | 4 | * * |
5 | * Copyright (C) 2004 by Carlos Eduardo Medaglia Dyonisio * | 5 | * Copyright (C) 2004 by Carlos Eduardo Medaglia Dyonisio * |
6 | * <medaglia@undl.org.br> * | 6 | * <medaglia@undl.org.br> * |
7 | * http://cadu.homelinux.com:8080/ * | 7 | * http://cadu.homelinux.com:8080/ * |
8 | * * | 8 | * * |
9 | * DAC Magnitude, exposure and green gain controls added by * | 9 | * Support for SN9C103, DAC Magnitude, exposure and green gain controls * |
10 | * Luca Risolia <luca.risolia@studio.unibo.it> * | 10 | * added by Luca Risolia <luca.risolia@studio.unibo.it> * |
11 | * * | 11 | * * |
12 | * This program is free software; you can redistribute it and/or modify * | 12 | * This program is free software; you can redistribute it and/or modify * |
13 | * it under the terms of the GNU General Public License as published by * | 13 | * it under the terms of the GNU General Public License as published by * |
@@ -35,12 +35,54 @@ static int pas202bcb_init(struct sn9c102_device* cam) | |||
35 | { | 35 | { |
36 | int err = 0; | 36 | int err = 0; |
37 | 37 | ||
38 | switch (sn9c102_get_bridge(cam)) { | ||
39 | case BRIDGE_SN9C101: | ||
40 | case BRIDGE_SN9C102: | ||
38 | err += sn9c102_write_reg(cam, 0x00, 0x10); | 41 | err += sn9c102_write_reg(cam, 0x00, 0x10); |
39 | err += sn9c102_write_reg(cam, 0x00, 0x11); | 42 | err += sn9c102_write_reg(cam, 0x00, 0x11); |
40 | err += sn9c102_write_reg(cam, 0x00, 0x14); | 43 | err += sn9c102_write_reg(cam, 0x00, 0x14); |
41 | err += sn9c102_write_reg(cam, 0x20, 0x17); | 44 | err += sn9c102_write_reg(cam, 0x20, 0x17); |
42 | err += sn9c102_write_reg(cam, 0x30, 0x19); | 45 | err += sn9c102_write_reg(cam, 0x30, 0x19); |
43 | err += sn9c102_write_reg(cam, 0x09, 0x18); | 46 | err += sn9c102_write_reg(cam, 0x09, 0x18); |
47 | break; | ||
48 | case BRIDGE_SN9C103: | ||
49 | err += sn9c102_write_reg(cam, 0x00, 0x02); | ||
50 | err += sn9c102_write_reg(cam, 0x00, 0x03); | ||
51 | err += sn9c102_write_reg(cam, 0x1a, 0x04); | ||
52 | err += sn9c102_write_reg(cam, 0x20, 0x05); | ||
53 | err += sn9c102_write_reg(cam, 0x20, 0x06); | ||
54 | err += sn9c102_write_reg(cam, 0x20, 0x07); | ||
55 | err += sn9c102_write_reg(cam, 0x00, 0x10); | ||
56 | err += sn9c102_write_reg(cam, 0x00, 0x11); | ||
57 | err += sn9c102_write_reg(cam, 0x00, 0x14); | ||
58 | err += sn9c102_write_reg(cam, 0x20, 0x17); | ||
59 | err += sn9c102_write_reg(cam, 0x30, 0x19); | ||
60 | err += sn9c102_write_reg(cam, 0x09, 0x18); | ||
61 | err += sn9c102_write_reg(cam, 0x02, 0x1c); | ||
62 | err += sn9c102_write_reg(cam, 0x03, 0x1d); | ||
63 | err += sn9c102_write_reg(cam, 0x0f, 0x1e); | ||
64 | err += sn9c102_write_reg(cam, 0x0c, 0x1f); | ||
65 | err += sn9c102_write_reg(cam, 0x00, 0x20); | ||
66 | err += sn9c102_write_reg(cam, 0x10, 0x21); | ||
67 | err += sn9c102_write_reg(cam, 0x20, 0x22); | ||
68 | err += sn9c102_write_reg(cam, 0x30, 0x23); | ||
69 | err += sn9c102_write_reg(cam, 0x40, 0x24); | ||
70 | err += sn9c102_write_reg(cam, 0x50, 0x25); | ||
71 | err += sn9c102_write_reg(cam, 0x60, 0x26); | ||
72 | err += sn9c102_write_reg(cam, 0x70, 0x27); | ||
73 | err += sn9c102_write_reg(cam, 0x80, 0x28); | ||
74 | err += sn9c102_write_reg(cam, 0x90, 0x29); | ||
75 | err += sn9c102_write_reg(cam, 0xa0, 0x2a); | ||
76 | err += sn9c102_write_reg(cam, 0xb0, 0x2b); | ||
77 | err += sn9c102_write_reg(cam, 0xc0, 0x2c); | ||
78 | err += sn9c102_write_reg(cam, 0xd0, 0x2d); | ||
79 | err += sn9c102_write_reg(cam, 0xe0, 0x2e); | ||
80 | err += sn9c102_write_reg(cam, 0xf0, 0x2f); | ||
81 | err += sn9c102_write_reg(cam, 0xff, 0x30); | ||
82 | break; | ||
83 | default: | ||
84 | break; | ||
85 | } | ||
44 | 86 | ||
45 | err += sn9c102_i2c_write(cam, 0x02, 0x14); | 87 | err += sn9c102_i2c_write(cam, 0x02, 0x14); |
46 | err += sn9c102_i2c_write(cam, 0x03, 0x40); | 88 | err += sn9c102_i2c_write(cam, 0x03, 0x40); |
@@ -107,7 +149,7 @@ static int pas202bcb_set_pix_format(struct sn9c102_device* cam, | |||
107 | int err = 0; | 149 | int err = 0; |
108 | 150 | ||
109 | if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) | 151 | if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) |
110 | err += sn9c102_write_reg(cam, 0x24, 0x17); | 152 | err += sn9c102_write_reg(cam, 0x28, 0x17); |
111 | else | 153 | else |
112 | err += sn9c102_write_reg(cam, 0x20, 0x17); | 154 | err += sn9c102_write_reg(cam, 0x20, 0x17); |
113 | 155 | ||
@@ -152,11 +194,23 @@ static int pas202bcb_set_ctrl(struct sn9c102_device* cam, | |||
152 | static int pas202bcb_set_crop(struct sn9c102_device* cam, | 194 | static int pas202bcb_set_crop(struct sn9c102_device* cam, |
153 | const struct v4l2_rect* rect) | 195 | const struct v4l2_rect* rect) |
154 | { | 196 | { |
155 | struct sn9c102_sensor* s = &pas202bcb; | 197 | struct sn9c102_sensor* s = sn9c102_get_sensor(cam); |
156 | int err = 0; | 198 | int err = 0; |
157 | u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 4, | 199 | u8 h_start = 0, |
158 | v_start = (u8)(rect->top - s->cropcap.bounds.top) + 3; | 200 | v_start = (u8)(rect->top - s->cropcap.bounds.top) + 3; |
159 | 201 | ||
202 | switch (sn9c102_get_bridge(cam)) { | ||
203 | case BRIDGE_SN9C101: | ||
204 | case BRIDGE_SN9C102: | ||
205 | h_start = (u8)(rect->left - s->cropcap.bounds.left) + 4; | ||
206 | break; | ||
207 | case BRIDGE_SN9C103: | ||
208 | h_start = (u8)(rect->left - s->cropcap.bounds.left) + 3; | ||
209 | break; | ||
210 | default: | ||
211 | break; | ||
212 | } | ||
213 | |||
160 | err += sn9c102_write_reg(cam, h_start, 0x12); | 214 | err += sn9c102_write_reg(cam, h_start, 0x12); |
161 | err += sn9c102_write_reg(cam, v_start, 0x13); | 215 | err += sn9c102_write_reg(cam, v_start, 0x13); |
162 | 216 | ||
@@ -166,8 +220,8 @@ static int pas202bcb_set_crop(struct sn9c102_device* cam, | |||
166 | 220 | ||
167 | static struct sn9c102_sensor pas202bcb = { | 221 | static struct sn9c102_sensor pas202bcb = { |
168 | .name = "PAS202BCB", | 222 | .name = "PAS202BCB", |
169 | .maintainer = "Carlos Eduardo Medaglia Dyonisio " | 223 | .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", |
170 | "<medaglia@undl.org.br>", | 224 | .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103, |
171 | .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE, | 225 | .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE, |
172 | .frequency = SN9C102_I2C_400KHZ | SN9C102_I2C_100KHZ, | 226 | .frequency = SN9C102_I2C_400KHZ | SN9C102_I2C_100KHZ, |
173 | .interface = SN9C102_I2C_2WIRES, | 227 | .interface = SN9C102_I2C_2WIRES, |
@@ -191,7 +245,7 @@ static struct sn9c102_sensor pas202bcb = { | |||
191 | .minimum = 0x00, | 245 | .minimum = 0x00, |
192 | .maximum = 0x1f, | 246 | .maximum = 0x1f, |
193 | .step = 0x01, | 247 | .step = 0x01, |
194 | .default_value = 0x0c, | 248 | .default_value = 0x0b, |
195 | .flags = 0, | 249 | .flags = 0, |
196 | }, | 250 | }, |
197 | { | 251 | { |
@@ -201,7 +255,7 @@ static struct sn9c102_sensor pas202bcb = { | |||
201 | .minimum = 0x00, | 255 | .minimum = 0x00, |
202 | .maximum = 0x0f, | 256 | .maximum = 0x0f, |
203 | .step = 0x01, | 257 | .step = 0x01, |
204 | .default_value = 0x01, | 258 | .default_value = 0x00, |
205 | .flags = 0, | 259 | .flags = 0, |
206 | }, | 260 | }, |
207 | { | 261 | { |
@@ -271,16 +325,27 @@ int sn9c102_probe_pas202bcb(struct sn9c102_device* cam) | |||
271 | * Minimal initialization to enable the I2C communication | 325 | * Minimal initialization to enable the I2C communication |
272 | * NOTE: do NOT change the values! | 326 | * NOTE: do NOT change the values! |
273 | */ | 327 | */ |
274 | err += sn9c102_write_reg(cam, 0x01, 0x01); /* sensor power down */ | 328 | switch (sn9c102_get_bridge(cam)) { |
275 | err += sn9c102_write_reg(cam, 0x40, 0x01); /* sensor power on */ | 329 | case BRIDGE_SN9C101: |
276 | err += sn9c102_write_reg(cam, 0x28, 0x17); /* sensor clock at 24 MHz */ | 330 | case BRIDGE_SN9C102: |
277 | if (err) | 331 | err += sn9c102_write_reg(cam, 0x01, 0x01); /* power down */ |
278 | return -EIO; | 332 | err += sn9c102_write_reg(cam, 0x40, 0x01); /* power on */ |
333 | err += sn9c102_write_reg(cam, 0x28, 0x17); /* clock 24 MHz */ | ||
334 | break; | ||
335 | case BRIDGE_SN9C103: /* do _not_ change anything! */ | ||
336 | err += sn9c102_write_reg(cam, 0x09, 0x01); | ||
337 | err += sn9c102_write_reg(cam, 0x44, 0x01); | ||
338 | err += sn9c102_write_reg(cam, 0x44, 0x02); | ||
339 | err += sn9c102_write_reg(cam, 0x29, 0x17); | ||
340 | break; | ||
341 | default: | ||
342 | break; | ||
343 | } | ||
279 | 344 | ||
280 | r0 = sn9c102_i2c_try_read(cam, &pas202bcb, 0x00); | 345 | r0 = sn9c102_i2c_try_read(cam, &pas202bcb, 0x00); |
281 | r1 = sn9c102_i2c_try_read(cam, &pas202bcb, 0x01); | 346 | r1 = sn9c102_i2c_try_read(cam, &pas202bcb, 0x01); |
282 | 347 | ||
283 | if (r0 < 0 || r1 < 0) | 348 | if (err || r0 < 0 || r1 < 0) |
284 | return -EIO; | 349 | return -EIO; |
285 | 350 | ||
286 | pid = (r0 << 4) | ((r1 & 0xf0) >> 4); | 351 | pid = (r0 << 4) | ((r1 & 0xf0) >> 4); |
diff --git a/drivers/media/video/sn9c102/sn9c102_sensor.h b/drivers/media/video/sn9c102/sn9c102_sensor.h index 2a874ee6f9f5..05f2942639c3 100644 --- a/drivers/media/video/sn9c102/sn9c102_sensor.h +++ b/drivers/media/video/sn9c102/sn9c102_sensor.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /*************************************************************************** | 1 | /*************************************************************************** |
2 | * API for image sensors connected to the SN9C10x PC Camera Controllers * | 2 | * API for image sensors connected to the SN9C1xx PC Camera Controllers * |
3 | * * | 3 | * * |
4 | * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it> * | 4 | * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it> * |
5 | * * | 5 | * * |
6 | * This program is free software; you can redistribute it and/or modify * | 6 | * This program is free software; you can redistribute it and/or modify * |
7 | * it under the terms of the GNU General Public License as published by * | 7 | * it under the terms of the GNU General Public License as published by * |
@@ -36,14 +36,13 @@ struct sn9c102_sensor; | |||
36 | /* | 36 | /* |
37 | OVERVIEW. | 37 | OVERVIEW. |
38 | This is a small interface that allows you to add support for any CCD/CMOS | 38 | This is a small interface that allows you to add support for any CCD/CMOS |
39 | image sensors connected to the SN9C10X bridges. The entire API is documented | 39 | image sensors connected to the SN9C1XX bridges. The entire API is documented |
40 | below. In the most general case, to support a sensor there are three steps | 40 | below. In the most general case, to support a sensor there are three steps |
41 | you have to follow: | 41 | you have to follow: |
42 | 1) define the main "sn9c102_sensor" structure by setting the basic fields; | 42 | 1) define the main "sn9c102_sensor" structure by setting the basic fields; |
43 | 2) write a probing function to be called by the core module when the USB | 43 | 2) write a probing function to be called by the core module when the USB |
44 | camera is recognized, then add both the USB ids and the name of that | 44 | camera is recognized, then add both the USB ids and the name of that |
45 | function to the two corresponding tables SENSOR_TABLE and ID_TABLE (see | 45 | function to the two corresponding tables in sn9c102_devtable.h; |
46 | below); | ||
47 | 3) implement the methods that you want/need (and fill the rest of the main | 46 | 3) implement the methods that you want/need (and fill the rest of the main |
48 | structure accordingly). | 47 | structure accordingly). |
49 | "sn9c102_pas106b.c" is an example of all this stuff. Remember that you do | 48 | "sn9c102_pas106b.c" is an example of all this stuff. Remember that you do |
@@ -54,42 +53,21 @@ struct sn9c102_sensor; | |||
54 | 53 | ||
55 | /*****************************************************************************/ | 54 | /*****************************************************************************/ |
56 | 55 | ||
57 | /* | 56 | enum sn9c102_bridge { |
58 | Probing functions: on success, you must attach the sensor to the camera | 57 | BRIDGE_SN9C101 = 0x01, |
59 | by calling sn9c102_attach_sensor() provided below. | 58 | BRIDGE_SN9C102 = 0x02, |
60 | To enable the I2C communication, you might need to perform a really basic | 59 | BRIDGE_SN9C103 = 0x04, |
61 | initialization of the SN9C10X chip by using the write function declared | 60 | BRIDGE_SN9C105 = 0x08, |
62 | ahead. | 61 | BRIDGE_SN9C120 = 0x10, |
63 | Functions must return 0 on success, the appropriate error otherwise. | ||
64 | */ | ||
65 | extern int sn9c102_probe_hv7131d(struct sn9c102_device* cam); | ||
66 | extern int sn9c102_probe_mi0343(struct sn9c102_device* cam); | ||
67 | extern int sn9c102_probe_ov7630(struct sn9c102_device* cam); | ||
68 | extern int sn9c102_probe_pas106b(struct sn9c102_device* cam); | ||
69 | extern int sn9c102_probe_pas202bca(struct sn9c102_device* cam); | ||
70 | extern int sn9c102_probe_pas202bcb(struct sn9c102_device* cam); | ||
71 | extern int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam); | ||
72 | extern int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam); | ||
73 | |||
74 | /* | ||
75 | Add the above entries to this table. Be sure to add the entry in the right | ||
76 | place, since, on failure, the next probing routine is called according to | ||
77 | the order of the list below, from top to bottom. | ||
78 | */ | ||
79 | #define SN9C102_SENSOR_TABLE \ | ||
80 | static int (*sn9c102_sensor_table[])(struct sn9c102_device*) = { \ | ||
81 | &sn9c102_probe_mi0343, /* strong detection based on SENSOR ids */ \ | ||
82 | &sn9c102_probe_pas106b, /* strong detection based on SENSOR ids */ \ | ||
83 | &sn9c102_probe_pas202bcb, /* strong detection based on SENSOR ids */ \ | ||
84 | &sn9c102_probe_hv7131d, /* strong detection based on SENSOR ids */ \ | ||
85 | &sn9c102_probe_pas202bca, /* detection mostly based on USB pid/vid */ \ | ||
86 | &sn9c102_probe_ov7630, /* detection mostly based on USB pid/vid */ \ | ||
87 | &sn9c102_probe_tas5110c1b, /* detection based on USB pid/vid */ \ | ||
88 | &sn9c102_probe_tas5130d1b, /* detection based on USB pid/vid */ \ | ||
89 | NULL, \ | ||
90 | }; | 62 | }; |
91 | 63 | ||
92 | /* Device identification */ | 64 | /* Return the bridge name */ |
65 | enum sn9c102_bridge sn9c102_get_bridge(struct sn9c102_device* cam); | ||
66 | |||
67 | /* Return a pointer the sensor struct attached to the camera */ | ||
68 | struct sn9c102_sensor* sn9c102_get_sensor(struct sn9c102_device* cam); | ||
69 | |||
70 | /* Identify a device */ | ||
93 | extern struct sn9c102_device* | 71 | extern struct sn9c102_device* |
94 | sn9c102_match_id(struct sn9c102_device* cam, const struct usb_device_id *id); | 72 | sn9c102_match_id(struct sn9c102_device* cam, const struct usb_device_id *id); |
95 | 73 | ||
@@ -99,68 +77,8 @@ sn9c102_attach_sensor(struct sn9c102_device* cam, | |||
99 | struct sn9c102_sensor* sensor); | 77 | struct sn9c102_sensor* sensor); |
100 | 78 | ||
101 | /* | 79 | /* |
102 | Each SN9C10x camera has proper PID/VID identifiers. | ||
103 | SN9C103 supports multiple interfaces, but we only handle the video class | ||
104 | interface. | ||
105 | */ | ||
106 | #define SN9C102_USB_DEVICE(vend, prod, intclass) \ | ||
107 | .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \ | ||
108 | USB_DEVICE_ID_MATCH_INT_CLASS, \ | ||
109 | .idVendor = (vend), \ | ||
110 | .idProduct = (prod), \ | ||
111 | .bInterfaceClass = (intclass) | ||
112 | |||
113 | #define SN9C102_ID_TABLE \ | ||
114 | static const struct usb_device_id sn9c102_id_table[] = { \ | ||
115 | { USB_DEVICE(0x0c45, 0x6001), }, /* TAS5110C1B */ \ | ||
116 | { USB_DEVICE(0x0c45, 0x6005), }, /* TAS5110C1B */ \ | ||
117 | { USB_DEVICE(0x0c45, 0x6007), }, \ | ||
118 | { USB_DEVICE(0x0c45, 0x6009), }, /* PAS106B */ \ | ||
119 | { USB_DEVICE(0x0c45, 0x600d), }, /* PAS106B */ \ | ||
120 | { USB_DEVICE(0x0c45, 0x6024), }, \ | ||
121 | { USB_DEVICE(0x0c45, 0x6025), }, /* TAS5130D1B and TAS5110C1B */ \ | ||
122 | { USB_DEVICE(0x0c45, 0x6028), }, /* PAS202BCB */ \ | ||
123 | { USB_DEVICE(0x0c45, 0x6029), }, /* PAS106B */ \ | ||
124 | { USB_DEVICE(0x0c45, 0x602a), }, /* HV7131D */ \ | ||
125 | { USB_DEVICE(0x0c45, 0x602b), }, /* MI-0343 */ \ | ||
126 | { USB_DEVICE(0x0c45, 0x602c), }, /* OV7630 */ \ | ||
127 | { USB_DEVICE(0x0c45, 0x602d), }, \ | ||
128 | { USB_DEVICE(0x0c45, 0x602e), }, /* OV7630 */ \ | ||
129 | { USB_DEVICE(0x0c45, 0x6030), }, /* MI03x */ \ | ||
130 | { SN9C102_USB_DEVICE(0x0c45, 0x6080, 0xff), }, \ | ||
131 | { SN9C102_USB_DEVICE(0x0c45, 0x6082, 0xff), }, /* MI0343 & MI0360 */ \ | ||
132 | { SN9C102_USB_DEVICE(0x0c45, 0x6083, 0xff), }, /* HV7131[D|E1] */ \ | ||
133 | { SN9C102_USB_DEVICE(0x0c45, 0x6088, 0xff), }, \ | ||
134 | { SN9C102_USB_DEVICE(0x0c45, 0x608a, 0xff), }, \ | ||
135 | { SN9C102_USB_DEVICE(0x0c45, 0x608b, 0xff), }, \ | ||
136 | { SN9C102_USB_DEVICE(0x0c45, 0x608c, 0xff), }, /* HV7131/R */ \ | ||
137 | { SN9C102_USB_DEVICE(0x0c45, 0x608e, 0xff), }, /* CIS-VF10 */ \ | ||
138 | { SN9C102_USB_DEVICE(0x0c45, 0x608f, 0xff), }, /* OV7630 */ \ | ||
139 | { SN9C102_USB_DEVICE(0x0c45, 0x60a0, 0xff), }, \ | ||
140 | { SN9C102_USB_DEVICE(0x0c45, 0x60a2, 0xff), }, \ | ||
141 | { SN9C102_USB_DEVICE(0x0c45, 0x60a3, 0xff), }, \ | ||
142 | { SN9C102_USB_DEVICE(0x0c45, 0x60a8, 0xff), }, /* PAS106B */ \ | ||
143 | { SN9C102_USB_DEVICE(0x0c45, 0x60aa, 0xff), }, /* TAS5130D1B */ \ | ||
144 | { SN9C102_USB_DEVICE(0x0c45, 0x60ab, 0xff), }, /* TAS5110C1B */ \ | ||
145 | { SN9C102_USB_DEVICE(0x0c45, 0x60ac, 0xff), }, \ | ||
146 | { SN9C102_USB_DEVICE(0x0c45, 0x60ae, 0xff), }, \ | ||
147 | { SN9C102_USB_DEVICE(0x0c45, 0x60af, 0xff), }, /* PAS202BCB */ \ | ||
148 | { SN9C102_USB_DEVICE(0x0c45, 0x60b0, 0xff), }, /* OV7630 (?) */ \ | ||
149 | { SN9C102_USB_DEVICE(0x0c45, 0x60b2, 0xff), }, \ | ||
150 | { SN9C102_USB_DEVICE(0x0c45, 0x60b3, 0xff), }, \ | ||
151 | { SN9C102_USB_DEVICE(0x0c45, 0x60b8, 0xff), }, \ | ||
152 | { SN9C102_USB_DEVICE(0x0c45, 0x60ba, 0xff), }, \ | ||
153 | { SN9C102_USB_DEVICE(0x0c45, 0x60bb, 0xff), }, \ | ||
154 | { SN9C102_USB_DEVICE(0x0c45, 0x60bc, 0xff), }, \ | ||
155 | { SN9C102_USB_DEVICE(0x0c45, 0x60be, 0xff), }, \ | ||
156 | { } \ | ||
157 | }; | ||
158 | |||
159 | /*****************************************************************************/ | ||
160 | |||
161 | /* | ||
162 | Read/write routines: they always return -1 on error, 0 or the read value | 80 | Read/write routines: they always return -1 on error, 0 or the read value |
163 | otherwise. NOTE that a real read operation is not supported by the SN9C10X | 81 | otherwise. NOTE that a real read operation is not supported by the SN9C1XX |
164 | chip for some of its registers. To work around this problem, a pseudo-read | 82 | chip for some of its registers. To work around this problem, a pseudo-read |
165 | call is provided instead: it returns the last successfully written value | 83 | call is provided instead: it returns the last successfully written value |
166 | on the register (0 if it has never been written), the usual -1 on error. | 84 | on the register (0 if it has never been written), the usual -1 on error. |
@@ -176,7 +94,7 @@ extern int sn9c102_i2c_try_read(struct sn9c102_device*,struct sn9c102_sensor*, | |||
176 | These must be used if and only if the sensor doesn't implement the standard | 94 | These must be used if and only if the sensor doesn't implement the standard |
177 | I2C protocol. There are a number of good reasons why you must use the | 95 | I2C protocol. There are a number of good reasons why you must use the |
178 | single-byte versions of these functions: do not abuse. The first function | 96 | single-byte versions of these functions: do not abuse. The first function |
179 | writes n bytes, from data0 to datan, to registers 0x09 - 0x09+n of SN9C10X | 97 | writes n bytes, from data0 to datan, to registers 0x09 - 0x09+n of SN9C1XX |
180 | chip. The second one programs the registers 0x09 and 0x10 with data0 and | 98 | chip. The second one programs the registers 0x09 and 0x10 with data0 and |
181 | data1, and places the n bytes read from the sensor register table in the | 99 | data1, and places the n bytes read from the sensor register table in the |
182 | buffer pointed by 'buffer'. Both the functions return -1 on error; the write | 100 | buffer pointed by 'buffer'. Both the functions return -1 on error; the write |
@@ -200,16 +118,6 @@ extern int sn9c102_write_regs(struct sn9c102_device*, u8* buff, u16 index); | |||
200 | extern int sn9c102_write_reg(struct sn9c102_device*, u8 value, u16 index); | 118 | extern int sn9c102_write_reg(struct sn9c102_device*, u8 value, u16 index); |
201 | extern int sn9c102_pread_reg(struct sn9c102_device*, u16 index); | 119 | extern int sn9c102_pread_reg(struct sn9c102_device*, u16 index); |
202 | 120 | ||
203 | /* | ||
204 | NOTE: there are no exported debugging functions. To uniform the output you | ||
205 | must use the dev_info()/dev_warn()/dev_err() macros defined in device.h, | ||
206 | already included here, the argument being the struct device '&usbdev->dev' | ||
207 | of the sensor structure. Do NOT use these macros before the sensor is | ||
208 | attached or the kernel will crash! However, you should not need to notify | ||
209 | the user about common errors or other messages, since this is done by the | ||
210 | master module. | ||
211 | */ | ||
212 | |||
213 | /*****************************************************************************/ | 121 | /*****************************************************************************/ |
214 | 122 | ||
215 | enum sn9c102_i2c_sysfs_ops { | 123 | enum sn9c102_i2c_sysfs_ops { |
@@ -227,17 +135,19 @@ enum sn9c102_i2c_interface { | |||
227 | SN9C102_I2C_3WIRES, | 135 | SN9C102_I2C_3WIRES, |
228 | }; | 136 | }; |
229 | 137 | ||
230 | #define SN9C102_MAX_CTRLS V4L2_CID_LASTP1-V4L2_CID_BASE+10 | 138 | #define SN9C102_MAX_CTRLS (V4L2_CID_LASTP1-V4L2_CID_BASE+10) |
231 | 139 | ||
232 | struct sn9c102_sensor { | 140 | struct sn9c102_sensor { |
233 | char name[32], /* sensor name */ | 141 | char name[32], /* sensor name */ |
234 | maintainer[64]; /* name of the mantainer <email> */ | 142 | maintainer[64]; /* name of the mantainer <email> */ |
235 | 143 | ||
144 | enum sn9c102_bridge supported_bridge; /* supported SN9C1xx bridges */ | ||
145 | |||
236 | /* Supported operations through the 'sysfs' interface */ | 146 | /* Supported operations through the 'sysfs' interface */ |
237 | enum sn9c102_i2c_sysfs_ops sysfs_ops; | 147 | enum sn9c102_i2c_sysfs_ops sysfs_ops; |
238 | 148 | ||
239 | /* | 149 | /* |
240 | These sensor capabilities must be provided if the SN9C10X controller | 150 | These sensor capabilities must be provided if the SN9C1XX controller |
241 | needs to communicate through the sensor serial interface by using | 151 | needs to communicate through the sensor serial interface by using |
242 | at least one of the i2c functions available. | 152 | at least one of the i2c functions available. |
243 | */ | 153 | */ |
@@ -260,7 +170,7 @@ struct sn9c102_sensor { | |||
260 | /* | 170 | /* |
261 | This function will be called after the sensor has been attached. | 171 | This function will be called after the sensor has been attached. |
262 | It should be used to initialize the sensor only, but may also | 172 | It should be used to initialize the sensor only, but may also |
263 | configure part of the SN9C10X chip if necessary. You don't need to | 173 | configure part of the SN9C1XX chip if necessary. You don't need to |
264 | setup picture settings like brightness, contrast, etc.. here, if | 174 | setup picture settings like brightness, contrast, etc.. here, if |
265 | the corrisponding controls are implemented (see below), since | 175 | the corrisponding controls are implemented (see below), since |
266 | they are adjusted in the core driver by calling the set_ctrl() | 176 | they are adjusted in the core driver by calling the set_ctrl() |
@@ -300,7 +210,7 @@ struct sn9c102_sensor { | |||
300 | It is not always true that the largest achievable active window can | 210 | It is not always true that the largest achievable active window can |
301 | cover the whole array of pixels. The V4L2 API defines another | 211 | cover the whole array of pixels. The V4L2 API defines another |
302 | area called "source rectangle", which, in turn, is a subrectangle of | 212 | area called "source rectangle", which, in turn, is a subrectangle of |
303 | the active window. The SN9C10X chip is always programmed to read the | 213 | the active window. The SN9C1XX chip is always programmed to read the |
304 | source rectangle. | 214 | source rectangle. |
305 | The bounds of both the active window and the source rectangle are | 215 | The bounds of both the active window and the source rectangle are |
306 | specified in the cropcap substructures 'bounds' and 'defrect'. | 216 | specified in the cropcap substructures 'bounds' and 'defrect'. |
@@ -326,13 +236,13 @@ struct sn9c102_sensor { | |||
326 | const struct v4l2_rect* rect); | 236 | const struct v4l2_rect* rect); |
327 | /* | 237 | /* |
328 | To be called on VIDIOC_C_SETCROP. The core module always calls a | 238 | To be called on VIDIOC_C_SETCROP. The core module always calls a |
329 | default routine which configures the appropriate SN9C10X regs (also | 239 | default routine which configures the appropriate SN9C1XX regs (also |
330 | scaling), but you may need to override/adjust specific stuff. | 240 | scaling), but you may need to override/adjust specific stuff. |
331 | 'rect' contains width and height values that are multiple of 16: in | 241 | 'rect' contains width and height values that are multiple of 16: in |
332 | case you override the default function, you always have to program | 242 | case you override the default function, you always have to program |
333 | the chip to match those values; on error return the corresponding | 243 | the chip to match those values; on error return the corresponding |
334 | error code without rolling back. | 244 | error code without rolling back. |
335 | NOTE: in case, you must program the SN9C10X chip to get rid of | 245 | NOTE: in case, you must program the SN9C1XX chip to get rid of |
336 | blank pixels or blank lines at the _start_ of each line or | 246 | blank pixels or blank lines at the _start_ of each line or |
337 | frame after each HSYNC or VSYNC, so that the image starts with | 247 | frame after each HSYNC or VSYNC, so that the image starts with |
338 | real RGB data (see regs 0x12, 0x13) (having set H_SIZE and, | 248 | real RGB data (see regs 0x12, 0x13) (having set H_SIZE and, |
@@ -344,16 +254,16 @@ struct sn9c102_sensor { | |||
344 | /* | 254 | /* |
345 | What you have to define here are: 1) initial 'width' and 'height' of | 255 | What you have to define here are: 1) initial 'width' and 'height' of |
346 | the target rectangle 2) the initial 'pixelformat', which can be | 256 | the target rectangle 2) the initial 'pixelformat', which can be |
347 | either V4L2_PIX_FMT_SN9C10X (for compressed video) or | 257 | either V4L2_PIX_FMT_SN9C10X, V4L2_PIX_FMT_JPEG (for ompressed video) |
348 | V4L2_PIX_FMT_SBGGR8 3) 'priv', which we'll be used to indicate the | 258 | or V4L2_PIX_FMT_SBGGR8 3) 'priv', which we'll be used to indicate |
349 | number of bits per pixel for uncompressed video, 8 or 9 (despite the | 259 | the number of bits per pixel for uncompressed video, 8 or 9 (despite |
350 | current value of 'pixelformat'). | 260 | the current value of 'pixelformat'). |
351 | NOTE 1: both 'width' and 'height' _must_ be either 1/1 or 1/2 or 1/4 | 261 | NOTE 1: both 'width' and 'height' _must_ be either 1/1 or 1/2 or 1/4 |
352 | of cropcap.defrect.width and cropcap.defrect.height. I | 262 | of cropcap.defrect.width and cropcap.defrect.height. I |
353 | suggest 1/1. | 263 | suggest 1/1. |
354 | NOTE 2: The initial compression quality is defined by the first bit | 264 | NOTE 2: The initial compression quality is defined by the first bit |
355 | of reg 0x17 during the initialization of the image sensor. | 265 | of reg 0x17 during the initialization of the image sensor. |
356 | NOTE 3: as said above, you have to program the SN9C10X chip to get | 266 | NOTE 3: as said above, you have to program the SN9C1XX chip to get |
357 | rid of any blank pixels, so that the output of the sensor | 267 | rid of any blank pixels, so that the output of the sensor |
358 | matches the RGB bayer sequence (i.e. BGBGBG...GRGRGR). | 268 | matches the RGB bayer sequence (i.e. BGBGBG...GRGRGR). |
359 | */ | 269 | */ |
@@ -378,12 +288,12 @@ struct sn9c102_sensor { | |||
378 | /*****************************************************************************/ | 288 | /*****************************************************************************/ |
379 | 289 | ||
380 | /* Private ioctl's for control settings supported by some image sensors */ | 290 | /* Private ioctl's for control settings supported by some image sensors */ |
381 | #define SN9C102_V4L2_CID_DAC_MAGNITUDE V4L2_CID_PRIVATE_BASE | 291 | #define SN9C102_V4L2_CID_DAC_MAGNITUDE (V4L2_CID_PRIVATE_BASE + 0) |
382 | #define SN9C102_V4L2_CID_GREEN_BALANCE V4L2_CID_PRIVATE_BASE + 1 | 292 | #define SN9C102_V4L2_CID_GREEN_BALANCE (V4L2_CID_PRIVATE_BASE + 1) |
383 | #define SN9C102_V4L2_CID_RESET_LEVEL V4L2_CID_PRIVATE_BASE + 2 | 293 | #define SN9C102_V4L2_CID_RESET_LEVEL (V4L2_CID_PRIVATE_BASE + 2) |
384 | #define SN9C102_V4L2_CID_PIXEL_BIAS_VOLTAGE V4L2_CID_PRIVATE_BASE + 3 | 294 | #define SN9C102_V4L2_CID_PIXEL_BIAS_VOLTAGE (V4L2_CID_PRIVATE_BASE + 3) |
385 | #define SN9C102_V4L2_CID_GAMMA V4L2_CID_PRIVATE_BASE + 4 | 295 | #define SN9C102_V4L2_CID_GAMMA (V4L2_CID_PRIVATE_BASE + 4) |
386 | #define SN9C102_V4L2_CID_BAND_FILTER V4L2_CID_PRIVATE_BASE + 5 | 296 | #define SN9C102_V4L2_CID_BAND_FILTER (V4L2_CID_PRIVATE_BASE + 5) |
387 | #define SN9C102_V4L2_CID_BRIGHT_LEVEL V4L2_CID_PRIVATE_BASE + 6 | 297 | #define SN9C102_V4L2_CID_BRIGHT_LEVEL (V4L2_CID_PRIVATE_BASE + 6) |
388 | 298 | ||
389 | #endif /* _SN9C102_SENSOR_H_ */ | 299 | #endif /* _SN9C102_SENSOR_H_ */ |
diff --git a/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c b/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c index 294eb02fbd88..90023ad63adc 100644 --- a/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c +++ b/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c | |||
@@ -1,8 +1,8 @@ | |||
1 | /*************************************************************************** | 1 | /*************************************************************************** |
2 | * Plug-in for TAS5110C1B image sensor connected to the SN9C10x PC Camera * | 2 | * Plug-in for TAS5110C1B image sensor connected to the SN9C1xx PC Camera * |
3 | * Controllers * | 3 | * Controllers * |
4 | * * | 4 | * * |
5 | * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it> * | 5 | * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it> * |
6 | * * | 6 | * * |
7 | * This program is free software; you can redistribute it and/or modify * | 7 | * This program is free software; you can redistribute it and/or modify * |
8 | * it under the terms of the GNU General Public License as published by * | 8 | * it under the terms of the GNU General Public License as published by * |
@@ -64,7 +64,7 @@ static int tas5110c1b_set_ctrl(struct sn9c102_device* cam, | |||
64 | static int tas5110c1b_set_crop(struct sn9c102_device* cam, | 64 | static int tas5110c1b_set_crop(struct sn9c102_device* cam, |
65 | const struct v4l2_rect* rect) | 65 | const struct v4l2_rect* rect) |
66 | { | 66 | { |
67 | struct sn9c102_sensor* s = &tas5110c1b; | 67 | struct sn9c102_sensor* s = sn9c102_get_sensor(cam); |
68 | int err = 0; | 68 | int err = 0; |
69 | u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 69, | 69 | u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 69, |
70 | v_start = (u8)(rect->top - s->cropcap.bounds.top) + 9; | 70 | v_start = (u8)(rect->top - s->cropcap.bounds.top) + 9; |
@@ -98,6 +98,7 @@ static int tas5110c1b_set_pix_format(struct sn9c102_device* cam, | |||
98 | static struct sn9c102_sensor tas5110c1b = { | 98 | static struct sn9c102_sensor tas5110c1b = { |
99 | .name = "TAS5110C1B", | 99 | .name = "TAS5110C1B", |
100 | .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", | 100 | .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", |
101 | .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103, | ||
101 | .sysfs_ops = SN9C102_I2C_WRITE, | 102 | .sysfs_ops = SN9C102_I2C_WRITE, |
102 | .frequency = SN9C102_I2C_100KHZ, | 103 | .frequency = SN9C102_I2C_100KHZ, |
103 | .interface = SN9C102_I2C_3WIRES, | 104 | .interface = SN9C102_I2C_3WIRES, |
@@ -145,6 +146,7 @@ int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam) | |||
145 | const struct usb_device_id tas5110c1b_id_table[] = { | 146 | const struct usb_device_id tas5110c1b_id_table[] = { |
146 | { USB_DEVICE(0x0c45, 0x6001), }, | 147 | { USB_DEVICE(0x0c45, 0x6001), }, |
147 | { USB_DEVICE(0x0c45, 0x6005), }, | 148 | { USB_DEVICE(0x0c45, 0x6005), }, |
149 | { USB_DEVICE(0x0c45, 0x6007), }, | ||
148 | { USB_DEVICE(0x0c45, 0x60ab), }, | 150 | { USB_DEVICE(0x0c45, 0x60ab), }, |
149 | { } | 151 | { } |
150 | }; | 152 | }; |
diff --git a/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c b/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c index 9ecb09032b68..cb1b318bc1ff 100644 --- a/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c +++ b/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c | |||
@@ -1,8 +1,8 @@ | |||
1 | /*************************************************************************** | 1 | /*************************************************************************** |
2 | * Plug-in for TAS5130D1B image sensor connected to the SN9C10x PC Camera * | 2 | * Plug-in for TAS5130D1B image sensor connected to the SN9C1xx PC Camera * |
3 | * Controllers * | 3 | * Controllers * |
4 | * * | 4 | * * |
5 | * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it> * | 5 | * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it> * |
6 | * * | 6 | * * |
7 | * This program is free software; you can redistribute it and/or modify * | 7 | * This program is free software; you can redistribute it and/or modify * |
8 | * it under the terms of the GNU General Public License as published by * | 8 | * it under the terms of the GNU General Public License as published by * |
@@ -65,7 +65,7 @@ static int tas5130d1b_set_ctrl(struct sn9c102_device* cam, | |||
65 | static int tas5130d1b_set_crop(struct sn9c102_device* cam, | 65 | static int tas5130d1b_set_crop(struct sn9c102_device* cam, |
66 | const struct v4l2_rect* rect) | 66 | const struct v4l2_rect* rect) |
67 | { | 67 | { |
68 | struct sn9c102_sensor* s = &tas5130d1b; | 68 | struct sn9c102_sensor* s = sn9c102_get_sensor(cam); |
69 | u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 104, | 69 | u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 104, |
70 | v_start = (u8)(rect->top - s->cropcap.bounds.top) + 12; | 70 | v_start = (u8)(rect->top - s->cropcap.bounds.top) + 12; |
71 | int err = 0; | 71 | int err = 0; |
@@ -99,6 +99,7 @@ static int tas5130d1b_set_pix_format(struct sn9c102_device* cam, | |||
99 | static struct sn9c102_sensor tas5130d1b = { | 99 | static struct sn9c102_sensor tas5130d1b = { |
100 | .name = "TAS5130D1B", | 100 | .name = "TAS5130D1B", |
101 | .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", | 101 | .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", |
102 | .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103, | ||
102 | .sysfs_ops = SN9C102_I2C_WRITE, | 103 | .sysfs_ops = SN9C102_I2C_WRITE, |
103 | .frequency = SN9C102_I2C_100KHZ, | 104 | .frequency = SN9C102_I2C_100KHZ, |
104 | .interface = SN9C102_I2C_3WIRES, | 105 | .interface = SN9C102_I2C_3WIRES, |
@@ -154,6 +155,7 @@ static struct sn9c102_sensor tas5130d1b = { | |||
154 | int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam) | 155 | int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam) |
155 | { | 156 | { |
156 | const struct usb_device_id tas5130d1b_id_table[] = { | 157 | const struct usb_device_id tas5130d1b_id_table[] = { |
158 | { USB_DEVICE(0x0c45, 0x6024), }, | ||
157 | { USB_DEVICE(0x0c45, 0x6025), }, | 159 | { USB_DEVICE(0x0c45, 0x6025), }, |
158 | { USB_DEVICE(0x0c45, 0x60aa), }, | 160 | { USB_DEVICE(0x0c45, 0x60aa), }, |
159 | { } | 161 | { } |
diff --git a/drivers/media/video/tvmixer.c b/drivers/media/video/tvmixer.c index 7ea9132a1965..3ae5a9cd2e28 100644 --- a/drivers/media/video/tvmixer.c +++ b/drivers/media/video/tvmixer.c | |||
@@ -212,8 +212,7 @@ static int tvmixer_release(struct inode *inode, struct file *file) | |||
212 | return -ENODEV; | 212 | return -ENODEV; |
213 | } | 213 | } |
214 | 214 | ||
215 | if (client->adapter->owner) | 215 | module_put(client->adapter->owner); |
216 | module_put(client->adapter->owner); | ||
217 | return 0; | 216 | return 0; |
218 | } | 217 | } |
219 | 218 | ||
diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c index bc0a4fc27b24..886b5df7c9d1 100644 --- a/drivers/media/video/tvp5150.c +++ b/drivers/media/video/tvp5150.c | |||
@@ -950,17 +950,8 @@ static int tvp5150_command(struct i2c_client *c, | |||
950 | } | 950 | } |
951 | 951 | ||
952 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 952 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
953 | case VIDIOC_INT_G_REGISTER: | 953 | case VIDIOC_DBG_G_REGISTER: |
954 | { | 954 | case VIDIOC_DBG_S_REGISTER: |
955 | struct v4l2_register *reg = arg; | ||
956 | |||
957 | if (reg->i2c_id != I2C_DRIVERID_TVP5150) | ||
958 | return -EINVAL; | ||
959 | reg->val = tvp5150_read(c, reg->reg & 0xff); | ||
960 | break; | ||
961 | } | ||
962 | |||
963 | case VIDIOC_INT_S_REGISTER: | ||
964 | { | 955 | { |
965 | struct v4l2_register *reg = arg; | 956 | struct v4l2_register *reg = arg; |
966 | 957 | ||
@@ -968,7 +959,10 @@ static int tvp5150_command(struct i2c_client *c, | |||
968 | return -EINVAL; | 959 | return -EINVAL; |
969 | if (!capable(CAP_SYS_ADMIN)) | 960 | if (!capable(CAP_SYS_ADMIN)) |
970 | return -EPERM; | 961 | return -EPERM; |
971 | tvp5150_write(c, reg->reg & 0xff, reg->val & 0xff); | 962 | if (cmd == VIDIOC_DBG_G_REGISTER) |
963 | reg->val = tvp5150_read(c, reg->reg & 0xff); | ||
964 | else | ||
965 | tvp5150_write(c, reg->reg & 0xff, reg->val & 0xff); | ||
972 | break; | 966 | break; |
973 | } | 967 | } |
974 | #endif | 968 | #endif |
diff --git a/drivers/media/video/upd64031a.c b/drivers/media/video/upd64031a.c index fc52201d607e..b3b5fd536dc3 100644 --- a/drivers/media/video/upd64031a.c +++ b/drivers/media/video/upd64031a.c | |||
@@ -162,27 +162,19 @@ static int upd64031a_command(struct i2c_client *client, unsigned int cmd, void * | |||
162 | break; | 162 | break; |
163 | 163 | ||
164 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 164 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
165 | case VIDIOC_INT_G_REGISTER: | 165 | case VIDIOC_DBG_G_REGISTER: |
166 | case VIDIOC_DBG_S_REGISTER: | ||
166 | { | 167 | { |
167 | struct v4l2_register *reg = arg; | 168 | struct v4l2_register *reg = arg; |
168 | 169 | ||
169 | if (reg->i2c_id != I2C_DRIVERID_UPD64031A) | 170 | if (reg->i2c_id != I2C_DRIVERID_UPD64031A) |
170 | return -EINVAL; | 171 | return -EINVAL; |
171 | reg->val = upd64031a_read(client, reg->reg & 0xff); | ||
172 | break; | ||
173 | } | ||
174 | |||
175 | case VIDIOC_INT_S_REGISTER: | ||
176 | { | ||
177 | struct v4l2_register *reg = arg; | ||
178 | u8 addr = reg->reg & 0xff; | ||
179 | u8 val = reg->val & 0xff; | ||
180 | |||
181 | if (reg->i2c_id != I2C_DRIVERID_UPD64031A) | ||
182 | return -EINVAL; | ||
183 | if (!capable(CAP_SYS_ADMIN)) | 172 | if (!capable(CAP_SYS_ADMIN)) |
184 | return -EPERM; | 173 | return -EPERM; |
185 | upd64031a_write(client, addr, val); | 174 | if (cmd == VIDIOC_DBG_G_REGISTER) |
175 | reg->val = upd64031a_read(client, reg->reg & 0xff); | ||
176 | else | ||
177 | upd64031a_write(client, reg->reg & 0xff, reg->val & 0xff); | ||
186 | break; | 178 | break; |
187 | } | 179 | } |
188 | #endif | 180 | #endif |
diff --git a/drivers/media/video/upd64083.c b/drivers/media/video/upd64083.c index c3a7ffe5c267..8852903e7a92 100644 --- a/drivers/media/video/upd64083.c +++ b/drivers/media/video/upd64083.c | |||
@@ -139,27 +139,19 @@ static int upd64083_command(struct i2c_client *client, unsigned int cmd, void *a | |||
139 | break; | 139 | break; |
140 | 140 | ||
141 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 141 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
142 | case VIDIOC_INT_G_REGISTER: | 142 | case VIDIOC_DBG_G_REGISTER: |
143 | case VIDIOC_DBG_S_REGISTER: | ||
143 | { | 144 | { |
144 | struct v4l2_register *reg = arg; | 145 | struct v4l2_register *reg = arg; |
145 | 146 | ||
146 | if (reg->i2c_id != I2C_DRIVERID_UPD64083) | 147 | if (reg->i2c_id != I2C_DRIVERID_UPD64083) |
147 | return -EINVAL; | 148 | return -EINVAL; |
148 | reg->val = upd64083_read(client, reg->reg & 0xff); | ||
149 | break; | ||
150 | } | ||
151 | |||
152 | case VIDIOC_INT_S_REGISTER: | ||
153 | { | ||
154 | struct v4l2_register *reg = arg; | ||
155 | u8 addr = reg->reg & 0xff; | ||
156 | u8 val = reg->val & 0xff; | ||
157 | |||
158 | if (reg->i2c_id != I2C_DRIVERID_UPD64083) | ||
159 | return -EINVAL; | ||
160 | if (!capable(CAP_SYS_ADMIN)) | 149 | if (!capable(CAP_SYS_ADMIN)) |
161 | return -EPERM; | 150 | return -EPERM; |
162 | upd64083_write(client, addr, val); | 151 | if (cmd == VIDIOC_DBG_G_REGISTER) |
152 | reg->val = upd64083_read(client, reg->reg & 0xff); | ||
153 | else | ||
154 | upd64083_write(client, reg->reg & 0xff, reg->val & 0xff); | ||
163 | break; | 155 | break; |
164 | } | 156 | } |
165 | #endif | 157 | #endif |
diff --git a/drivers/media/video/usbvision/Kconfig b/drivers/media/video/usbvision/Kconfig index fc24ef05b3f3..c43a5d899091 100644 --- a/drivers/media/video/usbvision/Kconfig +++ b/drivers/media/video/usbvision/Kconfig | |||
@@ -1,6 +1,6 @@ | |||
1 | config VIDEO_USBVISION | 1 | config VIDEO_USBVISION |
2 | tristate "USB video devices based on Nogatech NT1003/1004/1005" | 2 | tristate "USB video devices based on Nogatech NT1003/1004/1005" |
3 | depends on I2C && VIDEO_V4L2 | 3 | depends on I2C && VIDEO_V4L2 && USB |
4 | select VIDEO_TUNER | 4 | select VIDEO_TUNER |
5 | select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO | 5 | select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO |
6 | ---help--- | 6 | ---help--- |
diff --git a/drivers/media/video/usbvision/usbvision-core.c b/drivers/media/video/usbvision/usbvision-core.c index 901f664dc6db..f2154dc072e2 100644 --- a/drivers/media/video/usbvision/usbvision-core.c +++ b/drivers/media/video/usbvision/usbvision-core.c | |||
@@ -138,7 +138,7 @@ static void *usbvision_rvmalloc(unsigned long size) | |||
138 | return mem; | 138 | return mem; |
139 | } | 139 | } |
140 | 140 | ||
141 | void usbvision_rvfree(void *mem, unsigned long size) | 141 | static void usbvision_rvfree(void *mem, unsigned long size) |
142 | { | 142 | { |
143 | unsigned long adr; | 143 | unsigned long adr; |
144 | 144 | ||
@@ -1852,28 +1852,33 @@ int usbvision_set_output(struct usb_usbvision *usbvision, int width, | |||
1852 | 1852 | ||
1853 | /* | 1853 | /* |
1854 | * usbvision_frames_alloc | 1854 | * usbvision_frames_alloc |
1855 | * allocate the maximum frames this driver can manage | 1855 | * allocate the required frames |
1856 | */ | 1856 | */ |
1857 | int usbvision_frames_alloc(struct usb_usbvision *usbvision) | 1857 | int usbvision_frames_alloc(struct usb_usbvision *usbvision, int number_of_frames) |
1858 | { | 1858 | { |
1859 | int i; | 1859 | int i; |
1860 | 1860 | ||
1861 | /* Allocate memory for the frame buffers */ | 1861 | /*needs to be page aligned cause the buffers can be mapped individually! */ |
1862 | usbvision->max_frame_size = MAX_FRAME_SIZE; | 1862 | usbvision->max_frame_size = PAGE_ALIGN(usbvision->curwidth * |
1863 | usbvision->fbuf_size = USBVISION_NUMFRAMES * usbvision->max_frame_size; | 1863 | usbvision->curheight * |
1864 | usbvision->fbuf = usbvision_rvmalloc(usbvision->fbuf_size); | 1864 | usbvision->palette.bytes_per_pixel); |
1865 | 1865 | ||
1866 | if(usbvision->fbuf == NULL) { | 1866 | /* Try to do my best to allocate the frames the user want in the remaining memory */ |
1867 | err("%s: unable to allocate %d bytes for fbuf ", | 1867 | usbvision->num_frames = number_of_frames; |
1868 | __FUNCTION__, usbvision->fbuf_size); | 1868 | while (usbvision->num_frames > 0) { |
1869 | return -ENOMEM; | 1869 | usbvision->fbuf_size = usbvision->num_frames * usbvision->max_frame_size; |
1870 | if((usbvision->fbuf = usbvision_rvmalloc(usbvision->fbuf_size))) { | ||
1871 | break; | ||
1872 | } | ||
1873 | usbvision->num_frames--; | ||
1870 | } | 1874 | } |
1875 | |||
1871 | spin_lock_init(&usbvision->queue_lock); | 1876 | spin_lock_init(&usbvision->queue_lock); |
1872 | init_waitqueue_head(&usbvision->wait_frame); | 1877 | init_waitqueue_head(&usbvision->wait_frame); |
1873 | init_waitqueue_head(&usbvision->wait_stream); | 1878 | init_waitqueue_head(&usbvision->wait_stream); |
1874 | 1879 | ||
1875 | /* Allocate all buffers */ | 1880 | /* Allocate all buffers */ |
1876 | for (i = 0; i < USBVISION_NUMFRAMES; i++) { | 1881 | for (i = 0; i < usbvision->num_frames; i++) { |
1877 | usbvision->frame[i].index = i; | 1882 | usbvision->frame[i].index = i; |
1878 | usbvision->frame[i].grabstate = FrameState_Unused; | 1883 | usbvision->frame[i].grabstate = FrameState_Unused; |
1879 | usbvision->frame[i].data = usbvision->fbuf + | 1884 | usbvision->frame[i].data = usbvision->fbuf + |
@@ -1887,7 +1892,8 @@ int usbvision_frames_alloc(struct usb_usbvision *usbvision) | |||
1887 | usbvision->frame[i].height = usbvision->curheight; | 1892 | usbvision->frame[i].height = usbvision->curheight; |
1888 | usbvision->frame[i].bytes_read = 0; | 1893 | usbvision->frame[i].bytes_read = 0; |
1889 | } | 1894 | } |
1890 | return 0; | 1895 | PDEBUG(DBG_FUNC, "allocated %d frames (%d bytes per frame)",usbvision->num_frames,usbvision->max_frame_size); |
1896 | return usbvision->num_frames; | ||
1891 | } | 1897 | } |
1892 | 1898 | ||
1893 | /* | 1899 | /* |
@@ -1897,9 +1903,13 @@ int usbvision_frames_alloc(struct usb_usbvision *usbvision) | |||
1897 | void usbvision_frames_free(struct usb_usbvision *usbvision) | 1903 | void usbvision_frames_free(struct usb_usbvision *usbvision) |
1898 | { | 1904 | { |
1899 | /* Have to free all that memory */ | 1905 | /* Have to free all that memory */ |
1906 | PDEBUG(DBG_FUNC, "free %d frames",usbvision->num_frames); | ||
1907 | |||
1900 | if (usbvision->fbuf != NULL) { | 1908 | if (usbvision->fbuf != NULL) { |
1901 | usbvision_rvfree(usbvision->fbuf, usbvision->fbuf_size); | 1909 | usbvision_rvfree(usbvision->fbuf, usbvision->fbuf_size); |
1902 | usbvision->fbuf = NULL; | 1910 | usbvision->fbuf = NULL; |
1911 | |||
1912 | usbvision->num_frames = 0; | ||
1903 | } | 1913 | } |
1904 | } | 1914 | } |
1905 | /* | 1915 | /* |
@@ -2351,6 +2361,32 @@ int usbvision_setup(struct usb_usbvision *usbvision,int format) | |||
2351 | return USBVISION_IS_OPERATIONAL(usbvision); | 2361 | return USBVISION_IS_OPERATIONAL(usbvision); |
2352 | } | 2362 | } |
2353 | 2363 | ||
2364 | int usbvision_set_alternate(struct usb_usbvision *dev) | ||
2365 | { | ||
2366 | int errCode, prev_alt = dev->ifaceAlt; | ||
2367 | int i; | ||
2368 | |||
2369 | dev->ifaceAlt=0; | ||
2370 | for(i=0;i< dev->num_alt; i++) | ||
2371 | if(dev->alt_max_pkt_size[i]>dev->alt_max_pkt_size[dev->ifaceAlt]) | ||
2372 | dev->ifaceAlt=i; | ||
2373 | |||
2374 | if (dev->ifaceAlt != prev_alt) { | ||
2375 | dev->isocPacketSize = dev->alt_max_pkt_size[dev->ifaceAlt]; | ||
2376 | PDEBUG(DBG_FUNC,"setting alternate %d with wMaxPacketSize=%u", dev->ifaceAlt,dev->isocPacketSize); | ||
2377 | errCode = usb_set_interface(dev->dev, dev->iface, dev->ifaceAlt); | ||
2378 | if (errCode < 0) { | ||
2379 | err ("cannot change alternate number to %d (error=%i)", | ||
2380 | dev->ifaceAlt, errCode); | ||
2381 | return errCode; | ||
2382 | } | ||
2383 | } | ||
2384 | |||
2385 | PDEBUG(DBG_ISOC, "ISO Packet Length:%d", dev->isocPacketSize); | ||
2386 | |||
2387 | return 0; | ||
2388 | } | ||
2389 | |||
2354 | /* | 2390 | /* |
2355 | * usbvision_init_isoc() | 2391 | * usbvision_init_isoc() |
2356 | * | 2392 | * |
@@ -2368,15 +2404,13 @@ int usbvision_init_isoc(struct usb_usbvision *usbvision) | |||
2368 | scratch_reset(usbvision); | 2404 | scratch_reset(usbvision); |
2369 | 2405 | ||
2370 | /* Alternate interface 1 is is the biggest frame size */ | 2406 | /* Alternate interface 1 is is the biggest frame size */ |
2371 | errCode = usb_set_interface(dev, usbvision->iface, usbvision->ifaceAltActive); | 2407 | errCode = usbvision_set_alternate(usbvision); |
2372 | if (errCode < 0) { | 2408 | if (errCode < 0) { |
2373 | usbvision->last_error = errCode; | 2409 | usbvision->last_error = errCode; |
2374 | return -EBUSY; | 2410 | return -EBUSY; |
2375 | } | 2411 | } |
2376 | 2412 | ||
2377 | regValue = (16 - usbvision_read_reg(usbvision, USBVISION_ALTER_REG)) & 0x0F; | 2413 | regValue = (16 - usbvision_read_reg(usbvision, USBVISION_ALTER_REG)) & 0x0F; |
2378 | usbvision->isocPacketSize = (regValue == 0) ? 0 : (regValue * 64) - 1; | ||
2379 | PDEBUG(DBG_ISOC, "ISO Packet Length:%d", usbvision->isocPacketSize); | ||
2380 | 2414 | ||
2381 | usbvision->usb_bandwidth = regValue >> 1; | 2415 | usbvision->usb_bandwidth = regValue >> 1; |
2382 | PDEBUG(DBG_ISOC, "USB Bandwidth Usage: %dMbit/Sec", usbvision->usb_bandwidth); | 2416 | PDEBUG(DBG_ISOC, "USB Bandwidth Usage: %dMbit/Sec", usbvision->usb_bandwidth); |
@@ -2462,8 +2496,9 @@ void usbvision_stop_isoc(struct usb_usbvision *usbvision) | |||
2462 | if (!usbvision->remove_pending) { | 2496 | if (!usbvision->remove_pending) { |
2463 | 2497 | ||
2464 | /* Set packet size to 0 */ | 2498 | /* Set packet size to 0 */ |
2499 | usbvision->ifaceAlt=0; | ||
2465 | errCode = usb_set_interface(usbvision->dev, usbvision->iface, | 2500 | errCode = usb_set_interface(usbvision->dev, usbvision->iface, |
2466 | usbvision->ifaceAltInactive); | 2501 | usbvision->ifaceAlt); |
2467 | if (errCode < 0) { | 2502 | if (errCode < 0) { |
2468 | err("%s: usb_set_interface() failed: error %d", __FUNCTION__, errCode); | 2503 | err("%s: usb_set_interface() failed: error %d", __FUNCTION__, errCode); |
2469 | usbvision->last_error = errCode; | 2504 | usbvision->last_error = errCode; |
@@ -2490,6 +2525,7 @@ int usbvision_muxsel(struct usb_usbvision *usbvision, int channel) | |||
2490 | RESTRICT_TO_RANGE(channel, 0, usbvision->video_inputs); | 2525 | RESTRICT_TO_RANGE(channel, 0, usbvision->video_inputs); |
2491 | usbvision->ctl_input = channel; | 2526 | usbvision->ctl_input = channel; |
2492 | route.input = SAA7115_COMPOSITE1; | 2527 | route.input = SAA7115_COMPOSITE1; |
2528 | route.output = 0; | ||
2493 | call_i2c_clients(usbvision, VIDIOC_INT_S_VIDEO_ROUTING,&route); | 2529 | call_i2c_clients(usbvision, VIDIOC_INT_S_VIDEO_ROUTING,&route); |
2494 | call_i2c_clients(usbvision, VIDIOC_S_INPUT, &usbvision->ctl_input); | 2530 | call_i2c_clients(usbvision, VIDIOC_S_INPUT, &usbvision->ctl_input); |
2495 | 2531 | ||
diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c index af33653f0db8..ae5f42562c0c 100644 --- a/drivers/media/video/usbvision/usbvision-video.c +++ b/drivers/media/video/usbvision/usbvision-video.c | |||
@@ -230,7 +230,7 @@ static ssize_t show_hue(struct class_device *cd, char *buf) | |||
230 | ctrl.value = 0; | 230 | ctrl.value = 0; |
231 | if(usbvision->user) | 231 | if(usbvision->user) |
232 | call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl); | 232 | call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl); |
233 | return sprintf(buf, "%d\n", ctrl.value >> 8); | 233 | return sprintf(buf, "%d\n", ctrl.value); |
234 | } | 234 | } |
235 | static CLASS_DEVICE_ATTR(hue, S_IRUGO, show_hue, NULL); | 235 | static CLASS_DEVICE_ATTR(hue, S_IRUGO, show_hue, NULL); |
236 | 236 | ||
@@ -243,7 +243,7 @@ static ssize_t show_contrast(struct class_device *cd, char *buf) | |||
243 | ctrl.value = 0; | 243 | ctrl.value = 0; |
244 | if(usbvision->user) | 244 | if(usbvision->user) |
245 | call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl); | 245 | call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl); |
246 | return sprintf(buf, "%d\n", ctrl.value >> 8); | 246 | return sprintf(buf, "%d\n", ctrl.value); |
247 | } | 247 | } |
248 | static CLASS_DEVICE_ATTR(contrast, S_IRUGO, show_contrast, NULL); | 248 | static CLASS_DEVICE_ATTR(contrast, S_IRUGO, show_contrast, NULL); |
249 | 249 | ||
@@ -256,7 +256,7 @@ static ssize_t show_brightness(struct class_device *cd, char *buf) | |||
256 | ctrl.value = 0; | 256 | ctrl.value = 0; |
257 | if(usbvision->user) | 257 | if(usbvision->user) |
258 | call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl); | 258 | call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl); |
259 | return sprintf(buf, "%d\n", ctrl.value >> 8); | 259 | return sprintf(buf, "%d\n", ctrl.value); |
260 | } | 260 | } |
261 | static CLASS_DEVICE_ATTR(brightness, S_IRUGO, show_brightness, NULL); | 261 | static CLASS_DEVICE_ATTR(brightness, S_IRUGO, show_brightness, NULL); |
262 | 262 | ||
@@ -269,7 +269,7 @@ static ssize_t show_saturation(struct class_device *cd, char *buf) | |||
269 | ctrl.value = 0; | 269 | ctrl.value = 0; |
270 | if(usbvision->user) | 270 | if(usbvision->user) |
271 | call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl); | 271 | call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl); |
272 | return sprintf(buf, "%d\n", ctrl.value >> 8); | 272 | return sprintf(buf, "%d\n", ctrl.value); |
273 | } | 273 | } |
274 | static CLASS_DEVICE_ATTR(saturation, S_IRUGO, show_saturation, NULL); | 274 | static CLASS_DEVICE_ATTR(saturation, S_IRUGO, show_saturation, NULL); |
275 | 275 | ||
@@ -391,19 +391,14 @@ static int usbvision_v4l2_open(struct inode *inode, struct file *file) | |||
391 | if (usbvision->user) | 391 | if (usbvision->user) |
392 | errCode = -EBUSY; | 392 | errCode = -EBUSY; |
393 | else { | 393 | else { |
394 | /* Allocate memory for the frame buffers */ | 394 | /* Allocate memory for the scratch ring buffer */ |
395 | errCode = usbvision_frames_alloc(usbvision); | 395 | errCode = usbvision_scratch_alloc(usbvision); |
396 | if(!errCode) { | 396 | if (isocMode==ISOC_MODE_COMPRESS) { |
397 | /* Allocate memory for the scratch ring buffer */ | 397 | /* Allocate intermediate decompression buffers only if needed */ |
398 | errCode = usbvision_scratch_alloc(usbvision); | 398 | errCode = usbvision_decompress_alloc(usbvision); |
399 | if ((!errCode) && (isocMode==ISOC_MODE_COMPRESS)) { | ||
400 | /* Allocate intermediate decompression buffers only if needed */ | ||
401 | errCode = usbvision_decompress_alloc(usbvision); | ||
402 | } | ||
403 | } | 399 | } |
404 | if (errCode) { | 400 | if (errCode) { |
405 | /* Deallocate all buffers if trouble */ | 401 | /* Deallocate all buffers if trouble */ |
406 | usbvision_frames_free(usbvision); | ||
407 | usbvision_scratch_free(usbvision); | 402 | usbvision_scratch_free(usbvision); |
408 | usbvision_decompress_free(usbvision); | 403 | usbvision_decompress_free(usbvision); |
409 | } | 404 | } |
@@ -476,6 +471,7 @@ static int usbvision_v4l2_close(struct inode *inode, struct file *file) | |||
476 | 471 | ||
477 | usbvision_decompress_free(usbvision); | 472 | usbvision_decompress_free(usbvision); |
478 | usbvision_frames_free(usbvision); | 473 | usbvision_frames_free(usbvision); |
474 | usbvision_empty_framequeues(usbvision); | ||
479 | usbvision_scratch_free(usbvision); | 475 | usbvision_scratch_free(usbvision); |
480 | 476 | ||
481 | usbvision->user--; | 477 | usbvision->user--; |
@@ -489,7 +485,7 @@ static int usbvision_v4l2_close(struct inode *inode, struct file *file) | |||
489 | up(&usbvision->lock); | 485 | up(&usbvision->lock); |
490 | 486 | ||
491 | if (usbvision->remove_pending) { | 487 | if (usbvision->remove_pending) { |
492 | info("%s: Final disconnect", __FUNCTION__); | 488 | printk(KERN_INFO "%s: Final disconnect\n", __FUNCTION__); |
493 | usbvision_release(usbvision); | 489 | usbvision_release(usbvision); |
494 | } | 490 | } |
495 | 491 | ||
@@ -519,27 +515,8 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file, | |||
519 | 515 | ||
520 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 516 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
521 | /* ioctls to allow direct acces to the NT100x registers */ | 517 | /* ioctls to allow direct acces to the NT100x registers */ |
522 | case VIDIOC_INT_G_REGISTER: | 518 | case VIDIOC_DBG_G_REGISTER: |
523 | { | 519 | case VIDIOC_DBG_S_REGISTER: |
524 | struct v4l2_register *reg = arg; | ||
525 | int errCode; | ||
526 | |||
527 | if (reg->i2c_id != 0) | ||
528 | return -EINVAL; | ||
529 | /* NT100x has a 8-bit register space */ | ||
530 | errCode = usbvision_read_reg(usbvision, reg->reg&0xff); | ||
531 | if (errCode < 0) { | ||
532 | err("%s: VIDIOC_INT_G_REGISTER failed: error %d", __FUNCTION__, errCode); | ||
533 | } | ||
534 | else { | ||
535 | reg->val=(unsigned char)errCode; | ||
536 | PDEBUG(DBG_IOCTL, "VIDIOC_INT_G_REGISTER reg=0x%02X, value=0x%02X", | ||
537 | (unsigned int)reg->reg, reg->val); | ||
538 | errCode = 0; // No error | ||
539 | } | ||
540 | return errCode; | ||
541 | } | ||
542 | case VIDIOC_INT_S_REGISTER: | ||
543 | { | 520 | { |
544 | struct v4l2_register *reg = arg; | 521 | struct v4l2_register *reg = arg; |
545 | int errCode; | 522 | int errCode; |
@@ -548,15 +525,22 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file, | |||
548 | return -EINVAL; | 525 | return -EINVAL; |
549 | if (!capable(CAP_SYS_ADMIN)) | 526 | if (!capable(CAP_SYS_ADMIN)) |
550 | return -EPERM; | 527 | return -EPERM; |
551 | errCode = usbvision_write_reg(usbvision, reg->reg&0xff, reg->val); | 528 | /* NT100x has a 8-bit register space */ |
529 | if (cmd == VIDIOC_DBG_G_REGISTER) | ||
530 | errCode = usbvision_read_reg(usbvision, reg->reg&0xff); | ||
531 | else | ||
532 | errCode = usbvision_write_reg(usbvision, reg->reg&0xff, reg->val); | ||
552 | if (errCode < 0) { | 533 | if (errCode < 0) { |
553 | err("%s: VIDIOC_INT_S_REGISTER failed: error %d", __FUNCTION__, errCode); | 534 | err("%s: VIDIOC_DBG_%c_REGISTER failed: error %d", __FUNCTION__, |
554 | } | 535 | cmd == VIDIOC_DBG_G_REGISTER ? 'G' : 'S', errCode); |
555 | else { | 536 | return errCode; |
556 | PDEBUG(DBG_IOCTL, "VIDIOC_INT_S_REGISTER reg=0x%02X, value=0x%02X", | ||
557 | (unsigned int)reg->reg, reg->val); | ||
558 | errCode = 0; | ||
559 | } | 537 | } |
538 | if (cmd == VIDIOC_DBG_S_REGISTER) | ||
539 | reg->val = (u8)errCode; | ||
540 | |||
541 | PDEBUG(DBG_IOCTL, "VIDIOC_DBG_%c_REGISTER reg=0x%02X, value=0x%02X", | ||
542 | cmd == VIDIOC_DBG_G_REGISTER ? 'G' : 'S', | ||
543 | (unsigned int)reg->reg, reg->val); | ||
560 | return 0; | 544 | return 0; |
561 | } | 545 | } |
562 | #endif | 546 | #endif |
@@ -792,8 +776,8 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file, | |||
792 | case VIDIOC_G_CTRL: | 776 | case VIDIOC_G_CTRL: |
793 | { | 777 | { |
794 | struct v4l2_control *ctrl = arg; | 778 | struct v4l2_control *ctrl = arg; |
795 | PDEBUG(DBG_IOCTL,"VIDIOC_G_CTRL id=%x value=%x",ctrl->id,ctrl->value); | ||
796 | call_i2c_clients(usbvision, VIDIOC_G_CTRL, ctrl); | 779 | call_i2c_clients(usbvision, VIDIOC_G_CTRL, ctrl); |
780 | PDEBUG(DBG_IOCTL,"VIDIOC_G_CTRL id=%x value=%x",ctrl->id,ctrl->value); | ||
797 | return 0; | 781 | return 0; |
798 | } | 782 | } |
799 | case VIDIOC_S_CTRL: | 783 | case VIDIOC_S_CTRL: |
@@ -821,7 +805,9 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file, | |||
821 | return ret; | 805 | return ret; |
822 | } | 806 | } |
823 | 807 | ||
808 | usbvision_frames_free(usbvision); | ||
824 | usbvision_empty_framequeues(usbvision); | 809 | usbvision_empty_framequeues(usbvision); |
810 | vr->count = usbvision_frames_alloc(usbvision,vr->count); | ||
825 | 811 | ||
826 | usbvision->curFrame = NULL; | 812 | usbvision->curFrame = NULL; |
827 | 813 | ||
@@ -838,7 +824,7 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file, | |||
838 | if(vb->type != V4L2_CAP_VIDEO_CAPTURE) { | 824 | if(vb->type != V4L2_CAP_VIDEO_CAPTURE) { |
839 | return -EINVAL; | 825 | return -EINVAL; |
840 | } | 826 | } |
841 | if(vb->index>=USBVISION_NUMFRAMES) { | 827 | if(vb->index>=usbvision->num_frames) { |
842 | return -EINVAL; | 828 | return -EINVAL; |
843 | } | 829 | } |
844 | // Updating the corresponding frame state | 830 | // Updating the corresponding frame state |
@@ -852,7 +838,7 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file, | |||
852 | vb->flags |= V4L2_BUF_FLAG_MAPPED; | 838 | vb->flags |= V4L2_BUF_FLAG_MAPPED; |
853 | vb->memory = V4L2_MEMORY_MMAP; | 839 | vb->memory = V4L2_MEMORY_MMAP; |
854 | 840 | ||
855 | vb->m.offset = vb->index*usbvision->max_frame_size; | 841 | vb->m.offset = vb->index*PAGE_ALIGN(usbvision->max_frame_size); |
856 | 842 | ||
857 | vb->memory = V4L2_MEMORY_MMAP; | 843 | vb->memory = V4L2_MEMORY_MMAP; |
858 | vb->field = V4L2_FIELD_NONE; | 844 | vb->field = V4L2_FIELD_NONE; |
@@ -871,7 +857,7 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file, | |||
871 | if(vb->type != V4L2_CAP_VIDEO_CAPTURE) { | 857 | if(vb->type != V4L2_CAP_VIDEO_CAPTURE) { |
872 | return -EINVAL; | 858 | return -EINVAL; |
873 | } | 859 | } |
874 | if(vb->index>=USBVISION_NUMFRAMES) { | 860 | if(vb->index>=usbvision->num_frames) { |
875 | return -EINVAL; | 861 | return -EINVAL; |
876 | } | 862 | } |
877 | 863 | ||
@@ -1041,6 +1027,7 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file, | |||
1041 | if ((ret = usbvision_stream_interrupt(usbvision))) | 1027 | if ((ret = usbvision_stream_interrupt(usbvision))) |
1042 | return ret; | 1028 | return ret; |
1043 | } | 1029 | } |
1030 | usbvision_frames_free(usbvision); | ||
1044 | usbvision_empty_framequeues(usbvision); | 1031 | usbvision_empty_framequeues(usbvision); |
1045 | 1032 | ||
1046 | usbvision->curFrame = NULL; | 1033 | usbvision->curFrame = NULL; |
@@ -1087,12 +1074,24 @@ static ssize_t usbvision_v4l2_read(struct file *file, char __user *buf, | |||
1087 | if (!USBVISION_IS_OPERATIONAL(usbvision) || (buf == NULL)) | 1074 | if (!USBVISION_IS_OPERATIONAL(usbvision) || (buf == NULL)) |
1088 | return -EFAULT; | 1075 | return -EFAULT; |
1089 | 1076 | ||
1090 | /* no stream is running, make it running ! */ | 1077 | /* This entry point is compatible with the mmap routines so that a user can do either |
1091 | usbvision->streaming = Stream_On; | 1078 | VIDIOC_QBUF/VIDIOC_DQBUF to get frames or call read on the device. */ |
1092 | call_i2c_clients(usbvision,VIDIOC_STREAMON , NULL); | 1079 | if(!usbvision->num_frames) { |
1080 | /* First, allocate some frames to work with if this has not been done with | ||
1081 | VIDIOC_REQBUF */ | ||
1082 | usbvision_frames_free(usbvision); | ||
1083 | usbvision_empty_framequeues(usbvision); | ||
1084 | usbvision_frames_alloc(usbvision,USBVISION_NUMFRAMES); | ||
1085 | } | ||
1086 | |||
1087 | if(usbvision->streaming != Stream_On) { | ||
1088 | /* no stream is running, make it running ! */ | ||
1089 | usbvision->streaming = Stream_On; | ||
1090 | call_i2c_clients(usbvision,VIDIOC_STREAMON , NULL); | ||
1091 | } | ||
1093 | 1092 | ||
1094 | /* First, enqueue as many frames as possible (like a user of VIDIOC_QBUF would do) */ | 1093 | /* Then, enqueue as many frames as possible (like a user of VIDIOC_QBUF would do) */ |
1095 | for(i=0;i<USBVISION_NUMFRAMES;i++) { | 1094 | for(i=0;i<usbvision->num_frames;i++) { |
1096 | frame = &usbvision->frame[i]; | 1095 | frame = &usbvision->frame[i]; |
1097 | if(frame->grabstate == FrameState_Unused) { | 1096 | if(frame->grabstate == FrameState_Unused) { |
1098 | /* Mark it as ready and enqueue frame */ | 1097 | /* Mark it as ready and enqueue frame */ |
@@ -1169,6 +1168,8 @@ static int usbvision_v4l2_mmap(struct file *file, struct vm_area_struct *vma) | |||
1169 | struct video_device *dev = video_devdata(file); | 1168 | struct video_device *dev = video_devdata(file); |
1170 | struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev); | 1169 | struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev); |
1171 | 1170 | ||
1171 | PDEBUG(DBG_MMAP, "mmap"); | ||
1172 | |||
1172 | down(&usbvision->lock); | 1173 | down(&usbvision->lock); |
1173 | 1174 | ||
1174 | if (!USBVISION_IS_OPERATIONAL(usbvision)) { | 1175 | if (!USBVISION_IS_OPERATIONAL(usbvision)) { |
@@ -1177,16 +1178,16 @@ static int usbvision_v4l2_mmap(struct file *file, struct vm_area_struct *vma) | |||
1177 | } | 1178 | } |
1178 | 1179 | ||
1179 | if (!(vma->vm_flags & VM_WRITE) || | 1180 | if (!(vma->vm_flags & VM_WRITE) || |
1180 | size != PAGE_ALIGN(usbvision->curwidth*usbvision->curheight*usbvision->palette.bytes_per_pixel)) { | 1181 | size != PAGE_ALIGN(usbvision->max_frame_size)) { |
1181 | up(&usbvision->lock); | 1182 | up(&usbvision->lock); |
1182 | return -EINVAL; | 1183 | return -EINVAL; |
1183 | } | 1184 | } |
1184 | 1185 | ||
1185 | for (i = 0; i < USBVISION_NUMFRAMES; i++) { | 1186 | for (i = 0; i < usbvision->num_frames; i++) { |
1186 | if (((usbvision->max_frame_size*i) >> PAGE_SHIFT) == vma->vm_pgoff) | 1187 | if (((PAGE_ALIGN(usbvision->max_frame_size)*i) >> PAGE_SHIFT) == vma->vm_pgoff) |
1187 | break; | 1188 | break; |
1188 | } | 1189 | } |
1189 | if (i == USBVISION_NUMFRAMES) { | 1190 | if (i == usbvision->num_frames) { |
1190 | PDEBUG(DBG_MMAP, "mmap: user supplied mapping address is out of range"); | 1191 | PDEBUG(DBG_MMAP, "mmap: user supplied mapping address is out of range"); |
1191 | up(&usbvision->lock); | 1192 | up(&usbvision->lock); |
1192 | return -EINVAL; | 1193 | return -EINVAL; |
@@ -1242,6 +1243,13 @@ static int usbvision_radio_open(struct inode *inode, struct file *file) | |||
1242 | } | 1243 | } |
1243 | } | 1244 | } |
1244 | 1245 | ||
1246 | /* Alternate interface 1 is is the biggest frame size */ | ||
1247 | errCode = usbvision_set_alternate(usbvision); | ||
1248 | if (errCode < 0) { | ||
1249 | usbvision->last_error = errCode; | ||
1250 | return -EBUSY; | ||
1251 | } | ||
1252 | |||
1245 | // If so far no errors then we shall start the radio | 1253 | // If so far no errors then we shall start the radio |
1246 | usbvision->radio = 1; | 1254 | usbvision->radio = 1; |
1247 | call_i2c_clients(usbvision,AUDC_SET_RADIO,&usbvision->tuner_type); | 1255 | call_i2c_clients(usbvision,AUDC_SET_RADIO,&usbvision->tuner_type); |
@@ -1273,6 +1281,11 @@ static int usbvision_radio_close(struct inode *inode, struct file *file) | |||
1273 | 1281 | ||
1274 | down(&usbvision->lock); | 1282 | down(&usbvision->lock); |
1275 | 1283 | ||
1284 | /* Set packet size to 0 */ | ||
1285 | usbvision->ifaceAlt=0; | ||
1286 | errCode = usb_set_interface(usbvision->dev, usbvision->iface, | ||
1287 | usbvision->ifaceAlt); | ||
1288 | |||
1276 | usbvision_audio_off(usbvision); | 1289 | usbvision_audio_off(usbvision); |
1277 | usbvision->radio=0; | 1290 | usbvision->radio=0; |
1278 | usbvision->user--; | 1291 | usbvision->user--; |
@@ -1285,7 +1298,7 @@ static int usbvision_radio_close(struct inode *inode, struct file *file) | |||
1285 | up(&usbvision->lock); | 1298 | up(&usbvision->lock); |
1286 | 1299 | ||
1287 | if (usbvision->remove_pending) { | 1300 | if (usbvision->remove_pending) { |
1288 | info("%s: Final disconnect", __FUNCTION__); | 1301 | printk(KERN_INFO "%s: Final disconnect\n", __FUNCTION__); |
1289 | usbvision_release(usbvision); | 1302 | usbvision_release(usbvision); |
1290 | } | 1303 | } |
1291 | 1304 | ||
@@ -1611,7 +1624,7 @@ static int __devinit usbvision_register_video(struct usb_usbvision *usbvision) | |||
1611 | if (video_register_device(usbvision->vdev, VFL_TYPE_GRABBER, video_nr)<0) { | 1624 | if (video_register_device(usbvision->vdev, VFL_TYPE_GRABBER, video_nr)<0) { |
1612 | goto err_exit; | 1625 | goto err_exit; |
1613 | } | 1626 | } |
1614 | info("USBVision[%d]: registered USBVision Video device /dev/video%d [v4l2]", usbvision->nr,usbvision->vdev->minor & 0x1f); | 1627 | printk(KERN_INFO "USBVision[%d]: registered USBVision Video device /dev/video%d [v4l2]\n", usbvision->nr,usbvision->vdev->minor & 0x1f); |
1615 | 1628 | ||
1616 | // Radio Device: | 1629 | // Radio Device: |
1617 | if (usbvision_device_data[usbvision->DevModel].Radio) { | 1630 | if (usbvision_device_data[usbvision->DevModel].Radio) { |
@@ -1623,7 +1636,7 @@ static int __devinit usbvision_register_video(struct usb_usbvision *usbvision) | |||
1623 | if (video_register_device(usbvision->rdev, VFL_TYPE_RADIO, radio_nr)<0) { | 1636 | if (video_register_device(usbvision->rdev, VFL_TYPE_RADIO, radio_nr)<0) { |
1624 | goto err_exit; | 1637 | goto err_exit; |
1625 | } | 1638 | } |
1626 | info("USBVision[%d]: registered USBVision Radio device /dev/radio%d [v4l2]", usbvision->nr, usbvision->rdev->minor & 0x1f); | 1639 | printk(KERN_INFO "USBVision[%d]: registered USBVision Radio device /dev/radio%d [v4l2]\n", usbvision->nr, usbvision->rdev->minor & 0x1f); |
1627 | } | 1640 | } |
1628 | // vbi Device: | 1641 | // vbi Device: |
1629 | if (usbvision_device_data[usbvision->DevModel].vbi) { | 1642 | if (usbvision_device_data[usbvision->DevModel].vbi) { |
@@ -1634,7 +1647,7 @@ static int __devinit usbvision_register_video(struct usb_usbvision *usbvision) | |||
1634 | if (video_register_device(usbvision->vbi, VFL_TYPE_VBI, vbi_nr)<0) { | 1647 | if (video_register_device(usbvision->vbi, VFL_TYPE_VBI, vbi_nr)<0) { |
1635 | goto err_exit; | 1648 | goto err_exit; |
1636 | } | 1649 | } |
1637 | info("USBVision[%d]: registered USBVision VBI device /dev/vbi%d [v4l2] (Not Working Yet!)", usbvision->nr,usbvision->vbi->minor & 0x1f); | 1650 | printk(KERN_INFO "USBVision[%d]: registered USBVision VBI device /dev/vbi%d [v4l2] (Not Working Yet!)\n", usbvision->nr,usbvision->vbi->minor & 0x1f); |
1638 | } | 1651 | } |
1639 | // all done | 1652 | // all done |
1640 | return 0; | 1653 | return 0; |
@@ -1764,15 +1777,17 @@ static void usbvision_configure_video(struct usb_usbvision *usbvision) | |||
1764 | */ | 1777 | */ |
1765 | static int __devinit usbvision_probe(struct usb_interface *intf, const struct usb_device_id *devid) | 1778 | static int __devinit usbvision_probe(struct usb_interface *intf, const struct usb_device_id *devid) |
1766 | { | 1779 | { |
1767 | struct usb_device *dev = interface_to_usbdev(intf); | 1780 | struct usb_device *dev = usb_get_dev(interface_to_usbdev(intf)); |
1781 | struct usb_interface *uif; | ||
1768 | __u8 ifnum = intf->altsetting->desc.bInterfaceNumber; | 1782 | __u8 ifnum = intf->altsetting->desc.bInterfaceNumber; |
1769 | const struct usb_host_interface *interface; | 1783 | const struct usb_host_interface *interface; |
1770 | struct usb_usbvision *usbvision = NULL; | 1784 | struct usb_usbvision *usbvision = NULL; |
1771 | const struct usb_endpoint_descriptor *endpoint; | 1785 | const struct usb_endpoint_descriptor *endpoint; |
1772 | int model; | 1786 | int model,i; |
1773 | 1787 | ||
1774 | PDEBUG(DBG_PROBE, "VID=%#04x, PID=%#04x, ifnum=%u", | 1788 | PDEBUG(DBG_PROBE, "VID=%#04x, PID=%#04x, ifnum=%u", |
1775 | dev->descriptor.idVendor, dev->descriptor.idProduct, ifnum); | 1789 | dev->descriptor.idVendor, dev->descriptor.idProduct, ifnum); |
1790 | |||
1776 | /* Is it an USBVISION video dev? */ | 1791 | /* Is it an USBVISION video dev? */ |
1777 | model = 0; | 1792 | model = 0; |
1778 | for(model = 0; usbvision_device_data[model].idVendor; model++) { | 1793 | for(model = 0; usbvision_device_data[model].idVendor; model++) { |
@@ -1783,7 +1798,7 @@ static int __devinit usbvision_probe(struct usb_interface *intf, const struct us | |||
1783 | continue; | 1798 | continue; |
1784 | } | 1799 | } |
1785 | 1800 | ||
1786 | info("%s: %s found", __FUNCTION__, usbvision_device_data[model].ModelString); | 1801 | printk(KERN_INFO "%s: %s found\n", __FUNCTION__, usbvision_device_data[model].ModelString); |
1787 | break; | 1802 | break; |
1788 | } | 1803 | } |
1789 | 1804 | ||
@@ -1799,7 +1814,7 @@ static int __devinit usbvision_probe(struct usb_interface *intf, const struct us | |||
1799 | endpoint = &interface->endpoint[1].desc; | 1814 | endpoint = &interface->endpoint[1].desc; |
1800 | if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_ISOC) { | 1815 | if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_ISOC) { |
1801 | err("%s: interface %d. has non-ISO endpoint!", __FUNCTION__, ifnum); | 1816 | err("%s: interface %d. has non-ISO endpoint!", __FUNCTION__, ifnum); |
1802 | err("%s: Endpoint attribures %d", __FUNCTION__, endpoint->bmAttributes); | 1817 | err("%s: Endpoint attributes %d", __FUNCTION__, endpoint->bmAttributes); |
1803 | return -ENODEV; | 1818 | return -ENODEV; |
1804 | } | 1819 | } |
1805 | if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) { | 1820 | if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) { |
@@ -1826,6 +1841,28 @@ static int __devinit usbvision_probe(struct usb_interface *intf, const struct us | |||
1826 | 1841 | ||
1827 | down(&usbvision->lock); | 1842 | down(&usbvision->lock); |
1828 | 1843 | ||
1844 | /* compute alternate max packet sizes */ | ||
1845 | uif = dev->actconfig->interface[0]; | ||
1846 | |||
1847 | usbvision->num_alt=uif->num_altsetting; | ||
1848 | PDEBUG(DBG_PROBE, "Alternate settings: %i",usbvision->num_alt); | ||
1849 | usbvision->alt_max_pkt_size = kmalloc(32* | ||
1850 | usbvision->num_alt,GFP_KERNEL); | ||
1851 | if (usbvision->alt_max_pkt_size == NULL) { | ||
1852 | err("usbvision: out of memory!\n"); | ||
1853 | return -ENOMEM; | ||
1854 | } | ||
1855 | |||
1856 | for (i = 0; i < usbvision->num_alt ; i++) { | ||
1857 | u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[1].desc. | ||
1858 | wMaxPacketSize); | ||
1859 | usbvision->alt_max_pkt_size[i] = | ||
1860 | (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); | ||
1861 | PDEBUG(DBG_PROBE, "Alternate setting %i, max size= %i",i, | ||
1862 | usbvision->alt_max_pkt_size[i]); | ||
1863 | } | ||
1864 | |||
1865 | |||
1829 | usbvision->nr = usbvision_nr++; | 1866 | usbvision->nr = usbvision_nr++; |
1830 | 1867 | ||
1831 | usbvision->have_tuner = usbvision_device_data[model].Tuner; | 1868 | usbvision->have_tuner = usbvision_device_data[model].Tuner; |
@@ -1838,8 +1875,7 @@ static int __devinit usbvision_probe(struct usb_interface *intf, const struct us | |||
1838 | usbvision->DevModel = model; | 1875 | usbvision->DevModel = model; |
1839 | usbvision->remove_pending = 0; | 1876 | usbvision->remove_pending = 0; |
1840 | usbvision->iface = ifnum; | 1877 | usbvision->iface = ifnum; |
1841 | usbvision->ifaceAltInactive = 0; | 1878 | usbvision->ifaceAlt = 0; |
1842 | usbvision->ifaceAltActive = 1; | ||
1843 | usbvision->video_endp = endpoint->bEndpointAddress; | 1879 | usbvision->video_endp = endpoint->bEndpointAddress; |
1844 | usbvision->isocPacketSize = 0; | 1880 | usbvision->isocPacketSize = 0; |
1845 | usbvision->usb_bandwidth = 0; | 1881 | usbvision->usb_bandwidth = 0; |
@@ -1895,7 +1931,7 @@ static void __devexit usbvision_disconnect(struct usb_interface *intf) | |||
1895 | up(&usbvision->lock); | 1931 | up(&usbvision->lock); |
1896 | 1932 | ||
1897 | if (usbvision->user) { | 1933 | if (usbvision->user) { |
1898 | info("%s: In use, disconnect pending", __FUNCTION__); | 1934 | printk(KERN_INFO "%s: In use, disconnect pending\n", __FUNCTION__); |
1899 | wake_up_interruptible(&usbvision->wait_frame); | 1935 | wake_up_interruptible(&usbvision->wait_frame); |
1900 | wake_up_interruptible(&usbvision->wait_stream); | 1936 | wake_up_interruptible(&usbvision->wait_stream); |
1901 | } | 1937 | } |
@@ -2061,7 +2097,7 @@ static int __init usbvision_init(void) | |||
2061 | errCode = usb_register(&usbvision_driver); | 2097 | errCode = usb_register(&usbvision_driver); |
2062 | 2098 | ||
2063 | if (errCode == 0) { | 2099 | if (errCode == 0) { |
2064 | info(DRIVER_DESC " : " USBVISION_VERSION_STRING); | 2100 | printk(KERN_INFO DRIVER_DESC " : " USBVISION_VERSION_STRING "\n"); |
2065 | PDEBUG(DBG_PROBE, "success"); | 2101 | PDEBUG(DBG_PROBE, "success"); |
2066 | } | 2102 | } |
2067 | return errCode; | 2103 | return errCode; |
diff --git a/drivers/media/video/usbvision/usbvision.h b/drivers/media/video/usbvision/usbvision.h index e2bcaba93871..ad6afd3e42a4 100644 --- a/drivers/media/video/usbvision/usbvision.h +++ b/drivers/media/video/usbvision/usbvision.h | |||
@@ -33,6 +33,7 @@ | |||
33 | 33 | ||
34 | #include <linux/list.h> | 34 | #include <linux/list.h> |
35 | #include <linux/usb.h> | 35 | #include <linux/usb.h> |
36 | #include <linux/i2c.h> | ||
36 | #include <media/v4l2-common.h> | 37 | #include <media/v4l2-common.h> |
37 | #include <media/tuner.h> | 38 | #include <media/tuner.h> |
38 | #include <linux/videodev2.h> | 39 | #include <linux/videodev2.h> |
@@ -396,8 +397,11 @@ struct usb_usbvision { | |||
396 | 397 | ||
397 | /* Device structure */ | 398 | /* Device structure */ |
398 | struct usb_device *dev; | 399 | struct usb_device *dev; |
400 | /* usb transfer */ | ||
401 | int num_alt; /* Number of alternative settings */ | ||
402 | unsigned int *alt_max_pkt_size; /* array of wMaxPacketSize */ | ||
399 | unsigned char iface; /* Video interface number */ | 403 | unsigned char iface; /* Video interface number */ |
400 | unsigned char ifaceAltActive, ifaceAltInactive; /* Alt settings */ | 404 | unsigned char ifaceAlt; /* Alt settings */ |
401 | unsigned char Vin_Reg2_Preset; | 405 | unsigned char Vin_Reg2_Preset; |
402 | struct semaphore lock; | 406 | struct semaphore lock; |
403 | struct timer_list powerOffTimer; | 407 | struct timer_list powerOffTimer; |
@@ -421,6 +425,7 @@ struct usb_usbvision { | |||
421 | wait_queue_head_t wait_stream; /* Processes waiting */ | 425 | wait_queue_head_t wait_stream; /* Processes waiting */ |
422 | struct usbvision_frame *curFrame; // pointer to current frame, set by usbvision_find_header | 426 | struct usbvision_frame *curFrame; // pointer to current frame, set by usbvision_find_header |
423 | struct usbvision_frame frame[USBVISION_NUMFRAMES]; // frame buffer | 427 | struct usbvision_frame frame[USBVISION_NUMFRAMES]; // frame buffer |
428 | int num_frames; // number of frames allocated | ||
424 | struct usbvision_sbuf sbuf[USBVISION_NUMSBUF]; // S buffering | 429 | struct usbvision_sbuf sbuf[USBVISION_NUMSBUF]; // S buffering |
425 | volatile int remove_pending; /* If set then about to exit */ | 430 | volatile int remove_pending; /* If set then about to exit */ |
426 | 431 | ||
@@ -486,12 +491,11 @@ int usbvision_init_i2c(struct usb_usbvision *usbvision); | |||
486 | void call_i2c_clients(struct usb_usbvision *usbvision, unsigned int cmd,void *arg); | 491 | void call_i2c_clients(struct usb_usbvision *usbvision, unsigned int cmd,void *arg); |
487 | 492 | ||
488 | /* defined in usbvision-core.c */ | 493 | /* defined in usbvision-core.c */ |
489 | void usbvision_rvfree(void *mem, unsigned long size); | ||
490 | int usbvision_read_reg(struct usb_usbvision *usbvision, unsigned char reg); | 494 | int usbvision_read_reg(struct usb_usbvision *usbvision, unsigned char reg); |
491 | int usbvision_write_reg(struct usb_usbvision *usbvision, unsigned char reg, | 495 | int usbvision_write_reg(struct usb_usbvision *usbvision, unsigned char reg, |
492 | unsigned char value); | 496 | unsigned char value); |
493 | 497 | ||
494 | int usbvision_frames_alloc(struct usb_usbvision *usbvision); | 498 | int usbvision_frames_alloc(struct usb_usbvision *usbvision, int number_of_frames); |
495 | void usbvision_frames_free(struct usb_usbvision *usbvision); | 499 | void usbvision_frames_free(struct usb_usbvision *usbvision); |
496 | int usbvision_scratch_alloc(struct usb_usbvision *usbvision); | 500 | int usbvision_scratch_alloc(struct usb_usbvision *usbvision); |
497 | void usbvision_scratch_free(struct usb_usbvision *usbvision); | 501 | void usbvision_scratch_free(struct usb_usbvision *usbvision); |
@@ -502,6 +506,7 @@ int usbvision_setup(struct usb_usbvision *usbvision,int format); | |||
502 | int usbvision_init_isoc(struct usb_usbvision *usbvision); | 506 | int usbvision_init_isoc(struct usb_usbvision *usbvision); |
503 | int usbvision_restart_isoc(struct usb_usbvision *usbvision); | 507 | int usbvision_restart_isoc(struct usb_usbvision *usbvision); |
504 | void usbvision_stop_isoc(struct usb_usbvision *usbvision); | 508 | void usbvision_stop_isoc(struct usb_usbvision *usbvision); |
509 | int usbvision_set_alternate(struct usb_usbvision *dev); | ||
505 | 510 | ||
506 | int usbvision_set_audio(struct usb_usbvision *usbvision, int AudioChannel); | 511 | int usbvision_set_audio(struct usb_usbvision *usbvision, int AudioChannel); |
507 | int usbvision_audio_off(struct usb_usbvision *usbvision); | 512 | int usbvision_audio_off(struct usb_usbvision *usbvision); |
diff --git a/drivers/media/video/v4l1-compat.c b/drivers/media/video/v4l1-compat.c index 8a13e595304e..d2c1ae0dbfba 100644 --- a/drivers/media/video/v4l1-compat.c +++ b/drivers/media/video/v4l1-compat.c | |||
@@ -11,7 +11,7 @@ | |||
11 | * as published by the Free Software Foundation; either version | 11 | * as published by the Free Software Foundation; either version |
12 | * 2 of the License, or (at your option) any later version. | 12 | * 2 of the License, or (at your option) any later version. |
13 | * | 13 | * |
14 | * Author: Bill Dirks <bdirks@pacbell.net> | 14 | * Author: Bill Dirks <bill@thedirks.org> |
15 | * et al. | 15 | * et al. |
16 | * | 16 | * |
17 | */ | 17 | */ |
diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index b8ee37ded3c9..ddfd80c5618b 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c | |||
@@ -12,7 +12,7 @@ | |||
12 | * as published by the Free Software Foundation; either version | 12 | * as published by the Free Software Foundation; either version |
13 | * 2 of the License, or (at your option) any later version. | 13 | * 2 of the License, or (at your option) any later version. |
14 | * | 14 | * |
15 | * Author: Bill Dirks <bdirks@pacbell.net> | 15 | * Author: Bill Dirks <bill@thedirks.org> |
16 | * based on code by Alan Cox, <alan@cymru.net> | 16 | * based on code by Alan Cox, <alan@cymru.net> |
17 | * | 17 | * |
18 | */ | 18 | */ |
@@ -271,11 +271,6 @@ char *v4l2_type_names[] = { | |||
271 | [V4L2_BUF_TYPE_SLICED_VBI_OUTPUT] = "slicec-vbi-out", | 271 | [V4L2_BUF_TYPE_SLICED_VBI_OUTPUT] = "slicec-vbi-out", |
272 | }; | 272 | }; |
273 | 273 | ||
274 | static char *v4l2_memory_names[] = { | ||
275 | [V4L2_MEMORY_MMAP] = "mmap", | ||
276 | [V4L2_MEMORY_USERPTR] = "userptr", | ||
277 | [V4L2_MEMORY_OVERLAY] = "overlay", | ||
278 | }; | ||
279 | 274 | ||
280 | #define prt_names(a,arr) (((a)>=0)&&((a)<ARRAY_SIZE(arr)))?arr[a]:"unknown" | 275 | #define prt_names(a,arr) (((a)>=0)&&((a)<ARRAY_SIZE(arr)))?arr[a]:"unknown" |
281 | 276 | ||
@@ -400,9 +395,10 @@ static const char *v4l2_int_ioctls[] = { | |||
400 | [_IOC_NR(TUNER_SET_STANDBY)] = "TUNER_SET_STANDBY", | 395 | [_IOC_NR(TUNER_SET_STANDBY)] = "TUNER_SET_STANDBY", |
401 | [_IOC_NR(TDA9887_SET_CONFIG)] = "TDA9887_SET_CONFIG", | 396 | [_IOC_NR(TDA9887_SET_CONFIG)] = "TDA9887_SET_CONFIG", |
402 | 397 | ||
398 | [_IOC_NR(VIDIOC_DBG_S_REGISTER)] = "VIDIOC_DBG_S_REGISTER", | ||
399 | [_IOC_NR(VIDIOC_DBG_G_REGISTER)] = "VIDIOC_DBG_G_REGISTER", | ||
400 | |||
403 | [_IOC_NR(VIDIOC_INT_S_TUNER_MODE)] = "VIDIOC_INT_S_TUNER_MODE", | 401 | [_IOC_NR(VIDIOC_INT_S_TUNER_MODE)] = "VIDIOC_INT_S_TUNER_MODE", |
404 | [_IOC_NR(VIDIOC_INT_S_REGISTER)] = "VIDIOC_INT_S_REGISTER", | ||
405 | [_IOC_NR(VIDIOC_INT_G_REGISTER)] = "VIDIOC_INT_G_REGISTER", | ||
406 | [_IOC_NR(VIDIOC_INT_RESET)] = "VIDIOC_INT_RESET", | 402 | [_IOC_NR(VIDIOC_INT_RESET)] = "VIDIOC_INT_RESET", |
407 | [_IOC_NR(VIDIOC_INT_AUDIO_CLOCK_FREQ)] = "VIDIOC_INT_AUDIO_CLOCK_FREQ", | 403 | [_IOC_NR(VIDIOC_INT_AUDIO_CLOCK_FREQ)] = "VIDIOC_INT_AUDIO_CLOCK_FREQ", |
408 | [_IOC_NR(VIDIOC_INT_DECODE_VBI_LINE)] = "VIDIOC_INT_DECODE_VBI_LINE", | 404 | [_IOC_NR(VIDIOC_INT_DECODE_VBI_LINE)] = "VIDIOC_INT_DECODE_VBI_LINE", |
@@ -419,14 +415,6 @@ static const char *v4l2_int_ioctls[] = { | |||
419 | }; | 415 | }; |
420 | #define V4L2_INT_IOCTLS ARRAY_SIZE(v4l2_int_ioctls) | 416 | #define V4L2_INT_IOCTLS ARRAY_SIZE(v4l2_int_ioctls) |
421 | 417 | ||
422 | static void v4l_print_pix_fmt (char *s, struct v4l2_pix_format *fmt) | ||
423 | { | ||
424 | printk ("%s: width=%d, height=%d, format=%d, field=%s, " | ||
425 | "bytesperline=%d sizeimage=%d, colorspace=%d\n", s, | ||
426 | fmt->width,fmt->height,fmt->pixelformat, | ||
427 | prt_names(fmt->field,v4l2_field_names), | ||
428 | fmt->bytesperline,fmt->sizeimage,fmt->colorspace); | ||
429 | }; | ||
430 | 418 | ||
431 | /* Common ioctl debug function. This function can be used by | 419 | /* Common ioctl debug function. This function can be used by |
432 | external ioctl messages as well as internal V4L ioctl */ | 420 | external ioctl messages as well as internal V4L ioctl */ |
@@ -466,576 +454,6 @@ void v4l_printk_ioctl(unsigned int cmd) | |||
466 | } | 454 | } |
467 | } | 455 | } |
468 | 456 | ||
469 | /* Common ioctl debug function. This function can be used by | ||
470 | external ioctl messages as well as internal V4L ioctl and its | ||
471 | arguments */ | ||
472 | void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg) | ||
473 | { | ||
474 | printk(s); | ||
475 | printk(": "); | ||
476 | v4l_printk_ioctl(cmd); | ||
477 | switch (cmd) { | ||
478 | case VIDIOC_INT_G_CHIP_IDENT: | ||
479 | { | ||
480 | enum v4l2_chip_ident *p=arg; | ||
481 | printk ("%s: chip ident=%d\n", s, *p); | ||
482 | break; | ||
483 | } | ||
484 | case VIDIOC_G_PRIORITY: | ||
485 | case VIDIOC_S_PRIORITY: | ||
486 | { | ||
487 | enum v4l2_priority *p=arg; | ||
488 | printk ("%s: priority=%d\n", s, *p); | ||
489 | break; | ||
490 | } | ||
491 | case VIDIOC_INT_S_TUNER_MODE: | ||
492 | { | ||
493 | enum v4l2_tuner_type *p=arg; | ||
494 | printk ("%s: tuner type=%d\n", s, *p); | ||
495 | break; | ||
496 | } | ||
497 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | ||
498 | case DECODER_SET_VBI_BYPASS: | ||
499 | case DECODER_ENABLE_OUTPUT: | ||
500 | case DECODER_GET_STATUS: | ||
501 | case DECODER_SET_OUTPUT: | ||
502 | case DECODER_SET_INPUT: | ||
503 | case DECODER_SET_GPIO: | ||
504 | case DECODER_SET_NORM: | ||
505 | case VIDIOCCAPTURE: | ||
506 | case VIDIOCSYNC: | ||
507 | case VIDIOCSWRITEMODE: | ||
508 | #endif | ||
509 | case TUNER_SET_TYPE_ADDR: | ||
510 | case TUNER_SET_STANDBY: | ||
511 | case TDA9887_SET_CONFIG: | ||
512 | #ifdef __OLD_VIDIOC_ | ||
513 | case VIDIOC_OVERLAY_OLD: | ||
514 | #endif | ||
515 | case VIDIOC_STREAMOFF: | ||
516 | case VIDIOC_G_OUTPUT: | ||
517 | case VIDIOC_S_OUTPUT: | ||
518 | case VIDIOC_STREAMON: | ||
519 | case VIDIOC_G_INPUT: | ||
520 | case VIDIOC_OVERLAY: | ||
521 | case VIDIOC_S_INPUT: | ||
522 | { | ||
523 | int *p=arg; | ||
524 | printk ("%s: value=%d\n", s, *p); | ||
525 | break; | ||
526 | } | ||
527 | case VIDIOC_G_AUDIO: | ||
528 | case VIDIOC_S_AUDIO: | ||
529 | case VIDIOC_ENUMAUDIO: | ||
530 | #ifdef __OLD_VIDIOC_ | ||
531 | case VIDIOC_G_AUDIO_OLD: | ||
532 | #endif | ||
533 | { | ||
534 | struct v4l2_audio *p=arg; | ||
535 | |||
536 | printk ("%s: index=%d, name=%s, capability=%d, mode=%d\n", | ||
537 | s,p->index, p->name,p->capability, p->mode); | ||
538 | break; | ||
539 | } | ||
540 | case VIDIOC_G_AUDOUT: | ||
541 | case VIDIOC_S_AUDOUT: | ||
542 | case VIDIOC_ENUMAUDOUT: | ||
543 | #ifdef __OLD_VIDIOC_ | ||
544 | case VIDIOC_G_AUDOUT_OLD: | ||
545 | #endif | ||
546 | { | ||
547 | struct v4l2_audioout *p=arg; | ||
548 | printk ("%s: index=%d, name=%s, capability=%d, mode=%d\n", s, | ||
549 | p->index, p->name, p->capability,p->mode); | ||
550 | break; | ||
551 | } | ||
552 | case VIDIOC_QBUF: | ||
553 | case VIDIOC_DQBUF: | ||
554 | case VIDIOC_QUERYBUF: | ||
555 | { | ||
556 | struct v4l2_buffer *p=arg; | ||
557 | struct v4l2_timecode *tc=&p->timecode; | ||
558 | printk ("%s: %02ld:%02d:%02d.%08ld index=%d, type=%s, " | ||
559 | "bytesused=%d, flags=0x%08x, " | ||
560 | "field=%0d, sequence=%d, memory=%s, offset/userptr=0x%08lx\n", | ||
561 | s, | ||
562 | (p->timestamp.tv_sec/3600), | ||
563 | (int)(p->timestamp.tv_sec/60)%60, | ||
564 | (int)(p->timestamp.tv_sec%60), | ||
565 | p->timestamp.tv_usec, | ||
566 | p->index, | ||
567 | prt_names(p->type,v4l2_type_names), | ||
568 | p->bytesused,p->flags, | ||
569 | p->field,p->sequence, | ||
570 | prt_names(p->memory,v4l2_memory_names), | ||
571 | p->m.userptr); | ||
572 | printk ("%s: timecode= %02d:%02d:%02d type=%d, " | ||
573 | "flags=0x%08x, frames=%d, userbits=0x%08x\n", | ||
574 | s,tc->hours,tc->minutes,tc->seconds, | ||
575 | tc->type, tc->flags, tc->frames, *(__u32 *) tc->userbits); | ||
576 | break; | ||
577 | } | ||
578 | case VIDIOC_QUERYCAP: | ||
579 | { | ||
580 | struct v4l2_capability *p=arg; | ||
581 | printk ("%s: driver=%s, card=%s, bus=%s, version=0x%08x, " | ||
582 | "capabilities=0x%08x\n", s, | ||
583 | p->driver,p->card,p->bus_info, | ||
584 | p->version, | ||
585 | p->capabilities); | ||
586 | break; | ||
587 | } | ||
588 | case VIDIOC_G_CTRL: | ||
589 | case VIDIOC_S_CTRL: | ||
590 | #ifdef __OLD_VIDIOC_ | ||
591 | case VIDIOC_S_CTRL_OLD: | ||
592 | #endif | ||
593 | { | ||
594 | struct v4l2_control *p=arg; | ||
595 | printk ("%s: id=%d, value=%d\n", s, p->id, p->value); | ||
596 | break; | ||
597 | } | ||
598 | case VIDIOC_G_EXT_CTRLS: | ||
599 | case VIDIOC_S_EXT_CTRLS: | ||
600 | case VIDIOC_TRY_EXT_CTRLS: | ||
601 | { | ||
602 | struct v4l2_ext_controls *p = arg; | ||
603 | int i; | ||
604 | |||
605 | printk("%s: ctrl_class=%d, count=%d\n", s, p->ctrl_class, p->count); | ||
606 | for (i = 0; i < p->count; i++) { | ||
607 | struct v4l2_ext_control *c = &p->controls[i]; | ||
608 | if (cmd == VIDIOC_G_EXT_CTRLS) | ||
609 | printk("%s: id=%d\n", s, c->id); | ||
610 | else | ||
611 | printk("%s: id=%d, value=%d\n", s, c->id, c->value); | ||
612 | } | ||
613 | break; | ||
614 | } | ||
615 | case VIDIOC_G_CROP: | ||
616 | case VIDIOC_S_CROP: | ||
617 | { | ||
618 | struct v4l2_crop *p=arg; | ||
619 | /*FIXME: Should also show rect structs */ | ||
620 | printk ("%s: type=%d\n", s, p->type); | ||
621 | break; | ||
622 | } | ||
623 | case VIDIOC_CROPCAP: | ||
624 | #ifdef __OLD_VIDIOC_ | ||
625 | case VIDIOC_CROPCAP_OLD: | ||
626 | #endif | ||
627 | { | ||
628 | struct v4l2_cropcap *p=arg; | ||
629 | /*FIXME: Should also show rect structs */ | ||
630 | printk ("%s: type=%d\n", s, p->type); | ||
631 | break; | ||
632 | } | ||
633 | case VIDIOC_INT_DECODE_VBI_LINE: | ||
634 | { | ||
635 | struct v4l2_decode_vbi_line *p=arg; | ||
636 | printk ("%s: is_second_field=%d, ptr=0x%08lx, line=%d, " | ||
637 | "type=%d\n", s, | ||
638 | p->is_second_field,(unsigned long)p->p,p->line,p->type); | ||
639 | break; | ||
640 | } | ||
641 | case VIDIOC_ENUM_FMT: | ||
642 | { | ||
643 | struct v4l2_fmtdesc *p=arg; | ||
644 | printk ("%s: index=%d, type=%d, flags=%d, description=%s," | ||
645 | " pixelformat=%d\n", s, | ||
646 | p->index, p->type, p->flags,p->description, | ||
647 | p->pixelformat); | ||
648 | |||
649 | break; | ||
650 | } | ||
651 | case VIDIOC_G_FMT: | ||
652 | case VIDIOC_S_FMT: | ||
653 | case VIDIOC_TRY_FMT: | ||
654 | { | ||
655 | struct v4l2_format *p=arg; | ||
656 | printk ("%s: type=%s\n", s, | ||
657 | prt_names(p->type,v4l2_type_names)); | ||
658 | switch (p->type) { | ||
659 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
660 | v4l_print_pix_fmt (s, &p->fmt.pix); | ||
661 | break; | ||
662 | default: | ||
663 | break; | ||
664 | } | ||
665 | } | ||
666 | case VIDIOC_G_FBUF: | ||
667 | case VIDIOC_S_FBUF: | ||
668 | { | ||
669 | struct v4l2_framebuffer *p=arg; | ||
670 | printk ("%s: capability=%d, flags=%d, base=0x%08lx\n", s, | ||
671 | p->capability,p->flags, (unsigned long)p->base); | ||
672 | v4l_print_pix_fmt (s, &p->fmt); | ||
673 | break; | ||
674 | } | ||
675 | case VIDIOC_G_FREQUENCY: | ||
676 | case VIDIOC_S_FREQUENCY: | ||
677 | { | ||
678 | struct v4l2_frequency *p=arg; | ||
679 | printk ("%s: tuner=%d, type=%d, frequency=%d\n", s, | ||
680 | p->tuner,p->type,p->frequency); | ||
681 | break; | ||
682 | } | ||
683 | case VIDIOC_ENUMINPUT: | ||
684 | { | ||
685 | struct v4l2_input *p=arg; | ||
686 | printk ("%s: index=%d, name=%s, type=%d, audioset=%d, " | ||
687 | "tuner=%d, std=%Ld, status=%d\n", s, | ||
688 | p->index,p->name,p->type,p->audioset, | ||
689 | p->tuner, | ||
690 | (unsigned long long)p->std, | ||
691 | p->status); | ||
692 | break; | ||
693 | } | ||
694 | case VIDIOC_G_JPEGCOMP: | ||
695 | case VIDIOC_S_JPEGCOMP: | ||
696 | { | ||
697 | struct v4l2_jpegcompression *p=arg; | ||
698 | printk ("%s: quality=%d, APPn=%d, APP_len=%d, COM_len=%d," | ||
699 | " jpeg_markers=%d\n", s, | ||
700 | p->quality,p->APPn,p->APP_len, | ||
701 | p->COM_len,p->jpeg_markers); | ||
702 | break; | ||
703 | } | ||
704 | case VIDIOC_G_MODULATOR: | ||
705 | case VIDIOC_S_MODULATOR: | ||
706 | { | ||
707 | struct v4l2_modulator *p=arg; | ||
708 | printk ("%s: index=%d, name=%s, capability=%d, rangelow=%d," | ||
709 | " rangehigh=%d, txsubchans=%d\n", s, | ||
710 | p->index, p->name,p->capability,p->rangelow, | ||
711 | p->rangehigh,p->txsubchans); | ||
712 | break; | ||
713 | } | ||
714 | case VIDIOC_G_MPEGCOMP: | ||
715 | case VIDIOC_S_MPEGCOMP: | ||
716 | { | ||
717 | struct v4l2_mpeg_compression *p=arg; | ||
718 | /*FIXME: Several fields not shown */ | ||
719 | printk ("%s: ts_pid_pmt=%d, ts_pid_audio=%d, ts_pid_video=%d, " | ||
720 | "ts_pid_pcr=%d, ps_size=%d, au_sample_rate=%d, " | ||
721 | "au_pesid=%c, vi_frame_rate=%d, vi_frames_per_gop=%d, " | ||
722 | "vi_bframes_count=%d, vi_pesid=%c\n", s, | ||
723 | p->ts_pid_pmt,p->ts_pid_audio, p->ts_pid_video, | ||
724 | p->ts_pid_pcr, p->ps_size, p->au_sample_rate, | ||
725 | p->au_pesid, p->vi_frame_rate, | ||
726 | p->vi_frames_per_gop, p->vi_bframes_count, | ||
727 | p->vi_pesid); | ||
728 | break; | ||
729 | } | ||
730 | case VIDIOC_ENUMOUTPUT: | ||
731 | { | ||
732 | struct v4l2_output *p=arg; | ||
733 | printk ("%s: index=%d, name=%s,type=%d, audioset=%d, " | ||
734 | "modulator=%d, std=%Ld\n", | ||
735 | s,p->index,p->name,p->type,p->audioset, | ||
736 | p->modulator, | ||
737 | (unsigned long long)p->std); | ||
738 | break; | ||
739 | } | ||
740 | case VIDIOC_QUERYCTRL: | ||
741 | { | ||
742 | struct v4l2_queryctrl *p=arg; | ||
743 | printk ("%s: id=%d, type=%d, name=%s, min/max=%d/%d," | ||
744 | " step=%d, default=%d, flags=0x%08x\n", s, | ||
745 | p->id,p->type,p->name,p->minimum,p->maximum, | ||
746 | p->step,p->default_value,p->flags); | ||
747 | break; | ||
748 | } | ||
749 | case VIDIOC_QUERYMENU: | ||
750 | { | ||
751 | struct v4l2_querymenu *p=arg; | ||
752 | printk ("%s: id=%d, index=%d, name=%s\n", s, | ||
753 | p->id,p->index,p->name); | ||
754 | break; | ||
755 | } | ||
756 | case VIDIOC_INT_G_REGISTER: | ||
757 | case VIDIOC_INT_S_REGISTER: | ||
758 | { | ||
759 | struct v4l2_register *p=arg; | ||
760 | printk ("%s: i2c_id=%d, reg=%lu, val=%d\n", s, | ||
761 | p->i2c_id,p->reg,p->val); | ||
762 | |||
763 | break; | ||
764 | } | ||
765 | case VIDIOC_REQBUFS: | ||
766 | { | ||
767 | struct v4l2_requestbuffers *p=arg; | ||
768 | printk ("%s: count=%d, type=%s, memory=%s\n", s, | ||
769 | p->count, | ||
770 | prt_names(p->type,v4l2_type_names), | ||
771 | prt_names(p->memory,v4l2_memory_names)); | ||
772 | break; | ||
773 | } | ||
774 | case VIDIOC_INT_S_AUDIO_ROUTING: | ||
775 | case VIDIOC_INT_S_VIDEO_ROUTING: | ||
776 | case VIDIOC_INT_G_AUDIO_ROUTING: | ||
777 | case VIDIOC_INT_G_VIDEO_ROUTING: | ||
778 | { | ||
779 | struct v4l2_routing *p=arg; | ||
780 | printk ("%s: input=0x%x, output=0x%x\n", s, p->input, p->output); | ||
781 | break; | ||
782 | } | ||
783 | case VIDIOC_INT_S_CRYSTAL_FREQ: | ||
784 | { | ||
785 | struct v4l2_crystal_freq *p=arg; | ||
786 | printk ("%s: freq=%u, flags=0x%x\n", s, p->freq, p->flags); | ||
787 | break; | ||
788 | } | ||
789 | case VIDIOC_G_SLICED_VBI_CAP: | ||
790 | { | ||
791 | struct v4l2_sliced_vbi_cap *p=arg; | ||
792 | printk ("%s: service_set=%d\n", s, | ||
793 | p->service_set); | ||
794 | break; | ||
795 | } | ||
796 | case VIDIOC_INT_S_VBI_DATA: | ||
797 | case VIDIOC_INT_G_VBI_DATA: | ||
798 | { | ||
799 | struct v4l2_sliced_vbi_data *p=arg; | ||
800 | printk ("%s: id=%d, field=%d, line=%d\n", s, | ||
801 | p->id, p->field, p->line); | ||
802 | break; | ||
803 | } | ||
804 | case VIDIOC_ENUMSTD: | ||
805 | { | ||
806 | struct v4l2_standard *p=arg; | ||
807 | printk ("%s: index=%d, id=%Ld, name=%s, fps=%d/%d, " | ||
808 | "framelines=%d\n", s, p->index, | ||
809 | (unsigned long long)p->id, p->name, | ||
810 | p->frameperiod.numerator, | ||
811 | p->frameperiod.denominator, | ||
812 | p->framelines); | ||
813 | |||
814 | break; | ||
815 | } | ||
816 | case VIDIOC_G_PARM: | ||
817 | case VIDIOC_S_PARM: | ||
818 | #ifdef __OLD_VIDIOC_ | ||
819 | case VIDIOC_S_PARM_OLD: | ||
820 | #endif | ||
821 | { | ||
822 | struct v4l2_streamparm *p=arg; | ||
823 | printk ("%s: type=%d\n", s, p->type); | ||
824 | |||
825 | break; | ||
826 | } | ||
827 | case VIDIOC_G_TUNER: | ||
828 | case VIDIOC_S_TUNER: | ||
829 | { | ||
830 | struct v4l2_tuner *p=arg; | ||
831 | printk ("%s: index=%d, name=%s, type=%d, capability=%d, " | ||
832 | "rangelow=%d, rangehigh=%d, signal=%d, afc=%d, " | ||
833 | "rxsubchans=%d, audmode=%d\n", s, | ||
834 | p->index, p->name, p->type, | ||
835 | p->capability, p->rangelow,p->rangehigh, | ||
836 | p->rxsubchans, p->audmode, p->signal, | ||
837 | p->afc); | ||
838 | break; | ||
839 | } | ||
840 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | ||
841 | case VIDIOCGVBIFMT: | ||
842 | case VIDIOCSVBIFMT: | ||
843 | { | ||
844 | struct vbi_format *p=arg; | ||
845 | printk ("%s: sampling_rate=%d, samples_per_line=%d, " | ||
846 | "sample_format=%d, start=%d/%d, count=%d/%d, flags=%d\n", s, | ||
847 | p->sampling_rate,p->samples_per_line, | ||
848 | p->sample_format,p->start[0],p->start[1], | ||
849 | p->count[0],p->count[1],p->flags); | ||
850 | break; | ||
851 | } | ||
852 | case VIDIOCGAUDIO: | ||
853 | case VIDIOCSAUDIO: | ||
854 | { | ||
855 | struct video_audio *p=arg; | ||
856 | printk ("%s: audio=%d, volume=%d, bass=%d, treble=%d, " | ||
857 | "flags=%d, name=%s, mode=%d, balance=%d, step=%d\n", | ||
858 | s,p->audio,p->volume,p->bass, p->treble, | ||
859 | p->flags,p->name,p->mode,p->balance,p->step); | ||
860 | break; | ||
861 | } | ||
862 | case VIDIOCGFBUF: | ||
863 | case VIDIOCSFBUF: | ||
864 | { | ||
865 | struct video_buffer *p=arg; | ||
866 | printk ("%s: base=%08lx, height=%d, width=%d, depth=%d, " | ||
867 | "bytesperline=%d\n", s, | ||
868 | (unsigned long) p->base, p->height, p->width, | ||
869 | p->depth,p->bytesperline); | ||
870 | break; | ||
871 | } | ||
872 | case VIDIOCGCAP: | ||
873 | { | ||
874 | struct video_capability *p=arg; | ||
875 | printk ("%s: name=%s, type=%d, channels=%d, audios=%d, " | ||
876 | "maxwidth=%d, maxheight=%d, minwidth=%d, minheight=%d\n", | ||
877 | s,p->name,p->type,p->channels,p->audios, | ||
878 | p->maxwidth,p->maxheight,p->minwidth, | ||
879 | p->minheight); | ||
880 | |||
881 | break; | ||
882 | } | ||
883 | case VIDIOCGCAPTURE: | ||
884 | case VIDIOCSCAPTURE: | ||
885 | { | ||
886 | struct video_capture *p=arg; | ||
887 | printk ("%s: x=%d, y=%d, width=%d, height=%d, decimation=%d," | ||
888 | " flags=%d\n", s, | ||
889 | p->x, p->y,p->width, p->height, | ||
890 | p->decimation,p->flags); | ||
891 | break; | ||
892 | } | ||
893 | case VIDIOCGCHAN: | ||
894 | case VIDIOCSCHAN: | ||
895 | { | ||
896 | struct video_channel *p=arg; | ||
897 | printk ("%s: channel=%d, name=%s, tuners=%d, flags=%d, " | ||
898 | "type=%d, norm=%d\n", s, | ||
899 | p->channel,p->name,p->tuners, | ||
900 | p->flags,p->type,p->norm); | ||
901 | |||
902 | break; | ||
903 | } | ||
904 | case VIDIOCSMICROCODE: | ||
905 | { | ||
906 | struct video_code *p=arg; | ||
907 | printk ("%s: loadwhat=%s, datasize=%d\n", s, | ||
908 | p->loadwhat,p->datasize); | ||
909 | break; | ||
910 | } | ||
911 | case DECODER_GET_CAPABILITIES: | ||
912 | { | ||
913 | struct video_decoder_capability *p=arg; | ||
914 | printk ("%s: flags=%d, inputs=%d, outputs=%d\n", s, | ||
915 | p->flags,p->inputs,p->outputs); | ||
916 | break; | ||
917 | } | ||
918 | case DECODER_INIT: | ||
919 | { | ||
920 | struct video_decoder_init *p=arg; | ||
921 | printk ("%s: len=%c\n", s, p->len); | ||
922 | break; | ||
923 | } | ||
924 | case VIDIOCGPLAYINFO: | ||
925 | { | ||
926 | struct video_info *p=arg; | ||
927 | printk ("%s: frame_count=%d, h_size=%d, v_size=%d, " | ||
928 | "smpte_timecode=%d, picture_type=%d, " | ||
929 | "temporal_reference=%d, user_data=%s\n", s, | ||
930 | p->frame_count, p->h_size, | ||
931 | p->v_size, p->smpte_timecode, | ||
932 | p->picture_type, p->temporal_reference, | ||
933 | p->user_data); | ||
934 | break; | ||
935 | } | ||
936 | case VIDIOCKEY: | ||
937 | { | ||
938 | struct video_key *p=arg; | ||
939 | printk ("%s: key=%s, flags=%d\n", s, | ||
940 | p->key, p->flags); | ||
941 | break; | ||
942 | } | ||
943 | case VIDIOCGMBUF: | ||
944 | { | ||
945 | struct video_mbuf *p=arg; | ||
946 | printk ("%s: size=%d, frames=%d, offsets=0x%08lx\n", s, | ||
947 | p->size, | ||
948 | p->frames, | ||
949 | (unsigned long)p->offsets); | ||
950 | break; | ||
951 | } | ||
952 | case VIDIOCMCAPTURE: | ||
953 | { | ||
954 | struct video_mmap *p=arg; | ||
955 | printk ("%s: frame=%d, height=%d, width=%d, format=%d\n", s, | ||
956 | p->frame, | ||
957 | p->height, p->width, | ||
958 | p->format); | ||
959 | break; | ||
960 | } | ||
961 | case VIDIOCGPICT: | ||
962 | case VIDIOCSPICT: | ||
963 | case DECODER_SET_PICTURE: | ||
964 | { | ||
965 | struct video_picture *p=arg; | ||
966 | |||
967 | printk ("%s: brightness=%d, hue=%d, colour=%d, contrast=%d," | ||
968 | " whiteness=%d, depth=%d, palette=%d\n", s, | ||
969 | p->brightness, p->hue, p->colour, | ||
970 | p->contrast, p->whiteness, p->depth, | ||
971 | p->palette); | ||
972 | break; | ||
973 | } | ||
974 | case VIDIOCSPLAYMODE: | ||
975 | { | ||
976 | struct video_play_mode *p=arg; | ||
977 | printk ("%s: mode=%d, p1=%d, p2=%d\n", s, | ||
978 | p->mode,p->p1,p->p2); | ||
979 | break; | ||
980 | } | ||
981 | case VIDIOCGTUNER: | ||
982 | case VIDIOCSTUNER: | ||
983 | { | ||
984 | struct video_tuner *p=arg; | ||
985 | printk ("%s: tuner=%d, name=%s, rangelow=%ld, rangehigh=%ld, " | ||
986 | "flags=%d, mode=%d, signal=%d\n", s, | ||
987 | p->tuner, p->name,p->rangelow, p->rangehigh, | ||
988 | p->flags,p->mode, p->signal); | ||
989 | break; | ||
990 | } | ||
991 | case VIDIOCGUNIT: | ||
992 | { | ||
993 | struct video_unit *p=arg; | ||
994 | printk ("%s: video=%d, vbi=%d, radio=%d, audio=%d, " | ||
995 | "teletext=%d\n", s, | ||
996 | p->video,p->vbi,p->radio,p->audio,p->teletext); | ||
997 | break; | ||
998 | } | ||
999 | case VIDIOCGWIN: | ||
1000 | case VIDIOCSWIN: | ||
1001 | { | ||
1002 | struct video_window *p=arg; | ||
1003 | printk ("%s: x=%d, y=%d, width=%d, height=%d, chromakey=%d," | ||
1004 | " flags=%d, clipcount=%d\n", s, | ||
1005 | p->x, p->y,p->width, p->height, | ||
1006 | p->chromakey,p->flags, | ||
1007 | p->clipcount); | ||
1008 | break; | ||
1009 | } | ||
1010 | case VIDIOCGFREQ: | ||
1011 | case VIDIOCSFREQ: | ||
1012 | { | ||
1013 | unsigned long *p=arg; | ||
1014 | printk ("%s: value=%lu\n", s, *p); | ||
1015 | break; | ||
1016 | } | ||
1017 | #endif | ||
1018 | case VIDIOC_INT_AUDIO_CLOCK_FREQ: | ||
1019 | case VIDIOC_INT_I2S_CLOCK_FREQ: | ||
1020 | case VIDIOC_INT_S_STANDBY: | ||
1021 | case VIDIOC_INT_RESET: | ||
1022 | { | ||
1023 | u32 *p=arg; | ||
1024 | |||
1025 | printk ("%s: value=%d\n", s, *p); | ||
1026 | break; | ||
1027 | } | ||
1028 | case VIDIOC_G_STD: | ||
1029 | case VIDIOC_S_STD: | ||
1030 | case VIDIOC_QUERYSTD: | ||
1031 | { | ||
1032 | v4l2_std_id *p=arg; | ||
1033 | |||
1034 | printk ("%s: value=%Lu\n", s, (unsigned long long)*p); | ||
1035 | break; | ||
1036 | } | ||
1037 | } | ||
1038 | } | ||
1039 | 457 | ||
1040 | /* ----------------------------------------------------------------- */ | 458 | /* ----------------------------------------------------------------- */ |
1041 | 459 | ||
@@ -1544,7 +962,6 @@ EXPORT_SYMBOL(v4l2_prio_check); | |||
1544 | EXPORT_SYMBOL(v4l2_field_names); | 962 | EXPORT_SYMBOL(v4l2_field_names); |
1545 | EXPORT_SYMBOL(v4l2_type_names); | 963 | EXPORT_SYMBOL(v4l2_type_names); |
1546 | EXPORT_SYMBOL(v4l_printk_ioctl); | 964 | EXPORT_SYMBOL(v4l_printk_ioctl); |
1547 | EXPORT_SYMBOL(v4l_printk_ioctl_arg); | ||
1548 | 965 | ||
1549 | EXPORT_SYMBOL(v4l2_ctrl_next); | 966 | EXPORT_SYMBOL(v4l2_ctrl_next); |
1550 | EXPORT_SYMBOL(v4l2_ctrl_check); | 967 | EXPORT_SYMBOL(v4l2_ctrl_check); |
diff --git a/drivers/media/video/video-buf.c b/drivers/media/video/video-buf.c index 6504a5866849..459786ff459a 100644 --- a/drivers/media/video/video-buf.c +++ b/drivers/media/video/video-buf.c | |||
@@ -148,6 +148,8 @@ int videobuf_dma_init_user(struct videobuf_dmabuf *dma, int direction, | |||
148 | dprintk(1,"init user [0x%lx+0x%lx => %d pages]\n", | 148 | dprintk(1,"init user [0x%lx+0x%lx => %d pages]\n", |
149 | data,size,dma->nr_pages); | 149 | data,size,dma->nr_pages); |
150 | 150 | ||
151 | dma->varea = (void *) data; | ||
152 | |||
151 | down_read(¤t->mm->mmap_sem); | 153 | down_read(¤t->mm->mmap_sem); |
152 | err = get_user_pages(current,current->mm, | 154 | err = get_user_pages(current,current->mm, |
153 | data & PAGE_MASK, dma->nr_pages, | 155 | data & PAGE_MASK, dma->nr_pages, |
@@ -285,6 +287,7 @@ int videobuf_dma_free(struct videobuf_dmabuf *dma) | |||
285 | 287 | ||
286 | vfree(dma->vmalloc); | 288 | vfree(dma->vmalloc); |
287 | dma->vmalloc = NULL; | 289 | dma->vmalloc = NULL; |
290 | dma->varea = NULL; | ||
288 | 291 | ||
289 | if (dma->bus_addr) { | 292 | if (dma->bus_addr) { |
290 | dma->bus_addr = 0; | 293 | dma->bus_addr = 0; |
diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c index a786c1f5b960..dc9b1ef678aa 100644 --- a/drivers/media/video/videodev.c +++ b/drivers/media/video/videodev.c | |||
@@ -1453,6 +1453,26 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, | |||
1453 | ret=vfd->vidioc_log_status(file, fh); | 1453 | ret=vfd->vidioc_log_status(file, fh); |
1454 | break; | 1454 | break; |
1455 | } | 1455 | } |
1456 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
1457 | case VIDIOC_DBG_G_REGISTER: | ||
1458 | { | ||
1459 | struct v4l2_register *p=arg; | ||
1460 | if (!capable(CAP_SYS_ADMIN)) | ||
1461 | ret=-EPERM; | ||
1462 | else if (vfd->vidioc_g_register) | ||
1463 | ret=vfd->vidioc_g_register(file, fh, p); | ||
1464 | break; | ||
1465 | } | ||
1466 | case VIDIOC_DBG_S_REGISTER: | ||
1467 | { | ||
1468 | struct v4l2_register *p=arg; | ||
1469 | if (!capable(CAP_SYS_ADMIN)) | ||
1470 | ret=-EPERM; | ||
1471 | else if (vfd->vidioc_s_register) | ||
1472 | ret=vfd->vidioc_s_register(file, fh, p); | ||
1473 | break; | ||
1474 | } | ||
1475 | #endif | ||
1456 | } /* switch */ | 1476 | } /* switch */ |
1457 | 1477 | ||
1458 | if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) { | 1478 | if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) { |
diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index cfb6b1f0402c..f7e1d1910374 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c | |||
@@ -145,7 +145,9 @@ struct vivi_buffer { | |||
145 | 145 | ||
146 | struct vivi_fmt *fmt; | 146 | struct vivi_fmt *fmt; |
147 | 147 | ||
148 | #ifdef CONFIG_VIVI_SCATTER | ||
148 | struct sg_to_addr *to_addr; | 149 | struct sg_to_addr *to_addr; |
150 | #endif | ||
149 | }; | 151 | }; |
150 | 152 | ||
151 | struct vivi_dmaqueue { | 153 | struct vivi_dmaqueue { |
@@ -230,6 +232,7 @@ static u8 bars[8][3] = { | |||
230 | #define TSTAMP_MAX_Y TSTAMP_MIN_Y+15 | 232 | #define TSTAMP_MAX_Y TSTAMP_MIN_Y+15 |
231 | #define TSTAMP_MIN_X 64 | 233 | #define TSTAMP_MIN_X 64 |
232 | 234 | ||
235 | #ifdef CONFIG_VIVI_SCATTER | ||
233 | static void prep_to_addr(struct sg_to_addr to_addr[], | 236 | static void prep_to_addr(struct sg_to_addr to_addr[], |
234 | struct videobuf_buffer *vb) | 237 | struct videobuf_buffer *vb) |
235 | { | 238 | { |
@@ -262,14 +265,24 @@ static int get_addr_pos(int pos, int pages, struct sg_to_addr to_addr[]) | |||
262 | 265 | ||
263 | return (p1); | 266 | return (p1); |
264 | } | 267 | } |
268 | #endif | ||
265 | 269 | ||
270 | #ifdef CONFIG_VIVI_SCATTER | ||
266 | static void gen_line(struct sg_to_addr to_addr[],int inipos,int pages,int wmax, | 271 | static void gen_line(struct sg_to_addr to_addr[],int inipos,int pages,int wmax, |
267 | int hmax, int line, char *timestr) | 272 | int hmax, int line, char *timestr) |
273 | #else | ||
274 | static void gen_line(char *basep,int inipos,int wmax, | ||
275 | int hmax, int line, char *timestr) | ||
276 | #endif | ||
268 | { | 277 | { |
269 | int w,i,j,pos=inipos,pgpos,oldpg,y; | 278 | int w,i,j,pos=inipos,y; |
270 | char *p,*s,*basep; | 279 | char *p,*s; |
271 | struct page *pg; | ||
272 | u8 chr,r,g,b,color; | 280 | u8 chr,r,g,b,color; |
281 | #ifdef CONFIG_VIVI_SCATTER | ||
282 | int pgpos,oldpg; | ||
283 | char *basep; | ||
284 | struct page *pg; | ||
285 | |||
273 | unsigned long flags; | 286 | unsigned long flags; |
274 | spinlock_t spinlock; | 287 | spinlock_t spinlock; |
275 | 288 | ||
@@ -280,6 +293,7 @@ static void gen_line(struct sg_to_addr to_addr[],int inipos,int pages,int wmax, | |||
280 | pg=pfn_to_page(sg_dma_address(to_addr[oldpg].sg) >> PAGE_SHIFT); | 293 | pg=pfn_to_page(sg_dma_address(to_addr[oldpg].sg) >> PAGE_SHIFT); |
281 | spin_lock_irqsave(&spinlock,flags); | 294 | spin_lock_irqsave(&spinlock,flags); |
282 | basep = kmap_atomic(pg, KM_BOUNCE_READ)+to_addr[oldpg].sg->offset; | 295 | basep = kmap_atomic(pg, KM_BOUNCE_READ)+to_addr[oldpg].sg->offset; |
296 | #endif | ||
283 | 297 | ||
284 | /* We will just duplicate the second pixel at the packet */ | 298 | /* We will just duplicate the second pixel at the packet */ |
285 | wmax/=2; | 299 | wmax/=2; |
@@ -291,6 +305,7 @@ static void gen_line(struct sg_to_addr to_addr[],int inipos,int pages,int wmax, | |||
291 | b=bars[w*7/wmax][2]; | 305 | b=bars[w*7/wmax][2]; |
292 | 306 | ||
293 | for (color=0;color<4;color++) { | 307 | for (color=0;color<4;color++) { |
308 | #ifdef CONFIG_VIVI_SCATTER | ||
294 | pgpos=get_addr_pos(pos,pages,to_addr); | 309 | pgpos=get_addr_pos(pos,pages,to_addr); |
295 | if (pgpos!=oldpg) { | 310 | if (pgpos!=oldpg) { |
296 | pg=pfn_to_page(sg_dma_address(to_addr[pgpos].sg) >> PAGE_SHIFT); | 311 | pg=pfn_to_page(sg_dma_address(to_addr[pgpos].sg) >> PAGE_SHIFT); |
@@ -299,6 +314,9 @@ static void gen_line(struct sg_to_addr to_addr[],int inipos,int pages,int wmax, | |||
299 | oldpg=pgpos; | 314 | oldpg=pgpos; |
300 | } | 315 | } |
301 | p=basep+pos-to_addr[pgpos].pos; | 316 | p=basep+pos-to_addr[pgpos].pos; |
317 | #else | ||
318 | p=basep+pos; | ||
319 | #endif | ||
302 | 320 | ||
303 | switch (color) { | 321 | switch (color) { |
304 | case 0: | 322 | case 0: |
@@ -343,6 +361,7 @@ static void gen_line(struct sg_to_addr to_addr[],int inipos,int pages,int wmax, | |||
343 | 361 | ||
344 | pos=inipos+j*2; | 362 | pos=inipos+j*2; |
345 | for (color=0;color<4;color++) { | 363 | for (color=0;color<4;color++) { |
364 | #ifdef CONFIG_VIVI_SCATTER | ||
346 | pgpos=get_addr_pos(pos,pages,to_addr); | 365 | pgpos=get_addr_pos(pos,pages,to_addr); |
347 | if (pgpos!=oldpg) { | 366 | if (pgpos!=oldpg) { |
348 | pg=pfn_to_page(sg_dma_address( | 367 | pg=pfn_to_page(sg_dma_address( |
@@ -356,6 +375,9 @@ static void gen_line(struct sg_to_addr to_addr[],int inipos,int pages,int wmax, | |||
356 | oldpg=pgpos; | 375 | oldpg=pgpos; |
357 | } | 376 | } |
358 | p=basep+pos-to_addr[pgpos].pos; | 377 | p=basep+pos-to_addr[pgpos].pos; |
378 | #else | ||
379 | p=basep+pos; | ||
380 | #endif | ||
359 | 381 | ||
360 | y=TO_Y(r,g,b); | 382 | y=TO_Y(r,g,b); |
361 | 383 | ||
@@ -380,19 +402,27 @@ static void gen_line(struct sg_to_addr to_addr[],int inipos,int pages,int wmax, | |||
380 | 402 | ||
381 | 403 | ||
382 | end: | 404 | end: |
405 | #ifdef CONFIG_VIVI_SCATTER | ||
383 | kunmap_atomic(basep, KM_BOUNCE_READ); | 406 | kunmap_atomic(basep, KM_BOUNCE_READ); |
384 | spin_unlock_irqrestore(&spinlock,flags); | 407 | spin_unlock_irqrestore(&spinlock,flags); |
385 | 408 | #else | |
409 | return; | ||
410 | #endif | ||
386 | } | 411 | } |
387 | static void vivi_fillbuff(struct vivi_dev *dev,struct vivi_buffer *buf) | 412 | static void vivi_fillbuff(struct vivi_dev *dev,struct vivi_buffer *buf) |
388 | { | 413 | { |
389 | int h,pos=0; | 414 | int h,pos=0; |
390 | int hmax = buf->vb.height; | 415 | int hmax = buf->vb.height; |
391 | int wmax = buf->vb.width; | 416 | int wmax = buf->vb.width; |
392 | struct videobuf_buffer *vb=&buf->vb; | ||
393 | struct sg_to_addr *to_addr=buf->to_addr; | ||
394 | struct timeval ts; | 417 | struct timeval ts; |
418 | #ifdef CONFIG_VIVI_SCATTER | ||
419 | struct sg_to_addr *to_addr=buf->to_addr; | ||
420 | struct videobuf_buffer *vb=&buf->vb; | ||
421 | #else | ||
422 | char *tmpbuf; | ||
423 | #endif | ||
395 | 424 | ||
425 | #ifdef CONFIG_VIVI_SCATTER | ||
396 | /* Test if DMA mapping is ready */ | 426 | /* Test if DMA mapping is ready */ |
397 | if (!sg_dma_address(&vb->dma.sglist[0])) | 427 | if (!sg_dma_address(&vb->dma.sglist[0])) |
398 | return; | 428 | return; |
@@ -401,9 +431,28 @@ static void vivi_fillbuff(struct vivi_dev *dev,struct vivi_buffer *buf) | |||
401 | 431 | ||
402 | /* Check if there is enough memory */ | 432 | /* Check if there is enough memory */ |
403 | BUG_ON(buf->vb.dma.nr_pages << PAGE_SHIFT < (buf->vb.width*buf->vb.height)*2); | 433 | BUG_ON(buf->vb.dma.nr_pages << PAGE_SHIFT < (buf->vb.width*buf->vb.height)*2); |
434 | #else | ||
435 | if (buf->vb.dma.varea) { | ||
436 | tmpbuf=kmalloc (wmax*2, GFP_KERNEL); | ||
437 | } else { | ||
438 | tmpbuf=buf->vb.dma.vmalloc; | ||
439 | } | ||
440 | |||
441 | #endif | ||
404 | 442 | ||
405 | for (h=0;h<hmax;h++) { | 443 | for (h=0;h<hmax;h++) { |
444 | #ifdef CONFIG_VIVI_SCATTER | ||
406 | gen_line(to_addr,pos,vb->dma.nr_pages,wmax,hmax,h,dev->timestr); | 445 | gen_line(to_addr,pos,vb->dma.nr_pages,wmax,hmax,h,dev->timestr); |
446 | #else | ||
447 | if (buf->vb.dma.varea) { | ||
448 | gen_line(tmpbuf,0,wmax,hmax,h,dev->timestr); | ||
449 | /* FIXME: replacing to __copy_to_user */ | ||
450 | if (copy_to_user(buf->vb.dma.varea+pos,tmpbuf,wmax*2)!=0) | ||
451 | dprintk(2,"vivifill copy_to_user failed.\n"); | ||
452 | } else { | ||
453 | gen_line(tmpbuf,pos,wmax,hmax,h,dev->timestr); | ||
454 | } | ||
455 | #endif | ||
407 | pos += wmax*2; | 456 | pos += wmax*2; |
408 | } | 457 | } |
409 | 458 | ||
@@ -429,7 +478,7 @@ static void vivi_fillbuff(struct vivi_dev *dev,struct vivi_buffer *buf) | |||
429 | dev->h,dev->m,dev->s,(dev->us+500)/1000); | 478 | dev->h,dev->m,dev->s,(dev->us+500)/1000); |
430 | 479 | ||
431 | dprintk(2,"vivifill at %s: Buffer 0x%08lx size= %d\n",dev->timestr, | 480 | dprintk(2,"vivifill at %s: Buffer 0x%08lx size= %d\n",dev->timestr, |
432 | (unsigned long)buf->vb.dma.vmalloc,pos); | 481 | (unsigned long)buf->vb.dma.varea,pos); |
433 | 482 | ||
434 | /* Advice that buffer was filled */ | 483 | /* Advice that buffer was filled */ |
435 | buf->vb.state = STATE_DONE; | 484 | buf->vb.state = STATE_DONE; |
@@ -471,11 +520,12 @@ static void vivi_thread_tick(struct vivi_dmaqueue *dma_q) | |||
471 | 520 | ||
472 | /* Fill buffer */ | 521 | /* Fill buffer */ |
473 | vivi_fillbuff(dev,buf); | 522 | vivi_fillbuff(dev,buf); |
474 | } | 523 | |
475 | if (list_empty(&dma_q->active)) { | 524 | if (list_empty(&dma_q->active)) { |
476 | del_timer(&dma_q->timeout); | 525 | del_timer(&dma_q->timeout); |
477 | } else { | 526 | } else { |
478 | mod_timer(&dma_q->timeout, jiffies+BUFFER_TIMEOUT); | 527 | mod_timer(&dma_q->timeout, jiffies+BUFFER_TIMEOUT); |
528 | } | ||
479 | } | 529 | } |
480 | if (bc != 1) | 530 | if (bc != 1) |
481 | dprintk(1,"%s: %d buffers handled (should be 1)\n",__FUNCTION__,bc); | 531 | dprintk(1,"%s: %d buffers handled (should be 1)\n",__FUNCTION__,bc); |
@@ -522,6 +572,8 @@ static int vivi_thread(void *data) | |||
522 | 572 | ||
523 | dprintk(1,"thread started\n"); | 573 | dprintk(1,"thread started\n"); |
524 | 574 | ||
575 | mod_timer(&dma_q->timeout, jiffies+BUFFER_TIMEOUT); | ||
576 | |||
525 | for (;;) { | 577 | for (;;) { |
526 | vivi_sleep(dma_q); | 578 | vivi_sleep(dma_q); |
527 | 579 | ||
@@ -538,7 +590,6 @@ static int vivi_start_thread(struct vivi_dmaqueue *dma_q) | |||
538 | dma_q->ini_jiffies=jiffies; | 590 | dma_q->ini_jiffies=jiffies; |
539 | 591 | ||
540 | dprintk(1,"%s\n",__FUNCTION__); | 592 | dprintk(1,"%s\n",__FUNCTION__); |
541 | init_waitqueue_head(&dma_q->wq); | ||
542 | 593 | ||
543 | dma_q->kthread = kthread_run(vivi_thread, dma_q, "vivi"); | 594 | dma_q->kthread = kthread_run(vivi_thread, dma_q, "vivi"); |
544 | 595 | ||
@@ -546,6 +597,9 @@ static int vivi_start_thread(struct vivi_dmaqueue *dma_q) | |||
546 | printk(KERN_ERR "vivi: kernel_thread() failed\n"); | 597 | printk(KERN_ERR "vivi: kernel_thread() failed\n"); |
547 | return PTR_ERR(dma_q->kthread); | 598 | return PTR_ERR(dma_q->kthread); |
548 | } | 599 | } |
600 | /* Wakes thread */ | ||
601 | wake_up_interruptible(&dma_q->wq); | ||
602 | |||
549 | dprintk(1,"returning from %s\n",__FUNCTION__); | 603 | dprintk(1,"returning from %s\n",__FUNCTION__); |
550 | return 0; | 604 | return 0; |
551 | } | 605 | } |
@@ -663,9 +717,11 @@ static void free_buffer(struct videobuf_queue *vq, struct vivi_buffer *buf) | |||
663 | if (in_interrupt()) | 717 | if (in_interrupt()) |
664 | BUG(); | 718 | BUG(); |
665 | 719 | ||
720 | #ifdef CONFIG_VIVI_SCATTER | ||
666 | /*FIXME: Maybe a spinlock is required here */ | 721 | /*FIXME: Maybe a spinlock is required here */ |
667 | kfree(buf->to_addr); | 722 | kfree(buf->to_addr); |
668 | buf->to_addr=NULL; | 723 | buf->to_addr=NULL; |
724 | #endif | ||
669 | 725 | ||
670 | videobuf_waiton(&buf->vb,0,0); | 726 | videobuf_waiton(&buf->vb,0,0); |
671 | videobuf_dma_unmap(vq, &buf->vb.dma); | 727 | videobuf_dma_unmap(vq, &buf->vb.dma); |
@@ -711,11 +767,12 @@ buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, | |||
711 | 767 | ||
712 | buf->vb.state = STATE_PREPARED; | 768 | buf->vb.state = STATE_PREPARED; |
713 | 769 | ||
770 | #ifdef CONFIG_VIVI_SCATTER | ||
714 | if (NULL == (buf->to_addr = kmalloc(sizeof(*buf->to_addr) * vb->dma.nr_pages,GFP_KERNEL))) { | 771 | if (NULL == (buf->to_addr = kmalloc(sizeof(*buf->to_addr) * vb->dma.nr_pages,GFP_KERNEL))) { |
715 | rc=-ENOMEM; | 772 | rc=-ENOMEM; |
716 | goto fail; | 773 | goto fail; |
717 | } | 774 | } |
718 | 775 | #endif | |
719 | return 0; | 776 | return 0; |
720 | 777 | ||
721 | fail: | 778 | fail: |
@@ -780,6 +837,7 @@ static void buffer_release(struct videobuf_queue *vq, struct videobuf_buffer *vb | |||
780 | free_buffer(vq,buf); | 837 | free_buffer(vq,buf); |
781 | } | 838 | } |
782 | 839 | ||
840 | #ifdef CONFIG_VIVI_SCATTER | ||
783 | static int vivi_map_sg(void *dev, struct scatterlist *sg, int nents, | 841 | static int vivi_map_sg(void *dev, struct scatterlist *sg, int nents, |
784 | int direction) | 842 | int direction) |
785 | { | 843 | { |
@@ -812,6 +870,7 @@ static int vivi_dma_sync_sg(void *dev,struct scatterlist *sglist, int nr_pages, | |||
812 | // flush_write_buffers(); | 870 | // flush_write_buffers(); |
813 | return 0; | 871 | return 0; |
814 | } | 872 | } |
873 | #endif | ||
815 | 874 | ||
816 | static struct videobuf_queue_ops vivi_video_qops = { | 875 | static struct videobuf_queue_ops vivi_video_qops = { |
817 | .buf_setup = buffer_setup, | 876 | .buf_setup = buffer_setup, |
@@ -820,9 +879,9 @@ static struct videobuf_queue_ops vivi_video_qops = { | |||
820 | .buf_release = buffer_release, | 879 | .buf_release = buffer_release, |
821 | 880 | ||
822 | /* Non-pci handling routines */ | 881 | /* Non-pci handling routines */ |
823 | .vb_map_sg = vivi_map_sg, | 882 | // .vb_map_sg = vivi_map_sg, |
824 | .vb_dma_sync_sg = vivi_dma_sync_sg, | 883 | // .vb_dma_sync_sg = vivi_dma_sync_sg, |
825 | .vb_unmap_sg = vivi_unmap_sg, | 884 | // .vb_unmap_sg = vivi_unmap_sg, |
826 | }; | 885 | }; |
827 | 886 | ||
828 | /* ------------------------------------------------------------------ | 887 | /* ------------------------------------------------------------------ |
@@ -1200,11 +1259,19 @@ static int vivi_open(struct inode *inode, struct file *file) | |||
1200 | sprintf(dev->timestr,"%02d:%02d:%02d:%03d", | 1259 | sprintf(dev->timestr,"%02d:%02d:%02d:%03d", |
1201 | dev->h,dev->m,dev->s,(dev->us+500)/1000); | 1260 | dev->h,dev->m,dev->s,(dev->us+500)/1000); |
1202 | 1261 | ||
1262 | #ifdef CONFIG_VIVI_SCATTER | ||
1263 | videobuf_queue_init(&fh->vb_vidq,VIDEOBUF_DMA_SCATTER, &vivi_video_qops, | ||
1264 | NULL, NULL, | ||
1265 | fh->type, | ||
1266 | V4L2_FIELD_INTERLACED, | ||
1267 | sizeof(struct vivi_buffer),fh); | ||
1268 | #else | ||
1203 | videobuf_queue_init(&fh->vb_vidq, &vivi_video_qops, | 1269 | videobuf_queue_init(&fh->vb_vidq, &vivi_video_qops, |
1204 | NULL, NULL, | 1270 | NULL, NULL, |
1205 | fh->type, | 1271 | fh->type, |
1206 | V4L2_FIELD_INTERLACED, | 1272 | V4L2_FIELD_INTERLACED, |
1207 | sizeof(struct vivi_buffer),fh); | 1273 | sizeof(struct vivi_buffer),fh); |
1274 | #endif | ||
1208 | 1275 | ||
1209 | return 0; | 1276 | return 0; |
1210 | } | 1277 | } |
@@ -1352,6 +1419,7 @@ static int __init vivi_init(void) | |||
1352 | /* init video dma queues */ | 1419 | /* init video dma queues */ |
1353 | INIT_LIST_HEAD(&dev->vidq.active); | 1420 | INIT_LIST_HEAD(&dev->vidq.active); |
1354 | INIT_LIST_HEAD(&dev->vidq.queued); | 1421 | INIT_LIST_HEAD(&dev->vidq.queued); |
1422 | init_waitqueue_head(&dev->vidq.wq); | ||
1355 | 1423 | ||
1356 | /* initialize locks */ | 1424 | /* initialize locks */ |
1357 | init_MUTEX(&dev->lock); | 1425 | init_MUTEX(&dev->lock); |
diff --git a/drivers/media/video/zc0301/zc0301.h b/drivers/media/video/zc0301/zc0301.h index b9c93b8c16f7..710f12eb9126 100644 --- a/drivers/media/video/zc0301/zc0301.h +++ b/drivers/media/video/zc0301/zc0301.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /*************************************************************************** | 1 | /*************************************************************************** |
2 | * V4L2 driver for ZC0301 Image Processor and Control Chip * | 2 | * V4L2 driver for ZC0301[P] Image Processor and Control Chip * |
3 | * * | 3 | * * |
4 | * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it> * | 4 | * Copyright (C) 2006-2007 by Luca Risolia <luca.risolia@studio.unibo.it> * |
5 | * * | 5 | * * |
6 | * This program is free software; you can redistribute it and/or modify * | 6 | * This program is free software; you can redistribute it and/or modify * |
7 | * it under the terms of the GNU General Public License as published by * | 7 | * it under the terms of the GNU General Public License as published by * |
diff --git a/drivers/media/video/zc0301/zc0301_core.c b/drivers/media/video/zc0301/zc0301_core.c index 8da7f15f6290..f1120551c70c 100644 --- a/drivers/media/video/zc0301/zc0301_core.c +++ b/drivers/media/video/zc0301/zc0301_core.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /*************************************************************************** | 1 | /*************************************************************************** |
2 | * Video4Linux2 driver for ZC0301[P] Image Processor and Control Chip * | 2 | * Video4Linux2 driver for ZC0301[P] Image Processor and Control Chip * |
3 | * * | 3 | * * |
4 | * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it> * | 4 | * Copyright (C) 2006-2007 by Luca Risolia <luca.risolia@studio.unibo.it> * |
5 | * * | 5 | * * |
6 | * Informations about the chip internals needed to enable the I2C protocol * | 6 | * Informations about the chip internals needed to enable the I2C protocol * |
7 | * have been taken from the documentation of the ZC030x Video4Linux1 * | 7 | * have been taken from the documentation of the ZC030x Video4Linux1 * |
@@ -52,8 +52,8 @@ | |||
52 | #define ZC0301_MODULE_AUTHOR "(C) 2006 Luca Risolia" | 52 | #define ZC0301_MODULE_AUTHOR "(C) 2006 Luca Risolia" |
53 | #define ZC0301_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>" | 53 | #define ZC0301_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>" |
54 | #define ZC0301_MODULE_LICENSE "GPL" | 54 | #define ZC0301_MODULE_LICENSE "GPL" |
55 | #define ZC0301_MODULE_VERSION "1:1.05" | 55 | #define ZC0301_MODULE_VERSION "1:1.07" |
56 | #define ZC0301_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 5) | 56 | #define ZC0301_MODULE_VERSION_CODE KERNEL_VERSION(1, 1, 7) |
57 | 57 | ||
58 | /*****************************************************************************/ | 58 | /*****************************************************************************/ |
59 | 59 | ||
@@ -89,7 +89,7 @@ MODULE_PARM_DESC(force_munmap, | |||
89 | "\ndetected camera." | 89 | "\ndetected camera." |
90 | "\n 0 = do not force memory unmapping" | 90 | "\n 0 = do not force memory unmapping" |
91 | "\n 1 = force memory unmapping (save memory)" | 91 | "\n 1 = force memory unmapping (save memory)" |
92 | "\nDefault value is "__MODULE_STRING(SN9C102_FORCE_MUNMAP)"." | 92 | "\nDefault value is "__MODULE_STRING(ZC0301_FORCE_MUNMAP)"." |
93 | "\n"); | 93 | "\n"); |
94 | 94 | ||
95 | static unsigned int frame_timeout[] = {[0 ... ZC0301_MAX_DEVICES-1] = | 95 | static unsigned int frame_timeout[] = {[0 ... ZC0301_MAX_DEVICES-1] = |
@@ -136,7 +136,8 @@ zc0301_request_buffers(struct zc0301_device* cam, u32 count, | |||
136 | 136 | ||
137 | cam->nbuffers = count; | 137 | cam->nbuffers = count; |
138 | while (cam->nbuffers > 0) { | 138 | while (cam->nbuffers > 0) { |
139 | if ((buff = vmalloc_32(cam->nbuffers * PAGE_ALIGN(imagesize)))) | 139 | if ((buff = vmalloc_32_user(cam->nbuffers * |
140 | PAGE_ALIGN(imagesize)))) | ||
140 | break; | 141 | break; |
141 | cam->nbuffers--; | 142 | cam->nbuffers--; |
142 | } | 143 | } |
@@ -430,7 +431,8 @@ static int zc0301_start_transfer(struct zc0301_device* cam) | |||
430 | struct usb_host_interface* altsetting = usb_altnum_to_altsetting( | 431 | struct usb_host_interface* altsetting = usb_altnum_to_altsetting( |
431 | usb_ifnum_to_if(udev, 0), | 432 | usb_ifnum_to_if(udev, 0), |
432 | ZC0301_ALTERNATE_SETTING); | 433 | ZC0301_ALTERNATE_SETTING); |
433 | const unsigned int psz = altsetting->endpoint[0].desc.wMaxPacketSize; | 434 | const unsigned int psz = le16_to_cpu(altsetting-> |
435 | endpoint[0].desc.wMaxPacketSize); | ||
434 | struct urb* urb; | 436 | struct urb* urb; |
435 | s8 i, j; | 437 | s8 i, j; |
436 | int err = 0; | 438 | int err = 0; |
@@ -489,7 +491,7 @@ static int zc0301_start_transfer(struct zc0301_device* cam) | |||
489 | return 0; | 491 | return 0; |
490 | 492 | ||
491 | free_urbs: | 493 | free_urbs: |
492 | for (i = 0; i < ZC0301_URBS; i++) | 494 | for (i = 0; (i < ZC0301_URBS) && cam->urb[i]; i++) |
493 | usb_free_urb(cam->urb[i]); | 495 | usb_free_urb(cam->urb[i]); |
494 | 496 | ||
495 | free_buffers: | 497 | free_buffers: |
@@ -1288,6 +1290,35 @@ zc0301_vidioc_s_crop(struct zc0301_device* cam, void __user * arg) | |||
1288 | 1290 | ||
1289 | 1291 | ||
1290 | static int | 1292 | static int |
1293 | zc0301_vidioc_enum_framesizes(struct zc0301_device* cam, void __user * arg) | ||
1294 | { | ||
1295 | struct v4l2_frmsizeenum frmsize; | ||
1296 | |||
1297 | if (copy_from_user(&frmsize, arg, sizeof(frmsize))) | ||
1298 | return -EFAULT; | ||
1299 | |||
1300 | if (frmsize.index != 0 && frmsize.index != 1) | ||
1301 | return -EINVAL; | ||
1302 | |||
1303 | if (frmsize.pixel_format != V4L2_PIX_FMT_JPEG) | ||
1304 | return -EINVAL; | ||
1305 | |||
1306 | frmsize.type = V4L2_FRMSIZE_TYPE_DISCRETE; | ||
1307 | |||
1308 | if (frmsize.index == 1) { | ||
1309 | frmsize.discrete.width = cam->sensor.cropcap.defrect.width; | ||
1310 | frmsize.discrete.height = cam->sensor.cropcap.defrect.height; | ||
1311 | } | ||
1312 | memset(&frmsize.reserved, 0, sizeof(frmsize.reserved)); | ||
1313 | |||
1314 | if (copy_to_user(arg, &frmsize, sizeof(frmsize))) | ||
1315 | return -EFAULT; | ||
1316 | |||
1317 | return 0; | ||
1318 | } | ||
1319 | |||
1320 | |||
1321 | static int | ||
1291 | zc0301_vidioc_enum_fmt(struct zc0301_device* cam, void __user * arg) | 1322 | zc0301_vidioc_enum_fmt(struct zc0301_device* cam, void __user * arg) |
1292 | { | 1323 | { |
1293 | struct v4l2_fmtdesc fmtd; | 1324 | struct v4l2_fmtdesc fmtd; |
@@ -1295,6 +1326,9 @@ zc0301_vidioc_enum_fmt(struct zc0301_device* cam, void __user * arg) | |||
1295 | if (copy_from_user(&fmtd, arg, sizeof(fmtd))) | 1326 | if (copy_from_user(&fmtd, arg, sizeof(fmtd))) |
1296 | return -EFAULT; | 1327 | return -EFAULT; |
1297 | 1328 | ||
1329 | if (fmtd.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
1330 | return -EINVAL; | ||
1331 | |||
1298 | if (fmtd.index == 0) { | 1332 | if (fmtd.index == 0) { |
1299 | strcpy(fmtd.description, "JPEG"); | 1333 | strcpy(fmtd.description, "JPEG"); |
1300 | fmtd.pixelformat = V4L2_PIX_FMT_JPEG; | 1334 | fmtd.pixelformat = V4L2_PIX_FMT_JPEG; |
@@ -1795,6 +1829,9 @@ static int zc0301_ioctl_v4l2(struct inode* inode, struct file* filp, | |||
1795 | case VIDIOC_S_FMT: | 1829 | case VIDIOC_S_FMT: |
1796 | return zc0301_vidioc_try_s_fmt(cam, cmd, arg); | 1830 | return zc0301_vidioc_try_s_fmt(cam, cmd, arg); |
1797 | 1831 | ||
1832 | case VIDIOC_ENUM_FRAMESIZES: | ||
1833 | return zc0301_vidioc_enum_framesizes(cam, arg); | ||
1834 | |||
1798 | case VIDIOC_G_JPEGCOMP: | 1835 | case VIDIOC_G_JPEGCOMP: |
1799 | return zc0301_vidioc_g_jpegcomp(cam, arg); | 1836 | return zc0301_vidioc_g_jpegcomp(cam, arg); |
1800 | 1837 | ||
@@ -1830,6 +1867,7 @@ static int zc0301_ioctl_v4l2(struct inode* inode, struct file* filp, | |||
1830 | case VIDIOC_QUERYSTD: | 1867 | case VIDIOC_QUERYSTD: |
1831 | case VIDIOC_ENUMSTD: | 1868 | case VIDIOC_ENUMSTD: |
1832 | case VIDIOC_QUERYMENU: | 1869 | case VIDIOC_QUERYMENU: |
1870 | case VIDIOC_ENUM_FRAMEINTERVALS: | ||
1833 | return -EINVAL; | 1871 | return -EINVAL; |
1834 | 1872 | ||
1835 | default: | 1873 | default: |
@@ -1876,6 +1914,7 @@ static const struct file_operations zc0301_fops = { | |||
1876 | .open = zc0301_open, | 1914 | .open = zc0301_open, |
1877 | .release = zc0301_release, | 1915 | .release = zc0301_release, |
1878 | .ioctl = zc0301_ioctl, | 1916 | .ioctl = zc0301_ioctl, |
1917 | .compat_ioctl = v4l_compat_ioctl32, | ||
1879 | .read = zc0301_read, | 1918 | .read = zc0301_read, |
1880 | .poll = zc0301_poll, | 1919 | .poll = zc0301_poll, |
1881 | .mmap = zc0301_mmap, | 1920 | .mmap = zc0301_mmap, |
@@ -1913,7 +1952,7 @@ zc0301_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) | |||
1913 | mutex_init(&cam->dev_mutex); | 1952 | mutex_init(&cam->dev_mutex); |
1914 | 1953 | ||
1915 | DBG(2, "ZC0301[P] Image Processor and Control Chip detected " | 1954 | DBG(2, "ZC0301[P] Image Processor and Control Chip detected " |
1916 | "(vid/pid 0x%04X/0x%04X)",id->idVendor, id->idProduct); | 1955 | "(vid/pid 0x%04X:0x%04X)",id->idVendor, id->idProduct); |
1917 | 1956 | ||
1918 | for (i = 0; zc0301_sensor_table[i]; i++) { | 1957 | for (i = 0; zc0301_sensor_table[i]; i++) { |
1919 | err = zc0301_sensor_table[i](cam); | 1958 | err = zc0301_sensor_table[i](cam); |
diff --git a/drivers/media/video/zc0301/zc0301_pas202bcb.c b/drivers/media/video/zc0301/zc0301_pas202bcb.c index ecfd39a56df1..3efb92a0d0da 100644 --- a/drivers/media/video/zc0301/zc0301_pas202bcb.c +++ b/drivers/media/video/zc0301/zc0301_pas202bcb.c | |||
@@ -1,8 +1,8 @@ | |||
1 | /*************************************************************************** | 1 | /*************************************************************************** |
2 | * Plug-in for PAS202BCB image sensor connected to the ZC0301[P] Image * | 2 | * Plug-in for PAS202BCB image sensor connected to the ZC0301 Image * |
3 | * Processor and Control Chip * | 3 | * Processor and Control Chip * |
4 | * * | 4 | * * |
5 | * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it> * | 5 | * Copyright (C) 2006-2007 by Luca Risolia <luca.risolia@studio.unibo.it> * |
6 | * * | 6 | * * |
7 | * Initialization values of the ZC0301[P] have been taken from the SPCA5XX * | 7 | * Initialization values of the ZC0301[P] have been taken from the SPCA5XX * |
8 | * driver maintained by Michel Xhaard <mxhaard@magic.fr> * | 8 | * driver maintained by Michel Xhaard <mxhaard@magic.fr> * |
diff --git a/drivers/media/video/zc0301/zc0301_pb0330.c b/drivers/media/video/zc0301/zc0301_pb0330.c index ed8542e6c50f..5784b1d1491c 100644 --- a/drivers/media/video/zc0301/zc0301_pb0330.c +++ b/drivers/media/video/zc0301/zc0301_pb0330.c | |||
@@ -1,8 +1,8 @@ | |||
1 | /*************************************************************************** | 1 | /*************************************************************************** |
2 | * Plug-in for PB-0330 image sensor connected to the ZC0301[P] Image * | 2 | * Plug-in for PB-0330 image sensor connected to the ZC0301P Image * |
3 | * Processor and Control Chip * | 3 | * Processor and Control Chip * |
4 | * * | 4 | * * |
5 | * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it> * | 5 | * Copyright (C) 2006-2007 by Luca Risolia <luca.risolia@studio.unibo.it> * |
6 | * * | 6 | * * |
7 | * Initialization values of the ZC0301[P] have been taken from the SPCA5XX * | 7 | * Initialization values of the ZC0301[P] have been taken from the SPCA5XX * |
8 | * driver maintained by Michel Xhaard <mxhaard@magic.fr> * | 8 | * driver maintained by Michel Xhaard <mxhaard@magic.fr> * |
diff --git a/drivers/media/video/zc0301/zc0301_sensor.h b/drivers/media/video/zc0301/zc0301_sensor.h index 3daf049a288a..44e82cff9319 100644 --- a/drivers/media/video/zc0301/zc0301_sensor.h +++ b/drivers/media/video/zc0301/zc0301_sensor.h | |||
@@ -1,8 +1,8 @@ | |||
1 | /*************************************************************************** | 1 | /*************************************************************************** |
2 | * API for image sensors connected to the ZC0301 Image Processor and * | 2 | * API for image sensors connected to the ZC0301[P] Image Processor and * |
3 | * Control Chip * | 3 | * Control Chip * |
4 | * * | 4 | * * |
5 | * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it> * | 5 | * Copyright (C) 2006-2007 by Luca Risolia <luca.risolia@studio.unibo.it> * |
6 | * * | 6 | * * |
7 | * This program is free software; you can redistribute it and/or modify * | 7 | * This program is free software; you can redistribute it and/or modify * |
8 | * it under the terms of the GNU General Public License as published by * | 8 | * it under the terms of the GNU General Public License as published by * |
@@ -70,7 +70,7 @@ static const struct usb_device_id zc0301_id_table[] = { \ | |||
70 | { ZC0301_USB_DEVICE(0x041e, 0x4036, 0xff), }, /* HV7131 */ \ | 70 | { ZC0301_USB_DEVICE(0x041e, 0x4036, 0xff), }, /* HV7131 */ \ |
71 | { ZC0301_USB_DEVICE(0x041e, 0x403a, 0xff), }, /* HV7131 */ \ | 71 | { ZC0301_USB_DEVICE(0x041e, 0x403a, 0xff), }, /* HV7131 */ \ |
72 | { ZC0301_USB_DEVICE(0x0458, 0x7007, 0xff), }, /* TAS5130 */ \ | 72 | { ZC0301_USB_DEVICE(0x0458, 0x7007, 0xff), }, /* TAS5130 */ \ |
73 | { ZC0301_USB_DEVICE(0x0458, 0x700C, 0xff), }, /* TAS5130 */ \ | 73 | { ZC0301_USB_DEVICE(0x0458, 0x700c, 0xff), }, /* TAS5130 */ \ |
74 | { ZC0301_USB_DEVICE(0x0458, 0x700f, 0xff), }, /* TAS5130 */ \ | 74 | { ZC0301_USB_DEVICE(0x0458, 0x700f, 0xff), }, /* TAS5130 */ \ |
75 | { ZC0301_USB_DEVICE(0x046d, 0x08ae, 0xff), }, /* PAS202 */ \ | 75 | { ZC0301_USB_DEVICE(0x046d, 0x08ae, 0xff), }, /* PAS202 */ \ |
76 | { ZC0301_USB_DEVICE(0x055f, 0xd003, 0xff), }, /* TAS5130 */ \ | 76 | { ZC0301_USB_DEVICE(0x055f, 0xd003, 0xff), }, /* TAS5130 */ \ |
@@ -93,9 +93,9 @@ extern int zc0301_i2c_read(struct zc0301_device*, u16 address, u8 length); | |||
93 | 93 | ||
94 | /*****************************************************************************/ | 94 | /*****************************************************************************/ |
95 | 95 | ||
96 | #define ZC0301_MAX_CTRLS V4L2_CID_LASTP1-V4L2_CID_BASE+10 | 96 | #define ZC0301_MAX_CTRLS (V4L2_CID_LASTP1 - V4L2_CID_BASE + 10) |
97 | #define ZC0301_V4L2_CID_DAC_MAGNITUDE V4L2_CID_PRIVATE_BASE | 97 | #define ZC0301_V4L2_CID_DAC_MAGNITUDE (V4L2_CID_PRIVATE_BASE + 0) |
98 | #define ZC0301_V4L2_CID_GREEN_BALANCE V4L2_CID_PRIVATE_BASE + 1 | 98 | #define ZC0301_V4L2_CID_GREEN_BALANCE (V4L2_CID_PRIVATE_BASE + 1) |
99 | 99 | ||
100 | struct zc0301_sensor { | 100 | struct zc0301_sensor { |
101 | char name[32]; | 101 | char name[32]; |