diff options
Diffstat (limited to 'drivers/media/video/cafe_ccic.c')
-rw-r--r-- | drivers/media/video/cafe_ccic.c | 180 |
1 files changed, 147 insertions, 33 deletions
diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c index 9536f1a40dd2..2934770dacc3 100644 --- a/drivers/media/video/cafe_ccic.c +++ b/drivers/media/video/cafe_ccic.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/module.h> | 25 | #include <linux/module.h> |
26 | #include <linux/init.h> | 26 | #include <linux/init.h> |
27 | #include <linux/fs.h> | 27 | #include <linux/fs.h> |
28 | #include <linux/dmi.h> | ||
28 | #include <linux/mm.h> | 29 | #include <linux/mm.h> |
29 | #include <linux/pci.h> | 30 | #include <linux/pci.h> |
30 | #include <linux/i2c.h> | 31 | #include <linux/i2c.h> |
@@ -46,6 +47,7 @@ | |||
46 | #include <asm/uaccess.h> | 47 | #include <asm/uaccess.h> |
47 | #include <asm/io.h> | 48 | #include <asm/io.h> |
48 | 49 | ||
50 | #include "ov7670.h" | ||
49 | #include "cafe_ccic-regs.h" | 51 | #include "cafe_ccic-regs.h" |
50 | 52 | ||
51 | #define CAFE_VERSION 0x000002 | 53 | #define CAFE_VERSION 0x000002 |
@@ -180,6 +182,7 @@ struct cafe_camera | |||
180 | /* Current operating parameters */ | 182 | /* Current operating parameters */ |
181 | u32 sensor_type; /* Currently ov7670 only */ | 183 | u32 sensor_type; /* Currently ov7670 only */ |
182 | struct v4l2_pix_format pix_format; | 184 | struct v4l2_pix_format pix_format; |
185 | enum v4l2_mbus_pixelcode mbus_code; | ||
183 | 186 | ||
184 | /* Locks */ | 187 | /* Locks */ |
185 | struct mutex s_mutex; /* Access to this structure */ | 188 | struct mutex s_mutex; /* Access to this structure */ |
@@ -207,6 +210,49 @@ static inline struct cafe_camera *to_cam(struct v4l2_device *dev) | |||
207 | return container_of(dev, struct cafe_camera, v4l2_dev); | 210 | return container_of(dev, struct cafe_camera, v4l2_dev); |
208 | } | 211 | } |
209 | 212 | ||
213 | static struct cafe_format_struct { | ||
214 | __u8 *desc; | ||
215 | __u32 pixelformat; | ||
216 | int bpp; /* Bytes per pixel */ | ||
217 | enum v4l2_mbus_pixelcode mbus_code; | ||
218 | } cafe_formats[] = { | ||
219 | { | ||
220 | .desc = "YUYV 4:2:2", | ||
221 | .pixelformat = V4L2_PIX_FMT_YUYV, | ||
222 | .mbus_code = V4L2_MBUS_FMT_YUYV8_2X8, | ||
223 | .bpp = 2, | ||
224 | }, | ||
225 | { | ||
226 | .desc = "RGB 444", | ||
227 | .pixelformat = V4L2_PIX_FMT_RGB444, | ||
228 | .mbus_code = V4L2_MBUS_FMT_RGB444_2X8_PADHI_LE, | ||
229 | .bpp = 2, | ||
230 | }, | ||
231 | { | ||
232 | .desc = "RGB 565", | ||
233 | .pixelformat = V4L2_PIX_FMT_RGB565, | ||
234 | .mbus_code = V4L2_MBUS_FMT_RGB565_2X8_LE, | ||
235 | .bpp = 2, | ||
236 | }, | ||
237 | { | ||
238 | .desc = "Raw RGB Bayer", | ||
239 | .pixelformat = V4L2_PIX_FMT_SBGGR8, | ||
240 | .mbus_code = V4L2_MBUS_FMT_SBGGR8_1X8, | ||
241 | .bpp = 1 | ||
242 | }, | ||
243 | }; | ||
244 | #define N_CAFE_FMTS ARRAY_SIZE(cafe_formats) | ||
245 | |||
246 | static struct cafe_format_struct *cafe_find_format(u32 pixelformat) | ||
247 | { | ||
248 | unsigned i; | ||
249 | |||
250 | for (i = 0; i < N_CAFE_FMTS; i++) | ||
251 | if (cafe_formats[i].pixelformat == pixelformat) | ||
252 | return cafe_formats + i; | ||
253 | /* Not found? Then return the first format. */ | ||
254 | return cafe_formats; | ||
255 | } | ||
210 | 256 | ||
211 | /* | 257 | /* |
212 | * Start over with DMA buffers - dev_lock needed. | 258 | * Start over with DMA buffers - dev_lock needed. |
@@ -319,7 +365,6 @@ static int cafe_smbus_write_data(struct cafe_camera *cam, | |||
319 | { | 365 | { |
320 | unsigned int rval; | 366 | unsigned int rval; |
321 | unsigned long flags; | 367 | unsigned long flags; |
322 | DEFINE_WAIT(the_wait); | ||
323 | 368 | ||
324 | spin_lock_irqsave(&cam->dev_lock, flags); | 369 | spin_lock_irqsave(&cam->dev_lock, flags); |
325 | rval = TWSIC0_EN | ((addr << TWSIC0_SID_SHIFT) & TWSIC0_SID); | 370 | rval = TWSIC0_EN | ((addr << TWSIC0_SID_SHIFT) & TWSIC0_SID); |
@@ -334,28 +379,27 @@ static int cafe_smbus_write_data(struct cafe_camera *cam, | |||
334 | cafe_reg_write(cam, REG_TWSIC1, rval); | 379 | cafe_reg_write(cam, REG_TWSIC1, rval); |
335 | spin_unlock_irqrestore(&cam->dev_lock, flags); | 380 | spin_unlock_irqrestore(&cam->dev_lock, flags); |
336 | 381 | ||
382 | /* Unfortunately, reading TWSIC1 too soon after sending a command | ||
383 | * causes the device to die. | ||
384 | * Use a busy-wait because we often send a large quantity of small | ||
385 | * commands at-once; using msleep() would cause a lot of context | ||
386 | * switches which take longer than 2ms, resulting in a noticable | ||
387 | * boot-time and capture-start delays. | ||
388 | */ | ||
389 | mdelay(2); | ||
390 | |||
337 | /* | 391 | /* |
338 | * Time to wait for the write to complete. THIS IS A RACY | 392 | * Another sad fact is that sometimes, commands silently complete but |
339 | * WAY TO DO IT, but the sad fact is that reading the TWSIC1 | 393 | * cafe_smbus_write_done() never becomes aware of this. |
340 | * register too quickly after starting the operation sends | 394 | * This happens at random and appears to possible occur with any |
341 | * the device into a place that may be kinder and better, but | 395 | * command. |
342 | * which is absolutely useless for controlling the sensor. In | 396 | * We don't understand why this is. We work around this issue |
343 | * practice we have plenty of time to get into our sleep state | 397 | * with the timeout in the wait below, assuming that all commands |
344 | * before the interrupt hits, and the worst case is that we | 398 | * complete within the timeout. |
345 | * time out and then see that things completed, so this seems | ||
346 | * the best way for now. | ||
347 | */ | 399 | */ |
348 | do { | ||
349 | prepare_to_wait(&cam->smbus_wait, &the_wait, | ||
350 | TASK_UNINTERRUPTIBLE); | ||
351 | schedule_timeout(1); /* even 1 jiffy is too long */ | ||
352 | finish_wait(&cam->smbus_wait, &the_wait); | ||
353 | } while (!cafe_smbus_write_done(cam)); | ||
354 | |||
355 | #ifdef IF_THE_CAFE_HARDWARE_WORKED_RIGHT | ||
356 | wait_event_timeout(cam->smbus_wait, cafe_smbus_write_done(cam), | 400 | wait_event_timeout(cam->smbus_wait, cafe_smbus_write_done(cam), |
357 | CAFE_SMBUS_TIMEOUT); | 401 | CAFE_SMBUS_TIMEOUT); |
358 | #endif | 402 | |
359 | spin_lock_irqsave(&cam->dev_lock, flags); | 403 | spin_lock_irqsave(&cam->dev_lock, flags); |
360 | rval = cafe_reg_read(cam, REG_TWSIC1); | 404 | rval = cafe_reg_read(cam, REG_TWSIC1); |
361 | spin_unlock_irqrestore(&cam->dev_lock, flags); | 405 | spin_unlock_irqrestore(&cam->dev_lock, flags); |
@@ -812,15 +856,15 @@ static int cafe_cam_set_flip(struct cafe_camera *cam) | |||
812 | 856 | ||
813 | static int cafe_cam_configure(struct cafe_camera *cam) | 857 | static int cafe_cam_configure(struct cafe_camera *cam) |
814 | { | 858 | { |
815 | struct v4l2_format fmt; | 859 | struct v4l2_mbus_framefmt mbus_fmt; |
816 | int ret; | 860 | int ret; |
817 | 861 | ||
818 | if (cam->state != S_IDLE) | 862 | if (cam->state != S_IDLE) |
819 | return -EINVAL; | 863 | return -EINVAL; |
820 | fmt.fmt.pix = cam->pix_format; | 864 | v4l2_fill_mbus_format(&mbus_fmt, &cam->pix_format, cam->mbus_code); |
821 | ret = sensor_call(cam, core, init, 0); | 865 | ret = sensor_call(cam, core, init, 0); |
822 | if (ret == 0) | 866 | if (ret == 0) |
823 | ret = sensor_call(cam, video, s_fmt, &fmt); | 867 | ret = sensor_call(cam, video, s_mbus_fmt, &mbus_fmt); |
824 | /* | 868 | /* |
825 | * OV7670 does weird things if flip is set *before* format... | 869 | * OV7670 does weird things if flip is set *before* format... |
826 | */ | 870 | */ |
@@ -1481,7 +1525,7 @@ static int cafe_vidioc_querycap(struct file *file, void *priv, | |||
1481 | /* | 1525 | /* |
1482 | * The default format we use until somebody says otherwise. | 1526 | * The default format we use until somebody says otherwise. |
1483 | */ | 1527 | */ |
1484 | static struct v4l2_pix_format cafe_def_pix_format = { | 1528 | static const struct v4l2_pix_format cafe_def_pix_format = { |
1485 | .width = VGA_WIDTH, | 1529 | .width = VGA_WIDTH, |
1486 | .height = VGA_HEIGHT, | 1530 | .height = VGA_HEIGHT, |
1487 | .pixelformat = V4L2_PIX_FMT_YUYV, | 1531 | .pixelformat = V4L2_PIX_FMT_YUYV, |
@@ -1490,28 +1534,38 @@ static struct v4l2_pix_format cafe_def_pix_format = { | |||
1490 | .sizeimage = VGA_WIDTH*VGA_HEIGHT*2, | 1534 | .sizeimage = VGA_WIDTH*VGA_HEIGHT*2, |
1491 | }; | 1535 | }; |
1492 | 1536 | ||
1537 | static const enum v4l2_mbus_pixelcode cafe_def_mbus_code = | ||
1538 | V4L2_MBUS_FMT_YUYV8_2X8; | ||
1539 | |||
1493 | static int cafe_vidioc_enum_fmt_vid_cap(struct file *filp, | 1540 | static int cafe_vidioc_enum_fmt_vid_cap(struct file *filp, |
1494 | void *priv, struct v4l2_fmtdesc *fmt) | 1541 | void *priv, struct v4l2_fmtdesc *fmt) |
1495 | { | 1542 | { |
1496 | struct cafe_camera *cam = priv; | 1543 | if (fmt->index >= N_CAFE_FMTS) |
1497 | int ret; | 1544 | return -EINVAL; |
1498 | 1545 | strlcpy(fmt->description, cafe_formats[fmt->index].desc, | |
1499 | mutex_lock(&cam->s_mutex); | 1546 | sizeof(fmt->description)); |
1500 | ret = sensor_call(cam, video, enum_fmt, fmt); | 1547 | fmt->pixelformat = cafe_formats[fmt->index].pixelformat; |
1501 | mutex_unlock(&cam->s_mutex); | 1548 | return 0; |
1502 | return ret; | ||
1503 | } | 1549 | } |
1504 | 1550 | ||
1505 | |||
1506 | static int cafe_vidioc_try_fmt_vid_cap(struct file *filp, void *priv, | 1551 | static int cafe_vidioc_try_fmt_vid_cap(struct file *filp, void *priv, |
1507 | struct v4l2_format *fmt) | 1552 | struct v4l2_format *fmt) |
1508 | { | 1553 | { |
1509 | struct cafe_camera *cam = priv; | 1554 | struct cafe_camera *cam = priv; |
1555 | struct cafe_format_struct *f; | ||
1556 | struct v4l2_pix_format *pix = &fmt->fmt.pix; | ||
1557 | struct v4l2_mbus_framefmt mbus_fmt; | ||
1510 | int ret; | 1558 | int ret; |
1511 | 1559 | ||
1560 | f = cafe_find_format(pix->pixelformat); | ||
1561 | pix->pixelformat = f->pixelformat; | ||
1562 | v4l2_fill_mbus_format(&mbus_fmt, pix, f->mbus_code); | ||
1512 | mutex_lock(&cam->s_mutex); | 1563 | mutex_lock(&cam->s_mutex); |
1513 | ret = sensor_call(cam, video, try_fmt, fmt); | 1564 | ret = sensor_call(cam, video, try_mbus_fmt, &mbus_fmt); |
1514 | mutex_unlock(&cam->s_mutex); | 1565 | mutex_unlock(&cam->s_mutex); |
1566 | v4l2_fill_pix_format(pix, &mbus_fmt); | ||
1567 | pix->bytesperline = pix->width * f->bpp; | ||
1568 | pix->sizeimage = pix->height * pix->bytesperline; | ||
1515 | return ret; | 1569 | return ret; |
1516 | } | 1570 | } |
1517 | 1571 | ||
@@ -1519,6 +1573,7 @@ static int cafe_vidioc_s_fmt_vid_cap(struct file *filp, void *priv, | |||
1519 | struct v4l2_format *fmt) | 1573 | struct v4l2_format *fmt) |
1520 | { | 1574 | { |
1521 | struct cafe_camera *cam = priv; | 1575 | struct cafe_camera *cam = priv; |
1576 | struct cafe_format_struct *f; | ||
1522 | int ret; | 1577 | int ret; |
1523 | 1578 | ||
1524 | /* | 1579 | /* |
@@ -1527,6 +1582,9 @@ static int cafe_vidioc_s_fmt_vid_cap(struct file *filp, void *priv, | |||
1527 | */ | 1582 | */ |
1528 | if (cam->state != S_IDLE || cam->n_sbufs > 0) | 1583 | if (cam->state != S_IDLE || cam->n_sbufs > 0) |
1529 | return -EBUSY; | 1584 | return -EBUSY; |
1585 | |||
1586 | f = cafe_find_format(fmt->fmt.pix.pixelformat); | ||
1587 | |||
1530 | /* | 1588 | /* |
1531 | * See if the formatting works in principle. | 1589 | * See if the formatting works in principle. |
1532 | */ | 1590 | */ |
@@ -1539,6 +1597,8 @@ static int cafe_vidioc_s_fmt_vid_cap(struct file *filp, void *priv, | |||
1539 | */ | 1597 | */ |
1540 | mutex_lock(&cam->s_mutex); | 1598 | mutex_lock(&cam->s_mutex); |
1541 | cam->pix_format = fmt->fmt.pix; | 1599 | cam->pix_format = fmt->fmt.pix; |
1600 | cam->mbus_code = f->mbus_code; | ||
1601 | |||
1542 | /* | 1602 | /* |
1543 | * Make sure we have appropriate DMA buffers. | 1603 | * Make sure we have appropriate DMA buffers. |
1544 | */ | 1604 | */ |
@@ -1652,6 +1712,30 @@ static int cafe_vidioc_g_chip_ident(struct file *file, void *priv, | |||
1652 | return sensor_call(cam, core, g_chip_ident, chip); | 1712 | return sensor_call(cam, core, g_chip_ident, chip); |
1653 | } | 1713 | } |
1654 | 1714 | ||
1715 | static int cafe_vidioc_enum_framesizes(struct file *filp, void *priv, | ||
1716 | struct v4l2_frmsizeenum *sizes) | ||
1717 | { | ||
1718 | struct cafe_camera *cam = priv; | ||
1719 | int ret; | ||
1720 | |||
1721 | mutex_lock(&cam->s_mutex); | ||
1722 | ret = sensor_call(cam, video, enum_framesizes, sizes); | ||
1723 | mutex_unlock(&cam->s_mutex); | ||
1724 | return ret; | ||
1725 | } | ||
1726 | |||
1727 | static int cafe_vidioc_enum_frameintervals(struct file *filp, void *priv, | ||
1728 | struct v4l2_frmivalenum *interval) | ||
1729 | { | ||
1730 | struct cafe_camera *cam = priv; | ||
1731 | int ret; | ||
1732 | |||
1733 | mutex_lock(&cam->s_mutex); | ||
1734 | ret = sensor_call(cam, video, enum_frameintervals, interval); | ||
1735 | mutex_unlock(&cam->s_mutex); | ||
1736 | return ret; | ||
1737 | } | ||
1738 | |||
1655 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 1739 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
1656 | static int cafe_vidioc_g_register(struct file *file, void *priv, | 1740 | static int cafe_vidioc_g_register(struct file *file, void *priv, |
1657 | struct v4l2_dbg_register *reg) | 1741 | struct v4l2_dbg_register *reg) |
@@ -1715,6 +1799,8 @@ static const struct v4l2_ioctl_ops cafe_v4l_ioctl_ops = { | |||
1715 | .vidioc_s_ctrl = cafe_vidioc_s_ctrl, | 1799 | .vidioc_s_ctrl = cafe_vidioc_s_ctrl, |
1716 | .vidioc_g_parm = cafe_vidioc_g_parm, | 1800 | .vidioc_g_parm = cafe_vidioc_g_parm, |
1717 | .vidioc_s_parm = cafe_vidioc_s_parm, | 1801 | .vidioc_s_parm = cafe_vidioc_s_parm, |
1802 | .vidioc_enum_framesizes = cafe_vidioc_enum_framesizes, | ||
1803 | .vidioc_enum_frameintervals = cafe_vidioc_enum_frameintervals, | ||
1718 | .vidioc_g_chip_ident = cafe_vidioc_g_chip_ident, | 1804 | .vidioc_g_chip_ident = cafe_vidioc_g_chip_ident, |
1719 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 1805 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
1720 | .vidioc_g_register = cafe_vidioc_g_register, | 1806 | .vidioc_g_register = cafe_vidioc_g_register, |
@@ -1890,11 +1976,33 @@ static irqreturn_t cafe_irq(int irq, void *data) | |||
1890 | * PCI interface stuff. | 1976 | * PCI interface stuff. |
1891 | */ | 1977 | */ |
1892 | 1978 | ||
1979 | static const struct dmi_system_id olpc_xo1_dmi[] = { | ||
1980 | { | ||
1981 | .matches = { | ||
1982 | DMI_MATCH(DMI_SYS_VENDOR, "OLPC"), | ||
1983 | DMI_MATCH(DMI_PRODUCT_NAME, "XO"), | ||
1984 | DMI_MATCH(DMI_PRODUCT_VERSION, "1"), | ||
1985 | }, | ||
1986 | }, | ||
1987 | { } | ||
1988 | }; | ||
1989 | |||
1893 | static int cafe_pci_probe(struct pci_dev *pdev, | 1990 | static int cafe_pci_probe(struct pci_dev *pdev, |
1894 | const struct pci_device_id *id) | 1991 | const struct pci_device_id *id) |
1895 | { | 1992 | { |
1896 | int ret; | 1993 | int ret; |
1897 | struct cafe_camera *cam; | 1994 | struct cafe_camera *cam; |
1995 | struct ov7670_config sensor_cfg = { | ||
1996 | /* This controller only does SMBUS */ | ||
1997 | .use_smbus = true, | ||
1998 | |||
1999 | /* | ||
2000 | * Exclude QCIF mode, because it only captures a tiny portion | ||
2001 | * of the sensor FOV | ||
2002 | */ | ||
2003 | .min_width = 320, | ||
2004 | .min_height = 240, | ||
2005 | }; | ||
1898 | 2006 | ||
1899 | /* | 2007 | /* |
1900 | * Start putting together one of our big camera structures. | 2008 | * Start putting together one of our big camera structures. |
@@ -1915,6 +2023,7 @@ static int cafe_pci_probe(struct pci_dev *pdev, | |||
1915 | init_waitqueue_head(&cam->iowait); | 2023 | init_waitqueue_head(&cam->iowait); |
1916 | cam->pdev = pdev; | 2024 | cam->pdev = pdev; |
1917 | cam->pix_format = cafe_def_pix_format; | 2025 | cam->pix_format = cafe_def_pix_format; |
2026 | cam->mbus_code = cafe_def_mbus_code; | ||
1918 | INIT_LIST_HEAD(&cam->dev_list); | 2027 | INIT_LIST_HEAD(&cam->dev_list); |
1919 | INIT_LIST_HEAD(&cam->sb_avail); | 2028 | INIT_LIST_HEAD(&cam->sb_avail); |
1920 | INIT_LIST_HEAD(&cam->sb_full); | 2029 | INIT_LIST_HEAD(&cam->sb_full); |
@@ -1951,13 +2060,18 @@ static int cafe_pci_probe(struct pci_dev *pdev, | |||
1951 | if (ret) | 2060 | if (ret) |
1952 | goto out_freeirq; | 2061 | goto out_freeirq; |
1953 | 2062 | ||
2063 | /* Apply XO-1 clock speed */ | ||
2064 | if (dmi_check_system(olpc_xo1_dmi)) | ||
2065 | sensor_cfg.clock_speed = 45; | ||
2066 | |||
1954 | cam->sensor_addr = 0x42; | 2067 | cam->sensor_addr = 0x42; |
1955 | cam->sensor = v4l2_i2c_new_subdev(&cam->v4l2_dev, &cam->i2c_adapter, | 2068 | cam->sensor = v4l2_i2c_new_subdev(&cam->v4l2_dev, &cam->i2c_adapter, |
1956 | "ov7670", "ov7670", cam->sensor_addr, NULL); | 2069 | NULL, "ov7670", cam->sensor_addr, NULL); |
1957 | if (cam->sensor == NULL) { | 2070 | if (cam->sensor == NULL) { |
1958 | ret = -ENODEV; | 2071 | ret = -ENODEV; |
1959 | goto out_smbus; | 2072 | goto out_smbus; |
1960 | } | 2073 | } |
2074 | |||
1961 | ret = cafe_cam_init(cam); | 2075 | ret = cafe_cam_init(cam); |
1962 | if (ret) | 2076 | if (ret) |
1963 | goto out_smbus; | 2077 | goto out_smbus; |