diff options
author | Mauro Carvalho Chehab <mchehab@infradead.org> | 2007-11-03 20:20:59 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2008-01-25 16:01:55 -0500 |
commit | 03910cc39035d27f4c85c8ad2a236cc5c9456127 (patch) | |
tree | 04c852f7f52e9568cbc68cd6c489cc4d003958a9 /drivers/media/video/em28xx/em28xx-video.c | |
parent | 3dbd85ba36ff74af87550e76f5765a768b108409 (diff) |
V4L/DVB (6536): Add a hint for boards without unique USB ID
This patch adds a function to allow trying to detect boards that shares
the generic IDs.
The current detection method is based at eeprom checksum.
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video/em28xx/em28xx-video.c')
-rw-r--r-- | drivers/media/video/em28xx/em28xx-video.c | 120 |
1 files changed, 35 insertions, 85 deletions
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index fb0fa57dec92..18b8568c634c 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c | |||
@@ -37,7 +37,6 @@ | |||
37 | #include <linux/mutex.h> | 37 | #include <linux/mutex.h> |
38 | 38 | ||
39 | #include "em28xx.h" | 39 | #include "em28xx.h" |
40 | #include <media/tuner.h> | ||
41 | #include <media/v4l2-common.h> | 40 | #include <media/v4l2-common.h> |
42 | #include <media/msp3400.h> | 41 | #include <media/msp3400.h> |
43 | 42 | ||
@@ -71,10 +70,6 @@ MODULE_PARM_DESC(card,"card type"); | |||
71 | MODULE_PARM_DESC(video_nr,"video device numbers"); | 70 | MODULE_PARM_DESC(video_nr,"video device numbers"); |
72 | MODULE_PARM_DESC(vbi_nr,"vbi device numbers"); | 71 | MODULE_PARM_DESC(vbi_nr,"vbi device numbers"); |
73 | 72 | ||
74 | static int tuner = -1; | ||
75 | module_param(tuner, int, 0444); | ||
76 | MODULE_PARM_DESC(tuner, "tuner type"); | ||
77 | |||
78 | static unsigned int video_debug = 0; | 73 | static unsigned int video_debug = 0; |
79 | module_param(video_debug,int,0644); | 74 | module_param(video_debug,int,0644); |
80 | MODULE_PARM_DESC(video_debug,"enable debug messages [video]"); | 75 | MODULE_PARM_DESC(video_debug,"enable debug messages [video]"); |
@@ -171,7 +166,6 @@ static int em28xx_config(struct em28xx *dev) | |||
171 | */ | 166 | */ |
172 | static void em28xx_config_i2c(struct em28xx *dev) | 167 | static void em28xx_config_i2c(struct em28xx *dev) |
173 | { | 168 | { |
174 | struct v4l2_frequency f; | ||
175 | struct v4l2_routing route; | 169 | struct v4l2_routing route; |
176 | 170 | ||
177 | route.input = INPUT(dev->ctl_input)->vmux; | 171 | route.input = INPUT(dev->ctl_input)->vmux; |
@@ -179,13 +173,6 @@ static void em28xx_config_i2c(struct em28xx *dev) | |||
179 | em28xx_i2c_call_clients(dev, VIDIOC_INT_RESET, NULL); | 173 | em28xx_i2c_call_clients(dev, VIDIOC_INT_RESET, NULL); |
180 | em28xx_i2c_call_clients(dev, VIDIOC_INT_S_VIDEO_ROUTING, &route); | 174 | em28xx_i2c_call_clients(dev, VIDIOC_INT_S_VIDEO_ROUTING, &route); |
181 | em28xx_i2c_call_clients(dev, VIDIOC_STREAMON, NULL); | 175 | em28xx_i2c_call_clients(dev, VIDIOC_STREAMON, NULL); |
182 | |||
183 | /* configure tuner */ | ||
184 | f.tuner = 0; | ||
185 | f.type = V4L2_TUNER_ANALOG_TV; | ||
186 | f.frequency = 9076; /* FIXME:remove magic number */ | ||
187 | dev->ctl_freq = f.frequency; | ||
188 | em28xx_i2c_call_clients(dev, VIDIOC_S_FREQUENCY, &f); | ||
189 | } | 176 | } |
190 | 177 | ||
191 | /* | 178 | /* |
@@ -1495,7 +1482,7 @@ static const struct file_operations em28xx_v4l_fops = { | |||
1495 | * allocates and inits the device structs, registers i2c bus and v4l device | 1482 | * allocates and inits the device structs, registers i2c bus and v4l device |
1496 | */ | 1483 | */ |
1497 | static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, | 1484 | static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, |
1498 | int minor, int model) | 1485 | int minor) |
1499 | { | 1486 | { |
1500 | struct em28xx *dev = *devhandle; | 1487 | struct em28xx *dev = *devhandle; |
1501 | int retval = -ENOMEM; | 1488 | int retval = -ENOMEM; |
@@ -1503,7 +1490,6 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, | |||
1503 | unsigned int maxh, maxw; | 1490 | unsigned int maxh, maxw; |
1504 | 1491 | ||
1505 | dev->udev = udev; | 1492 | dev->udev = udev; |
1506 | dev->model = model; | ||
1507 | mutex_init(&dev->lock); | 1493 | mutex_init(&dev->lock); |
1508 | init_waitqueue_head(&dev->open); | 1494 | init_waitqueue_head(&dev->open); |
1509 | 1495 | ||
@@ -1512,43 +1498,6 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, | |||
1512 | dev->em28xx_read_reg_req_len = em28xx_read_reg_req_len; | 1498 | dev->em28xx_read_reg_req_len = em28xx_read_reg_req_len; |
1513 | dev->em28xx_write_regs_req = em28xx_write_regs_req; | 1499 | dev->em28xx_write_regs_req = em28xx_write_regs_req; |
1514 | dev->em28xx_read_reg_req = em28xx_read_reg_req; | 1500 | dev->em28xx_read_reg_req = em28xx_read_reg_req; |
1515 | dev->is_em2800 = em28xx_boards[model].is_em2800; | ||
1516 | dev->has_tuner = em28xx_boards[model].has_tuner; | ||
1517 | dev->has_msp34xx = em28xx_boards[model].has_msp34xx; | ||
1518 | dev->tda9887_conf = em28xx_boards[model].tda9887_conf; | ||
1519 | dev->decoder = em28xx_boards[model].decoder; | ||
1520 | |||
1521 | if (tuner >= 0) | ||
1522 | dev->tuner_type = tuner; | ||
1523 | else | ||
1524 | dev->tuner_type = em28xx_boards[model].tuner_type; | ||
1525 | |||
1526 | dev->video_inputs = em28xx_boards[model].vchannels; | ||
1527 | |||
1528 | for (i = 0; i < TVNORMS; i++) | ||
1529 | if (em28xx_boards[model].norm == tvnorms[i].mode) | ||
1530 | break; | ||
1531 | if (i == TVNORMS) | ||
1532 | i = 0; | ||
1533 | |||
1534 | dev->tvnorm = &tvnorms[i]; /* set default norm */ | ||
1535 | |||
1536 | em28xx_videodbg("tvnorm=%s\n", dev->tvnorm->name); | ||
1537 | |||
1538 | maxw = norm_maxw(dev); | ||
1539 | maxh = norm_maxh(dev); | ||
1540 | |||
1541 | /* set default image size */ | ||
1542 | dev->width = maxw; | ||
1543 | dev->height = maxh; | ||
1544 | dev->interlaced = EM28XX_INTERLACED_DEFAULT; | ||
1545 | dev->field_size = dev->width * dev->height; | ||
1546 | dev->frame_size = | ||
1547 | dev->interlaced ? dev->field_size << 1 : dev->field_size; | ||
1548 | dev->bytesperline = dev->width * 2; | ||
1549 | dev->hscale = 0; | ||
1550 | dev->vscale = 0; | ||
1551 | dev->ctl_input = 2; | ||
1552 | 1501 | ||
1553 | /* setup video picture settings for saa7113h */ | 1502 | /* setup video picture settings for saa7113h */ |
1554 | memset(&dev->vpic, 0, sizeof(dev->vpic)); | 1503 | memset(&dev->vpic, 0, sizeof(dev->vpic)); |
@@ -1561,24 +1510,17 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, | |||
1561 | dev->vpic.palette = VIDEO_PALETTE_YUV422; | 1510 | dev->vpic.palette = VIDEO_PALETTE_YUV422; |
1562 | 1511 | ||
1563 | em28xx_pre_card_setup(dev); | 1512 | em28xx_pre_card_setup(dev); |
1564 | #ifdef CONFIG_MODULES | 1513 | |
1565 | /* request some modules */ | ||
1566 | if (dev->decoder == EM28XX_SAA7113 || dev->decoder == EM28XX_SAA7114) | ||
1567 | request_module("saa7115"); | ||
1568 | if (dev->decoder == EM28XX_TVP5150) | ||
1569 | request_module("tvp5150"); | ||
1570 | if (dev->has_tuner) | ||
1571 | request_module("tuner"); | ||
1572 | #endif | ||
1573 | errCode = em28xx_config(dev); | 1514 | errCode = em28xx_config(dev); |
1574 | if (errCode) { | 1515 | if (errCode) { |
1575 | em28xx_errdev("error configuring device\n"); | 1516 | em28xx_errdev("error configuring device\n"); |
1576 | em28xx_devused&=~(1<<dev->devno); | 1517 | em28xx_devused &= ~(1<<dev->devno); |
1577 | kfree(dev); | 1518 | kfree(dev); |
1578 | return -ENOMEM; | 1519 | return -ENOMEM; |
1579 | } | 1520 | } |
1580 | 1521 | ||
1581 | mutex_lock(&dev->lock); | 1522 | mutex_lock(&dev->lock); |
1523 | |||
1582 | /* register i2c bus */ | 1524 | /* register i2c bus */ |
1583 | em28xx_i2c_register(dev); | 1525 | em28xx_i2c_register(dev); |
1584 | 1526 | ||
@@ -1590,12 +1532,33 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, | |||
1590 | 1532 | ||
1591 | mutex_unlock(&dev->lock); | 1533 | mutex_unlock(&dev->lock); |
1592 | 1534 | ||
1535 | for (i = 0; i < TVNORMS; i++) | ||
1536 | if (em28xx_boards[dev->model].norm == tvnorms[i].mode) | ||
1537 | break; | ||
1538 | if (i == TVNORMS) | ||
1539 | i = 0; | ||
1540 | |||
1541 | dev->tvnorm = &tvnorms[i]; /* set default norm */ | ||
1542 | |||
1543 | em28xx_videodbg("tvnorm=%s\n", dev->tvnorm->name); | ||
1544 | |||
1545 | maxw = norm_maxw(dev); | ||
1546 | maxh = norm_maxh(dev); | ||
1547 | |||
1548 | /* set default image size */ | ||
1549 | dev->width = maxw; | ||
1550 | dev->height = maxh; | ||
1551 | dev->interlaced = EM28XX_INTERLACED_DEFAULT; | ||
1552 | dev->field_size = dev->width * dev->height; | ||
1553 | dev->frame_size = | ||
1554 | dev->interlaced ? dev->field_size << 1 : dev->field_size; | ||
1555 | dev->bytesperline = dev->width * 2; | ||
1556 | dev->hscale = 0; | ||
1557 | dev->vscale = 0; | ||
1558 | dev->ctl_input = 2; | ||
1559 | |||
1593 | errCode = em28xx_config(dev); | 1560 | errCode = em28xx_config(dev); |
1594 | 1561 | ||
1595 | #ifdef CONFIG_MODULES | ||
1596 | if (dev->has_msp34xx) | ||
1597 | request_module("msp3400"); | ||
1598 | #endif | ||
1599 | /* allocate and fill v4l2 device struct */ | 1562 | /* allocate and fill v4l2 device struct */ |
1600 | dev->vdev = video_device_alloc(); | 1563 | dev->vdev = video_device_alloc(); |
1601 | if (NULL == dev->vdev) { | 1564 | if (NULL == dev->vdev) { |
@@ -1695,7 +1658,7 @@ static int em28xx_usb_probe(struct usb_interface *interface, | |||
1695 | struct usb_interface *uif; | 1658 | struct usb_interface *uif; |
1696 | struct em28xx *dev = NULL; | 1659 | struct em28xx *dev = NULL; |
1697 | int retval = -ENODEV; | 1660 | int retval = -ENODEV; |
1698 | int model,i,nr,ifnum; | 1661 | int i, nr, ifnum; |
1699 | 1662 | ||
1700 | udev = usb_get_dev(interface_to_usbdev(interface)); | 1663 | udev = usb_get_dev(interface_to_usbdev(interface)); |
1701 | ifnum = interface->altsetting[0].desc.bInterfaceNumber; | 1664 | ifnum = interface->altsetting[0].desc.bInterfaceNumber; |
@@ -1735,8 +1698,6 @@ static int em28xx_usb_probe(struct usb_interface *interface, | |||
1735 | return -ENODEV; | 1698 | return -ENODEV; |
1736 | } | 1699 | } |
1737 | 1700 | ||
1738 | model=id->driver_info; | ||
1739 | |||
1740 | if (nr >= EM28XX_MAXBOARDS) { | 1701 | if (nr >= EM28XX_MAXBOARDS) { |
1741 | printk (DRIVER_NAME ": Supports only %i em28xx boards.\n",EM28XX_MAXBOARDS); | 1702 | printk (DRIVER_NAME ": Supports only %i em28xx boards.\n",EM28XX_MAXBOARDS); |
1742 | em28xx_devused&=~(1<<nr); | 1703 | em28xx_devused&=~(1<<nr); |
@@ -1752,7 +1713,8 @@ static int em28xx_usb_probe(struct usb_interface *interface, | |||
1752 | } | 1713 | } |
1753 | 1714 | ||
1754 | snprintf(dev->name, 29, "em28xx #%d", nr); | 1715 | snprintf(dev->name, 29, "em28xx #%d", nr); |
1755 | dev->devno=nr; | 1716 | dev->devno = nr; |
1717 | dev->model = id->driver_info; | ||
1756 | 1718 | ||
1757 | /* compute alternate max packet sizes */ | 1719 | /* compute alternate max packet sizes */ |
1758 | uif = udev->actconfig->interface[0]; | 1720 | uif = udev->actconfig->interface[0]; |
@@ -1779,26 +1741,14 @@ static int em28xx_usb_probe(struct usb_interface *interface, | |||
1779 | } | 1741 | } |
1780 | 1742 | ||
1781 | if ((card[nr]>=0)&&(card[nr]<em28xx_bcount)) | 1743 | if ((card[nr]>=0)&&(card[nr]<em28xx_bcount)) |
1782 | model=card[nr]; | 1744 | dev->model = card[nr]; |
1783 | |||
1784 | if ((model==EM2800_BOARD_UNKNOWN)||(model==EM2820_BOARD_UNKNOWN)) { | ||
1785 | em28xx_errdev("Your board has no unique USB ID and thus can't be autodetected.\n"); | ||
1786 | em28xx_errdev("Please pass card=<n> insmod option to workaround that.\n"); | ||
1787 | em28xx_errdev("If there isn't any card number for you, please send an email to:\n"); | ||
1788 | em28xx_errdev("\tV4L Mailing List <video4linux-list@redhat.com>\n"); | ||
1789 | em28xx_errdev("Here is a list of valid choices for the card=<n> insmod option:\n"); | ||
1790 | for (i = 0; i < em28xx_bcount; i++) { | ||
1791 | em28xx_errdev(" card=%d -> %s\n", i, | ||
1792 | em28xx_boards[i].name); | ||
1793 | } | ||
1794 | } | ||
1795 | 1745 | ||
1796 | /* allocate device struct */ | 1746 | /* allocate device struct */ |
1797 | retval = em28xx_init_dev(&dev, udev, nr, model); | 1747 | retval = em28xx_init_dev(&dev, udev, nr); |
1798 | if (retval) | 1748 | if (retval) |
1799 | return retval; | 1749 | return retval; |
1800 | 1750 | ||
1801 | em28xx_info("Found %s\n", em28xx_boards[model].name); | 1751 | em28xx_info("Found %s\n", em28xx_boards[dev->model].name); |
1802 | 1752 | ||
1803 | /* save our data pointer in this interface device */ | 1753 | /* save our data pointer in this interface device */ |
1804 | usb_set_intfdata(interface, dev); | 1754 | usb_set_intfdata(interface, dev); |