aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/cx18
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/cx18')
-rw-r--r--drivers/media/video/cx18/Kconfig4
-rw-r--r--drivers/media/video/cx18/cx18-cards.c18
-rw-r--r--drivers/media/video/cx18/cx18-cards.h2
-rw-r--r--drivers/media/video/cx18/cx18-driver.c27
-rw-r--r--drivers/media/video/cx18/cx18-driver.h25
-rw-r--r--drivers/media/video/cx18/cx18-fileops.c70
-rw-r--r--drivers/media/video/cx18/cx18-fileops.h2
-rw-r--r--drivers/media/video/cx18/cx18-ioctl.c144
-rw-r--r--drivers/media/video/cx18/cx18-mailbox.c58
-rw-r--r--drivers/media/video/cx18/cx18-streams.c177
-rw-r--r--drivers/media/video/cx18/cx18-version.h2
-rw-r--r--drivers/media/video/cx18/cx23418.h6
12 files changed, 517 insertions, 18 deletions
diff --git a/drivers/media/video/cx18/Kconfig b/drivers/media/video/cx18/Kconfig
index d9d2f6ad6ff..53b3c770257 100644
--- a/drivers/media/video/cx18/Kconfig
+++ b/drivers/media/video/cx18/Kconfig
@@ -2,6 +2,7 @@ config VIDEO_CX18
2 tristate "Conexant cx23418 MPEG encoder support" 2 tristate "Conexant cx23418 MPEG encoder support"
3 depends on VIDEO_V4L2 && DVB_CORE && PCI && I2C && EXPERIMENTAL 3 depends on VIDEO_V4L2 && DVB_CORE && PCI && I2C && EXPERIMENTAL
4 select I2C_ALGOBIT 4 select I2C_ALGOBIT
5 select VIDEOBUF_VMALLOC
5 depends on RC_CORE 6 depends on RC_CORE
6 select VIDEO_TUNER 7 select VIDEO_TUNER
7 select VIDEO_TVEEPROM 8 select VIDEO_TVEEPROM
@@ -9,6 +10,9 @@ config VIDEO_CX18
9 select VIDEO_CS5345 10 select VIDEO_CS5345
10 select DVB_S5H1409 if !DVB_FE_CUSTOMISE 11 select DVB_S5H1409 if !DVB_FE_CUSTOMISE
11 select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE 12 select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE
13 select DVB_S5H1411 if !DVB_FE_CUSTOMISE
14 select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE
15 select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMISE
12 ---help--- 16 ---help---
13 This is a video4linux driver for Conexant cx23418 based 17 This is a video4linux driver for Conexant cx23418 based
14 PCI combo video recorder devices. 18 PCI combo video recorder devices.
diff --git a/drivers/media/video/cx18/cx18-cards.c b/drivers/media/video/cx18/cx18-cards.c
index 68ad1963f42..c07c849b1aa 100644
--- a/drivers/media/video/cx18/cx18-cards.c
+++ b/drivers/media/video/cx18/cx18-cards.c
@@ -39,6 +39,16 @@ static struct cx18_card_tuner_i2c cx18_i2c_std = {
39 .tv = { 0x61, 0x60, I2C_CLIENT_END }, 39 .tv = { 0x61, 0x60, I2C_CLIENT_END },
40}; 40};
41 41
42/*
43 * usual i2c tuner addresses to probe with additional demod address for
44 * an NXP TDA8295 at 0x42 (N.B. it can possibly be at 0x4b or 0x4c too).
45 */
46static struct cx18_card_tuner_i2c cx18_i2c_nxp = {
47 .radio = { I2C_CLIENT_END },
48 .demod = { 0x42, 0x43, I2C_CLIENT_END },
49 .tv = { 0x61, 0x60, I2C_CLIENT_END },
50};
51
42/* Please add new PCI IDs to: http://pci-ids.ucw.cz/ 52/* Please add new PCI IDs to: http://pci-ids.ucw.cz/
43 This keeps the PCI ID database up to date. Note that the entries 53 This keeps the PCI ID database up to date. Note that the entries
44 must be added under vendor 0x4444 (Conexant) as subsystem IDs. 54 must be added under vendor 0x4444 (Conexant) as subsystem IDs.
@@ -131,15 +141,15 @@ static const struct cx18_card cx18_card_hvr1600_s5h1411 = {
131 .tune_lane = 0, 141 .tune_lane = 0,
132 .initial_emrs = 0, 142 .initial_emrs = 0,
133 }, 143 },
134 .gpio_init.initial_value = 0x3001, 144 .gpio_init.initial_value = 0x3801,
135 .gpio_init.direction = 0x3001, 145 .gpio_init.direction = 0x3801,
136 .gpio_i2c_slave_reset = { 146 .gpio_i2c_slave_reset = {
137 .active_lo_mask = 0x3001, 147 .active_lo_mask = 0x3801,
138 .msecs_asserted = 10, 148 .msecs_asserted = 10,
139 .msecs_recovery = 40, 149 .msecs_recovery = 40,
140 .ir_reset_mask = 0x0001, 150 .ir_reset_mask = 0x0001,
141 }, 151 },
142 .i2c = &cx18_i2c_std, 152 .i2c = &cx18_i2c_nxp,
143}; 153};
144 154
145static const struct cx18_card cx18_card_hvr1600_samsung = { 155static const struct cx18_card cx18_card_hvr1600_samsung = {
diff --git a/drivers/media/video/cx18/cx18-cards.h b/drivers/media/video/cx18/cx18-cards.h
index 3e750068f27..add7391ecab 100644
--- a/drivers/media/video/cx18/cx18-cards.h
+++ b/drivers/media/video/cx18/cx18-cards.h
@@ -109,7 +109,7 @@ struct cx18_card_tuner {
109 109
110struct cx18_card_tuner_i2c { 110struct cx18_card_tuner_i2c {
111 unsigned short radio[2];/* radio tuner i2c address to probe */ 111 unsigned short radio[2];/* radio tuner i2c address to probe */
112 unsigned short demod[2];/* demodulator i2c address to probe */ 112 unsigned short demod[3];/* demodulator i2c address to probe */
113 unsigned short tv[4]; /* tv tuner i2c addresses to probe */ 113 unsigned short tv[4]; /* tv tuner i2c addresses to probe */
114}; 114};
115 115
diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c
index 321c1b79794..9e2f870f425 100644
--- a/drivers/media/video/cx18/cx18-driver.c
+++ b/drivers/media/video/cx18/cx18-driver.c
@@ -423,7 +423,16 @@ static void cx18_process_eeprom(struct cx18 *cx)
423 return; 423 return;
424 424
425 /* autodetect tuner standard */ 425 /* autodetect tuner standard */
426 if (tv.tuner_formats & V4L2_STD_PAL) { 426#define TVEEPROM_TUNER_FORMAT_ALL (V4L2_STD_B | V4L2_STD_GH | \
427 V4L2_STD_MN | \
428 V4L2_STD_PAL_I | \
429 V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC | \
430 V4L2_STD_DK)
431 if ((tv.tuner_formats & TVEEPROM_TUNER_FORMAT_ALL)
432 == TVEEPROM_TUNER_FORMAT_ALL) {
433 CX18_DEBUG_INFO("Worldwide tuner detected\n");
434 cx->std = V4L2_STD_ALL;
435 } else if (tv.tuner_formats & V4L2_STD_PAL) {
427 CX18_DEBUG_INFO("PAL tuner detected\n"); 436 CX18_DEBUG_INFO("PAL tuner detected\n");
428 cx->std |= V4L2_STD_PAL_BG | V4L2_STD_PAL_H; 437 cx->std |= V4L2_STD_PAL_BG | V4L2_STD_PAL_H;
429 } else if (tv.tuner_formats & V4L2_STD_NTSC) { 438 } else if (tv.tuner_formats & V4L2_STD_NTSC) {
@@ -818,7 +827,7 @@ static int cx18_setup_pci(struct cx18 *cx, struct pci_dev *pci_dev,
818 cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; 827 cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
819 pci_write_config_word(pci_dev, PCI_COMMAND, cmd); 828 pci_write_config_word(pci_dev, PCI_COMMAND, cmd);
820 829
821 pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &cx->card_rev); 830 cx->card_rev = pci_dev->revision;
822 pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &pci_latency); 831 pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &pci_latency);
823 832
824 if (pci_latency < 64 && cx18_pci_latency) { 833 if (pci_latency < 64 && cx18_pci_latency) {
@@ -1001,7 +1010,15 @@ static int __devinit cx18_probe(struct pci_dev *pci_dev,
1001 if (cx->card->hw_all & CX18_HW_TVEEPROM) { 1010 if (cx->card->hw_all & CX18_HW_TVEEPROM) {
1002 /* Based on the model number the cardtype may be changed. 1011 /* Based on the model number the cardtype may be changed.
1003 The PCI IDs are not always reliable. */ 1012 The PCI IDs are not always reliable. */
1013 const struct cx18_card *orig_card = cx->card;
1004 cx18_process_eeprom(cx); 1014 cx18_process_eeprom(cx);
1015
1016 if (cx->card != orig_card) {
1017 /* Changed the cardtype; re-reset the I2C chips */
1018 cx18_gpio_init(cx);
1019 cx18_call_hw(cx, CX18_HW_GPIO_RESET_CTRL,
1020 core, reset, (u32) CX18_GPIO_RESET_I2C);
1021 }
1005 } 1022 }
1006 if (cx->card->comment) 1023 if (cx->card->comment)
1007 CX18_INFO("%s", cx->card->comment); 1024 CX18_INFO("%s", cx->card->comment);
@@ -1087,6 +1104,8 @@ static int __devinit cx18_probe(struct pci_dev *pci_dev,
1087 /* The tuner is fixed to the standard. The other inputs (e.g. S-Video) 1104 /* The tuner is fixed to the standard. The other inputs (e.g. S-Video)
1088 are not. */ 1105 are not. */
1089 cx->tuner_std = cx->std; 1106 cx->tuner_std = cx->std;
1107 if (cx->std == V4L2_STD_ALL)
1108 cx->std = V4L2_STD_NTSC_M;
1090 1109
1091 retval = cx18_streams_setup(cx); 1110 retval = cx18_streams_setup(cx);
1092 if (retval) { 1111 if (retval) {
@@ -1133,6 +1152,7 @@ int cx18_init_on_first_open(struct cx18 *cx)
1133 int fw_retry_count = 3; 1152 int fw_retry_count = 3;
1134 struct v4l2_frequency vf; 1153 struct v4l2_frequency vf;
1135 struct cx18_open_id fh; 1154 struct cx18_open_id fh;
1155 v4l2_std_id std;
1136 1156
1137 fh.cx = cx; 1157 fh.cx = cx;
1138 1158
@@ -1220,7 +1240,8 @@ int cx18_init_on_first_open(struct cx18 *cx)
1220 /* Let the VIDIOC_S_STD ioctl do all the work, keeps the code 1240 /* Let the VIDIOC_S_STD ioctl do all the work, keeps the code
1221 in one place. */ 1241 in one place. */
1222 cx->std++; /* Force full standard initialization */ 1242 cx->std++; /* Force full standard initialization */
1223 cx18_s_std(NULL, &fh, &cx->tuner_std); 1243 std = (cx->tuner_std == V4L2_STD_ALL) ? V4L2_STD_NTSC_M : cx->tuner_std;
1244 cx18_s_std(NULL, &fh, &std);
1224 cx18_s_frequency(NULL, &fh, &vf); 1245 cx18_s_frequency(NULL, &fh, &vf);
1225 return 0; 1246 return 0;
1226} 1247}
diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h
index b86a740c68d..086427288de 100644
--- a/drivers/media/video/cx18/cx18-driver.h
+++ b/drivers/media/video/cx18/cx18-driver.h
@@ -65,6 +65,10 @@
65#include "dvb_net.h" 65#include "dvb_net.h"
66#include "dvbdev.h" 66#include "dvbdev.h"
67 67
68/* Videobuf / YUV support */
69#include <media/videobuf-core.h>
70#include <media/videobuf-vmalloc.h>
71
68#ifndef CONFIG_PCI 72#ifndef CONFIG_PCI
69# error "This driver requires kernel PCI support." 73# error "This driver requires kernel PCI support."
70#endif 74#endif
@@ -403,6 +407,23 @@ struct cx18_stream {
403 struct cx18_queue q_idle; /* idle - not in rotation */ 407 struct cx18_queue q_idle; /* idle - not in rotation */
404 408
405 struct work_struct out_work_order; 409 struct work_struct out_work_order;
410
411 /* Videobuf for YUV video */
412 u32 pixelformat;
413 struct list_head vb_capture; /* video capture queue */
414 spinlock_t vb_lock;
415 struct timer_list vb_timeout;
416
417 struct videobuf_queue vbuf_q;
418 spinlock_t vbuf_q_lock; /* Protect vbuf_q */
419 enum v4l2_buf_type vb_type;
420};
421
422struct cx18_videobuf_buffer {
423 /* Common video buffer sub-system struct */
424 struct videobuf_buffer vb;
425 v4l2_std_id tvnorm; /* selected tv norm */
426 u32 bytes_used;
406}; 427};
407 428
408struct cx18_open_id { 429struct cx18_open_id {
@@ -410,6 +431,10 @@ struct cx18_open_id {
410 u32 open_id; 431 u32 open_id;
411 int type; 432 int type;
412 struct cx18 *cx; 433 struct cx18 *cx;
434
435 struct videobuf_queue vbuf_q;
436 spinlock_t s_lock; /* Protect vbuf_q */
437 enum v4l2_buf_type vb_type;
413}; 438};
414 439
415static inline struct cx18_open_id *fh2id(struct v4l2_fh *fh) 440static inline struct cx18_open_id *fh2id(struct v4l2_fh *fh)
diff --git a/drivers/media/video/cx18/cx18-fileops.c b/drivers/media/video/cx18/cx18-fileops.c
index e9802d99439..07411f34885 100644
--- a/drivers/media/video/cx18/cx18-fileops.c
+++ b/drivers/media/video/cx18/cx18-fileops.c
@@ -597,6 +597,13 @@ ssize_t cx18_v4l2_read(struct file *filp, char __user *buf, size_t count,
597 mutex_unlock(&cx->serialize_lock); 597 mutex_unlock(&cx->serialize_lock);
598 if (rc) 598 if (rc)
599 return rc; 599 return rc;
600
601 if ((s->vb_type == V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
602 (id->type == CX18_ENC_STREAM_TYPE_YUV)) {
603 return videobuf_read_stream(&s->vbuf_q, buf, count, pos, 0,
604 filp->f_flags & O_NONBLOCK);
605 }
606
600 return cx18_read_pos(s, buf, count, pos, filp->f_flags & O_NONBLOCK); 607 return cx18_read_pos(s, buf, count, pos, filp->f_flags & O_NONBLOCK);
601} 608}
602 609
@@ -622,6 +629,15 @@ unsigned int cx18_v4l2_enc_poll(struct file *filp, poll_table *wait)
622 CX18_DEBUG_FILE("Encoder poll started capture\n"); 629 CX18_DEBUG_FILE("Encoder poll started capture\n");
623 } 630 }
624 631
632 if ((s->vb_type == V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
633 (id->type == CX18_ENC_STREAM_TYPE_YUV)) {
634 int videobuf_poll = videobuf_poll_stream(filp, &s->vbuf_q, wait);
635 if (eof && videobuf_poll == POLLERR)
636 return POLLHUP;
637 else
638 return videobuf_poll;
639 }
640
625 /* add stream's waitq to the poll list */ 641 /* add stream's waitq to the poll list */
626 CX18_DEBUG_HI_FILE("Encoder poll\n"); 642 CX18_DEBUG_HI_FILE("Encoder poll\n");
627 poll_wait(filp, &s->waitq, wait); 643 poll_wait(filp, &s->waitq, wait);
@@ -633,6 +649,58 @@ unsigned int cx18_v4l2_enc_poll(struct file *filp, poll_table *wait)
633 return 0; 649 return 0;
634} 650}
635 651
652int cx18_v4l2_mmap(struct file *file, struct vm_area_struct *vma)
653{
654 struct cx18_open_id *id = file->private_data;
655 struct cx18 *cx = id->cx;
656 struct cx18_stream *s = &cx->streams[id->type];
657 int eof = test_bit(CX18_F_S_STREAMOFF, &s->s_flags);
658
659 if ((s->vb_type == V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
660 (id->type == CX18_ENC_STREAM_TYPE_YUV)) {
661
662 /* Start a capture if there is none */
663 if (!eof && !test_bit(CX18_F_S_STREAMING, &s->s_flags)) {
664 int rc;
665
666 mutex_lock(&cx->serialize_lock);
667 rc = cx18_start_capture(id);
668 mutex_unlock(&cx->serialize_lock);
669 if (rc) {
670 CX18_DEBUG_INFO(
671 "Could not start capture for %s (%d)\n",
672 s->name, rc);
673 return -EINVAL;
674 }
675 CX18_DEBUG_FILE("Encoder mmap started capture\n");
676 }
677
678 return videobuf_mmap_mapper(&s->vbuf_q, vma);
679 }
680
681 return -EINVAL;
682}
683
684void cx18_vb_timeout(unsigned long data)
685{
686 struct cx18_stream *s = (struct cx18_stream *)data;
687 struct cx18_videobuf_buffer *buf;
688 unsigned long flags;
689
690 /* Return all of the buffers in error state, so the vbi/vid inode
691 * can return from blocking.
692 */
693 spin_lock_irqsave(&s->vb_lock, flags);
694 while (!list_empty(&s->vb_capture)) {
695 buf = list_entry(s->vb_capture.next,
696 struct cx18_videobuf_buffer, vb.queue);
697 list_del(&buf->vb.queue);
698 buf->vb.state = VIDEOBUF_ERROR;
699 wake_up(&buf->vb.done);
700 }
701 spin_unlock_irqrestore(&s->vb_lock, flags);
702}
703
636void cx18_stop_capture(struct cx18_open_id *id, int gop_end) 704void cx18_stop_capture(struct cx18_open_id *id, int gop_end)
637{ 705{
638 struct cx18 *cx = id->cx; 706 struct cx18 *cx = id->cx;
@@ -716,6 +784,8 @@ int cx18_v4l2_close(struct file *filp)
716 cx18_release_stream(s); 784 cx18_release_stream(s);
717 } else { 785 } else {
718 cx18_stop_capture(id, 0); 786 cx18_stop_capture(id, 0);
787 if (id->type == CX18_ENC_STREAM_TYPE_YUV)
788 videobuf_mmap_free(&id->vbuf_q);
719 } 789 }
720 kfree(id); 790 kfree(id);
721 mutex_unlock(&cx->serialize_lock); 791 mutex_unlock(&cx->serialize_lock);
diff --git a/drivers/media/video/cx18/cx18-fileops.h b/drivers/media/video/cx18/cx18-fileops.h
index 5c8fcb884f0..b9e5110ad04 100644
--- a/drivers/media/video/cx18/cx18-fileops.h
+++ b/drivers/media/video/cx18/cx18-fileops.h
@@ -33,6 +33,8 @@ int cx18_start_capture(struct cx18_open_id *id);
33void cx18_stop_capture(struct cx18_open_id *id, int gop_end); 33void cx18_stop_capture(struct cx18_open_id *id, int gop_end);
34void cx18_mute(struct cx18 *cx); 34void cx18_mute(struct cx18 *cx);
35void cx18_unmute(struct cx18 *cx); 35void cx18_unmute(struct cx18 *cx);
36int cx18_v4l2_mmap(struct file *file, struct vm_area_struct *vma);
37void cx18_vb_timeout(unsigned long data);
36 38
37/* Shared with cx18-alsa module */ 39/* Shared with cx18-alsa module */
38int cx18_claim_stream(struct cx18_open_id *id, int type); 40int cx18_claim_stream(struct cx18_open_id *id, int type);
diff --git a/drivers/media/video/cx18/cx18-ioctl.c b/drivers/media/video/cx18/cx18-ioctl.c
index 4f041c033c5..1933d4d11bf 100644
--- a/drivers/media/video/cx18/cx18-ioctl.c
+++ b/drivers/media/video/cx18/cx18-ioctl.c
@@ -150,6 +150,7 @@ static int cx18_g_fmt_vid_cap(struct file *file, void *fh,
150{ 150{
151 struct cx18_open_id *id = fh2id(fh); 151 struct cx18_open_id *id = fh2id(fh);
152 struct cx18 *cx = id->cx; 152 struct cx18 *cx = id->cx;
153 struct cx18_stream *s = &cx->streams[id->type];
153 struct v4l2_pix_format *pixfmt = &fmt->fmt.pix; 154 struct v4l2_pix_format *pixfmt = &fmt->fmt.pix;
154 155
155 pixfmt->width = cx->cxhdl.width; 156 pixfmt->width = cx->cxhdl.width;
@@ -158,9 +159,13 @@ static int cx18_g_fmt_vid_cap(struct file *file, void *fh,
158 pixfmt->field = V4L2_FIELD_INTERLACED; 159 pixfmt->field = V4L2_FIELD_INTERLACED;
159 pixfmt->priv = 0; 160 pixfmt->priv = 0;
160 if (id->type == CX18_ENC_STREAM_TYPE_YUV) { 161 if (id->type == CX18_ENC_STREAM_TYPE_YUV) {
161 pixfmt->pixelformat = V4L2_PIX_FMT_HM12; 162 pixfmt->pixelformat = s->pixelformat;
162 /* YUV size is (Y=(h*720) + UV=(h*(720/2))) */ 163 /* HM12 YUV size is (Y=(h*720) + UV=(h*(720/2)))
163 pixfmt->sizeimage = pixfmt->height * 720 * 3 / 2; 164 UYUV YUV size is (Y=(h*720) + UV=(h*(720))) */
165 if (s->pixelformat == V4L2_PIX_FMT_HM12)
166 pixfmt->sizeimage = pixfmt->height * 720 * 3 / 2;
167 else
168 pixfmt->sizeimage = pixfmt->height * 720 * 2;
164 pixfmt->bytesperline = 720; 169 pixfmt->bytesperline = 720;
165 } else { 170 } else {
166 pixfmt->pixelformat = V4L2_PIX_FMT_MPEG; 171 pixfmt->pixelformat = V4L2_PIX_FMT_MPEG;
@@ -237,7 +242,6 @@ static int cx18_try_fmt_vid_cap(struct file *file, void *fh,
237 h = min(h, cx->is_50hz ? 576 : 480); 242 h = min(h, cx->is_50hz ? 576 : 480);
238 h = max(h, min_h); 243 h = max(h, min_h);
239 244
240 cx18_g_fmt_vid_cap(file, fh, fmt);
241 fmt->fmt.pix.width = w; 245 fmt->fmt.pix.width = w;
242 fmt->fmt.pix.height = h; 246 fmt->fmt.pix.height = h;
243 return 0; 247 return 0;
@@ -274,6 +278,7 @@ static int cx18_s_fmt_vid_cap(struct file *file, void *fh,
274 struct cx18_open_id *id = fh2id(fh); 278 struct cx18_open_id *id = fh2id(fh);
275 struct cx18 *cx = id->cx; 279 struct cx18 *cx = id->cx;
276 struct v4l2_mbus_framefmt mbus_fmt; 280 struct v4l2_mbus_framefmt mbus_fmt;
281 struct cx18_stream *s = &cx->streams[id->type];
277 int ret; 282 int ret;
278 int w, h; 283 int w, h;
279 284
@@ -283,12 +288,15 @@ static int cx18_s_fmt_vid_cap(struct file *file, void *fh,
283 w = fmt->fmt.pix.width; 288 w = fmt->fmt.pix.width;
284 h = fmt->fmt.pix.height; 289 h = fmt->fmt.pix.height;
285 290
286 if (cx->cxhdl.width == w && cx->cxhdl.height == h) 291 if (cx->cxhdl.width == w && cx->cxhdl.height == h &&
292 s->pixelformat == fmt->fmt.pix.pixelformat)
287 return 0; 293 return 0;
288 294
289 if (atomic_read(&cx->ana_capturing) > 0) 295 if (atomic_read(&cx->ana_capturing) > 0)
290 return -EBUSY; 296 return -EBUSY;
291 297
298 s->pixelformat = fmt->fmt.pix.pixelformat;
299
292 mbus_fmt.width = cx->cxhdl.width = w; 300 mbus_fmt.width = cx->cxhdl.width = w;
293 mbus_fmt.height = cx->cxhdl.height = h; 301 mbus_fmt.height = cx->cxhdl.height = h;
294 mbus_fmt.code = V4L2_MBUS_FMT_FIXED; 302 mbus_fmt.code = V4L2_MBUS_FMT_FIXED;
@@ -540,16 +548,19 @@ static int cx18_g_crop(struct file *file, void *fh, struct v4l2_crop *crop)
540static int cx18_enum_fmt_vid_cap(struct file *file, void *fh, 548static int cx18_enum_fmt_vid_cap(struct file *file, void *fh,
541 struct v4l2_fmtdesc *fmt) 549 struct v4l2_fmtdesc *fmt)
542{ 550{
543 static struct v4l2_fmtdesc formats[] = { 551 static const struct v4l2_fmtdesc formats[] = {
544 { 0, V4L2_BUF_TYPE_VIDEO_CAPTURE, 0, 552 { 0, V4L2_BUF_TYPE_VIDEO_CAPTURE, 0,
545 "HM12 (YUV 4:1:1)", V4L2_PIX_FMT_HM12, { 0, 0, 0, 0 } 553 "HM12 (YUV 4:1:1)", V4L2_PIX_FMT_HM12, { 0, 0, 0, 0 }
546 }, 554 },
547 { 1, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FMT_FLAG_COMPRESSED, 555 { 1, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FMT_FLAG_COMPRESSED,
548 "MPEG", V4L2_PIX_FMT_MPEG, { 0, 0, 0, 0 } 556 "MPEG", V4L2_PIX_FMT_MPEG, { 0, 0, 0, 0 }
549 } 557 },
558 { 2, V4L2_BUF_TYPE_VIDEO_CAPTURE, 0,
559 "UYVY 4:2:2", V4L2_PIX_FMT_UYVY, { 0, 0, 0, 0 }
560 },
550 }; 561 };
551 562
552 if (fmt->index > 1) 563 if (fmt->index > ARRAY_SIZE(formats) - 1)
553 return -EINVAL; 564 return -EINVAL;
554 *fmt = formats[fmt->index]; 565 *fmt = formats[fmt->index];
555 return 0; 566 return 0;
@@ -863,6 +874,117 @@ static int cx18_g_enc_index(struct file *file, void *fh,
863 return 0; 874 return 0;
864} 875}
865 876
877static struct videobuf_queue *cx18_vb_queue(struct cx18_open_id *id)
878{
879 struct videobuf_queue *q = NULL;
880 struct cx18 *cx = id->cx;
881 struct cx18_stream *s = &cx->streams[id->type];
882
883 switch (s->vb_type) {
884 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
885 q = &s->vbuf_q;
886 break;
887 case V4L2_BUF_TYPE_VBI_CAPTURE:
888 break;
889 default:
890 break;
891 }
892 return q;
893}
894
895static int cx18_streamon(struct file *file, void *priv,
896 enum v4l2_buf_type type)
897{
898 struct cx18_open_id *id = file->private_data;
899 struct cx18 *cx = id->cx;
900 struct cx18_stream *s = &cx->streams[id->type];
901
902 /* Start the hardware only if we're the video device */
903 if ((s->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
904 (s->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE))
905 return -EINVAL;
906
907 if (id->type != CX18_ENC_STREAM_TYPE_YUV)
908 return -EINVAL;
909
910 /* Establish a buffer timeout */
911 mod_timer(&s->vb_timeout, msecs_to_jiffies(2000) + jiffies);
912
913 return videobuf_streamon(cx18_vb_queue(id));
914}
915
916static int cx18_streamoff(struct file *file, void *priv,
917 enum v4l2_buf_type type)
918{
919 struct cx18_open_id *id = file->private_data;
920 struct cx18 *cx = id->cx;
921 struct cx18_stream *s = &cx->streams[id->type];
922
923 /* Start the hardware only if we're the video device */
924 if ((s->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
925 (s->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE))
926 return -EINVAL;
927
928 if (id->type != CX18_ENC_STREAM_TYPE_YUV)
929 return -EINVAL;
930
931 return videobuf_streamoff(cx18_vb_queue(id));
932}
933
934static int cx18_reqbufs(struct file *file, void *priv,
935 struct v4l2_requestbuffers *rb)
936{
937 struct cx18_open_id *id = file->private_data;
938 struct cx18 *cx = id->cx;
939 struct cx18_stream *s = &cx->streams[id->type];
940
941 if ((s->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
942 (s->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE))
943 return -EINVAL;
944
945 return videobuf_reqbufs(cx18_vb_queue(id), rb);
946}
947
948static int cx18_querybuf(struct file *file, void *priv,
949 struct v4l2_buffer *b)
950{
951 struct cx18_open_id *id = file->private_data;
952 struct cx18 *cx = id->cx;
953 struct cx18_stream *s = &cx->streams[id->type];
954
955 if ((s->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
956 (s->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE))
957 return -EINVAL;
958
959 return videobuf_querybuf(cx18_vb_queue(id), b);
960}
961
962static int cx18_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
963{
964 struct cx18_open_id *id = file->private_data;
965 struct cx18 *cx = id->cx;
966 struct cx18_stream *s = &cx->streams[id->type];
967
968 if ((s->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
969 (s->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE))
970 return -EINVAL;
971
972 return videobuf_qbuf(cx18_vb_queue(id), b);
973}
974
975static int cx18_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
976{
977 struct cx18_open_id *id = file->private_data;
978 struct cx18 *cx = id->cx;
979 struct cx18_stream *s = &cx->streams[id->type];
980
981 if ((s->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
982 (s->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE))
983 return -EINVAL;
984
985 return videobuf_dqbuf(cx18_vb_queue(id), b, file->f_flags & O_NONBLOCK);
986}
987
866static int cx18_encoder_cmd(struct file *file, void *fh, 988static int cx18_encoder_cmd(struct file *file, void *fh,
867 struct v4l2_encoder_cmd *enc) 989 struct v4l2_encoder_cmd *enc)
868{ 990{
@@ -1081,6 +1203,12 @@ static const struct v4l2_ioctl_ops cx18_ioctl_ops = {
1081 .vidioc_s_register = cx18_s_register, 1203 .vidioc_s_register = cx18_s_register,
1082#endif 1204#endif
1083 .vidioc_default = cx18_default, 1205 .vidioc_default = cx18_default,
1206 .vidioc_streamon = cx18_streamon,
1207 .vidioc_streamoff = cx18_streamoff,
1208 .vidioc_reqbufs = cx18_reqbufs,
1209 .vidioc_querybuf = cx18_querybuf,
1210 .vidioc_qbuf = cx18_qbuf,
1211 .vidioc_dqbuf = cx18_dqbuf,
1084}; 1212};
1085 1213
1086void cx18_set_funcs(struct video_device *vdev) 1214void cx18_set_funcs(struct video_device *vdev)
diff --git a/drivers/media/video/cx18/cx18-mailbox.c b/drivers/media/video/cx18/cx18-mailbox.c
index 9605d54bd08..c07191e09fc 100644
--- a/drivers/media/video/cx18/cx18-mailbox.c
+++ b/drivers/media/video/cx18/cx18-mailbox.c
@@ -81,6 +81,7 @@ static const struct cx18_api_info api_info[] = {
81 API_ENTRY(CPU, CX18_CPU_SET_SLICED_VBI_PARAM, 0), 81 API_ENTRY(CPU, CX18_CPU_SET_SLICED_VBI_PARAM, 0),
82 API_ENTRY(CPU, CX18_CPU_SET_USERDATA_PLACE_HOLDER, 0), 82 API_ENTRY(CPU, CX18_CPU_SET_USERDATA_PLACE_HOLDER, 0),
83 API_ENTRY(CPU, CX18_CPU_GET_ENC_PTS, 0), 83 API_ENTRY(CPU, CX18_CPU_GET_ENC_PTS, 0),
84 API_ENTRY(CPU, CX18_CPU_SET_VFC_PARAM, 0),
84 API_ENTRY(CPU, CX18_CPU_DE_SET_MDL_ACK, 0), 85 API_ENTRY(CPU, CX18_CPU_DE_SET_MDL_ACK, 0),
85 API_ENTRY(CPU, CX18_CPU_DE_SET_MDL, API_FAST), 86 API_ENTRY(CPU, CX18_CPU_DE_SET_MDL, API_FAST),
86 API_ENTRY(CPU, CX18_CPU_DE_RELEASE_MDL, API_SLOW), 87 API_ENTRY(CPU, CX18_CPU_DE_RELEASE_MDL, API_SLOW),
@@ -158,6 +159,60 @@ static void cx18_mdl_send_to_dvb(struct cx18_stream *s, struct cx18_mdl *mdl)
158 } 159 }
159} 160}
160 161
162static void cx18_mdl_send_to_videobuf(struct cx18_stream *s,
163 struct cx18_mdl *mdl)
164{
165 struct cx18_videobuf_buffer *vb_buf;
166 struct cx18_buffer *buf;
167 u8 *p;
168 u32 offset = 0;
169 int dispatch = 0;
170
171 if (mdl->bytesused == 0)
172 return;
173
174 /* Acquire a videobuf buffer, clone to and and release it */
175 spin_lock(&s->vb_lock);
176 if (list_empty(&s->vb_capture))
177 goto out;
178
179 vb_buf = list_first_entry(&s->vb_capture, struct cx18_videobuf_buffer,
180 vb.queue);
181
182 p = videobuf_to_vmalloc(&vb_buf->vb);
183 if (!p)
184 goto out;
185
186 offset = vb_buf->bytes_used;
187 list_for_each_entry(buf, &mdl->buf_list, list) {
188 if (buf->bytesused == 0)
189 break;
190
191 if ((offset + buf->bytesused) <= vb_buf->vb.bsize) {
192 memcpy(p + offset, buf->buf, buf->bytesused);
193 offset += buf->bytesused;
194 vb_buf->bytes_used += buf->bytesused;
195 }
196 }
197
198 /* If we've filled the buffer as per the callers res then dispatch it */
199 if (vb_buf->bytes_used >= (vb_buf->vb.width * vb_buf->vb.height * 2)) {
200 dispatch = 1;
201 vb_buf->bytes_used = 0;
202 }
203
204 if (dispatch) {
205 vb_buf->vb.ts = ktime_to_timeval(ktime_get());
206 list_del(&vb_buf->vb.queue);
207 vb_buf->vb.state = VIDEOBUF_DONE;
208 wake_up(&vb_buf->vb.done);
209 }
210
211 mod_timer(&s->vb_timeout, msecs_to_jiffies(2000) + jiffies);
212
213out:
214 spin_unlock(&s->vb_lock);
215}
161 216
162static void cx18_mdl_send_to_alsa(struct cx18 *cx, struct cx18_stream *s, 217static void cx18_mdl_send_to_alsa(struct cx18 *cx, struct cx18_stream *s,
163 struct cx18_mdl *mdl) 218 struct cx18_mdl *mdl)
@@ -263,6 +318,9 @@ static void epu_dma_done(struct cx18 *cx, struct cx18_in_work_order *order)
263 } else { 318 } else {
264 cx18_enqueue(s, mdl, &s->q_full); 319 cx18_enqueue(s, mdl, &s->q_full);
265 } 320 }
321 } else if (s->type == CX18_ENC_STREAM_TYPE_YUV) {
322 cx18_mdl_send_to_videobuf(s, mdl);
323 cx18_enqueue(s, mdl, &s->q_free);
266 } else { 324 } else {
267 cx18_enqueue(s, mdl, &s->q_full); 325 cx18_enqueue(s, mdl, &s->q_full);
268 if (s->type == CX18_ENC_STREAM_TYPE_IDX) 326 if (s->type == CX18_ENC_STREAM_TYPE_IDX)
diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c
index 6fbc356113c..852f420fd27 100644
--- a/drivers/media/video/cx18/cx18-streams.c
+++ b/drivers/media/video/cx18/cx18-streams.c
@@ -44,6 +44,7 @@ static struct v4l2_file_operations cx18_v4l2_enc_fops = {
44 .unlocked_ioctl = cx18_v4l2_ioctl, 44 .unlocked_ioctl = cx18_v4l2_ioctl,
45 .release = cx18_v4l2_close, 45 .release = cx18_v4l2_close,
46 .poll = cx18_v4l2_enc_poll, 46 .poll = cx18_v4l2_enc_poll,
47 .mmap = cx18_v4l2_mmap,
47}; 48};
48 49
49/* offset from 0 to register ts v4l2 minors on */ 50/* offset from 0 to register ts v4l2 minors on */
@@ -97,6 +98,141 @@ static struct {
97 }, 98 },
98}; 99};
99 100
101
102void cx18_dma_free(struct videobuf_queue *q,
103 struct cx18_stream *s, struct cx18_videobuf_buffer *buf)
104{
105 videobuf_waiton(q, &buf->vb, 0, 0);
106 videobuf_vmalloc_free(&buf->vb);
107 buf->vb.state = VIDEOBUF_NEEDS_INIT;
108}
109
110static int cx18_prepare_buffer(struct videobuf_queue *q,
111 struct cx18_stream *s,
112 struct cx18_videobuf_buffer *buf,
113 u32 pixelformat,
114 unsigned int width, unsigned int height,
115 enum v4l2_field field)
116{
117 struct cx18 *cx = s->cx;
118 int rc = 0;
119
120 /* check settings */
121 buf->bytes_used = 0;
122
123 if ((width < 48) || (height < 32))
124 return -EINVAL;
125
126 buf->vb.size = (width * height * 2);
127 if ((buf->vb.baddr != 0) && (buf->vb.bsize < buf->vb.size))
128 return -EINVAL;
129
130 /* alloc + fill struct (if changed) */
131 if (buf->vb.width != width || buf->vb.height != height ||
132 buf->vb.field != field || s->pixelformat != pixelformat ||
133 buf->tvnorm != cx->std) {
134
135 buf->vb.width = width;
136 buf->vb.height = height;
137 buf->vb.field = field;
138 buf->tvnorm = cx->std;
139 s->pixelformat = pixelformat;
140
141 cx18_dma_free(q, s, buf);
142 }
143
144 if ((buf->vb.baddr != 0) && (buf->vb.bsize < buf->vb.size))
145 return -EINVAL;
146
147 if (buf->vb.field == 0)
148 buf->vb.field = V4L2_FIELD_INTERLACED;
149
150 if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
151 buf->vb.width = width;
152 buf->vb.height = height;
153 buf->vb.field = field;
154 buf->tvnorm = cx->std;
155 s->pixelformat = pixelformat;
156
157 rc = videobuf_iolock(q, &buf->vb, NULL);
158 if (rc != 0)
159 goto fail;
160 }
161 buf->vb.state = VIDEOBUF_PREPARED;
162 return 0;
163
164fail:
165 cx18_dma_free(q, s, buf);
166 return rc;
167
168}
169
170/* VB_MIN_BUFSIZE is lcm(1440 * 480, 1440 * 576)
171 1440 is a single line of 4:2:2 YUV at 720 luma samples wide
172*/
173#define VB_MIN_BUFFERS 32
174#define VB_MIN_BUFSIZE 4147200
175
176static int buffer_setup(struct videobuf_queue *q,
177 unsigned int *count, unsigned int *size)
178{
179 struct cx18_stream *s = q->priv_data;
180 struct cx18 *cx = s->cx;
181
182 *size = 2 * cx->cxhdl.width * cx->cxhdl.height;
183 if (*count == 0)
184 *count = VB_MIN_BUFFERS;
185
186 while (*size * *count > VB_MIN_BUFFERS * VB_MIN_BUFSIZE)
187 (*count)--;
188
189 q->field = V4L2_FIELD_INTERLACED;
190 q->last = V4L2_FIELD_INTERLACED;
191
192 return 0;
193}
194
195static int buffer_prepare(struct videobuf_queue *q,
196 struct videobuf_buffer *vb,
197 enum v4l2_field field)
198{
199 struct cx18_videobuf_buffer *buf =
200 container_of(vb, struct cx18_videobuf_buffer, vb);
201 struct cx18_stream *s = q->priv_data;
202 struct cx18 *cx = s->cx;
203
204 return cx18_prepare_buffer(q, s, buf, s->pixelformat,
205 cx->cxhdl.width, cx->cxhdl.height, field);
206}
207
208static void buffer_release(struct videobuf_queue *q,
209 struct videobuf_buffer *vb)
210{
211 struct cx18_videobuf_buffer *buf =
212 container_of(vb, struct cx18_videobuf_buffer, vb);
213 struct cx18_stream *s = q->priv_data;
214
215 cx18_dma_free(q, s, buf);
216}
217
218static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
219{
220 struct cx18_videobuf_buffer *buf =
221 container_of(vb, struct cx18_videobuf_buffer, vb);
222 struct cx18_stream *s = q->priv_data;
223
224 buf->vb.state = VIDEOBUF_QUEUED;
225
226 list_add_tail(&buf->vb.queue, &s->vb_capture);
227}
228
229static struct videobuf_queue_ops cx18_videobuf_qops = {
230 .buf_setup = buffer_setup,
231 .buf_prepare = buffer_prepare,
232 .buf_queue = buffer_queue,
233 .buf_release = buffer_release,
234};
235
100static void cx18_stream_init(struct cx18 *cx, int type) 236static void cx18_stream_init(struct cx18 *cx, int type)
101{ 237{
102 struct cx18_stream *s = &cx->streams[type]; 238 struct cx18_stream *s = &cx->streams[type];
@@ -132,6 +268,26 @@ static void cx18_stream_init(struct cx18 *cx, int type)
132 cx18_queue_init(&s->q_idle); 268 cx18_queue_init(&s->q_idle);
133 269
134 INIT_WORK(&s->out_work_order, cx18_out_work_handler); 270 INIT_WORK(&s->out_work_order, cx18_out_work_handler);
271
272 INIT_LIST_HEAD(&s->vb_capture);
273 s->vb_timeout.function = cx18_vb_timeout;
274 s->vb_timeout.data = (unsigned long)s;
275 init_timer(&s->vb_timeout);
276 spin_lock_init(&s->vb_lock);
277 if (type == CX18_ENC_STREAM_TYPE_YUV) {
278 spin_lock_init(&s->vbuf_q_lock);
279
280 s->vb_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
281 videobuf_queue_vmalloc_init(&s->vbuf_q, &cx18_videobuf_qops,
282 &cx->pci_dev->dev, &s->vbuf_q_lock,
283 V4L2_BUF_TYPE_VIDEO_CAPTURE,
284 V4L2_FIELD_INTERLACED,
285 sizeof(struct cx18_videobuf_buffer),
286 s, &cx->serialize_lock);
287
288 /* Assume the previous pixel default */
289 s->pixelformat = V4L2_PIX_FMT_HM12;
290 }
135} 291}
136 292
137static int cx18_prep_dev(struct cx18 *cx, int type) 293static int cx18_prep_dev(struct cx18 *cx, int type)
@@ -372,6 +528,9 @@ void cx18_streams_cleanup(struct cx18 *cx, int unregister)
372 if (vdev == NULL) 528 if (vdev == NULL)
373 continue; 529 continue;
374 530
531 if (type == CX18_ENC_STREAM_TYPE_YUV)
532 videobuf_mmap_free(&cx->streams[type].vbuf_q);
533
375 cx18_stream_free(&cx->streams[type]); 534 cx18_stream_free(&cx->streams[type]);
376 535
377 /* Unregister or release device */ 536 /* Unregister or release device */
@@ -581,7 +740,10 @@ static void cx18_stream_configure_mdls(struct cx18_stream *s)
581 * Set the MDL size to the exact size needed for one frame. 740 * Set the MDL size to the exact size needed for one frame.
582 * Use enough buffers per MDL to cover the MDL size 741 * Use enough buffers per MDL to cover the MDL size
583 */ 742 */
584 s->mdl_size = 720 * s->cx->cxhdl.height * 3 / 2; 743 if (s->pixelformat == V4L2_PIX_FMT_HM12)
744 s->mdl_size = 720 * s->cx->cxhdl.height * 3 / 2;
745 else
746 s->mdl_size = 720 * s->cx->cxhdl.height * 2;
585 s->bufs_per_mdl = s->mdl_size / s->buf_size; 747 s->bufs_per_mdl = s->mdl_size / s->buf_size;
586 if (s->mdl_size % s->buf_size) 748 if (s->mdl_size % s->buf_size)
587 s->bufs_per_mdl++; 749 s->bufs_per_mdl++;
@@ -729,6 +891,19 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s)
729 test_bit(CX18_F_I_RADIO_USER, &cx->i_flags)) 891 test_bit(CX18_F_I_RADIO_USER, &cx->i_flags))
730 cx18_vapi(cx, CX18_CPU_SET_VIDEO_MUTE, 2, s->handle, 892 cx18_vapi(cx, CX18_CPU_SET_VIDEO_MUTE, 2, s->handle,
731 (v4l2_ctrl_g_ctrl(cx->cxhdl.video_mute_yuv) << 8) | 1); 893 (v4l2_ctrl_g_ctrl(cx->cxhdl.video_mute_yuv) << 8) | 1);
894
895 /* Enable the Video Format Converter for UYVY 4:2:2 support,
896 * rather than the default HM12 Macroblovk 4:2:0 support.
897 */
898 if (captype == CAPTURE_CHANNEL_TYPE_YUV) {
899 if (s->pixelformat == V4L2_PIX_FMT_UYVY)
900 cx18_vapi(cx, CX18_CPU_SET_VFC_PARAM, 2,
901 s->handle, 1);
902 else
903 /* If in doubt, default to HM12 */
904 cx18_vapi(cx, CX18_CPU_SET_VFC_PARAM, 2,
905 s->handle, 0);
906 }
732 } 907 }
733 908
734 if (atomic_read(&cx->tot_capturing) == 0) { 909 if (atomic_read(&cx->tot_capturing) == 0) {
diff --git a/drivers/media/video/cx18/cx18-version.h b/drivers/media/video/cx18/cx18-version.h
index 3e1aec4bcfd..cd189b6bbe2 100644
--- a/drivers/media/video/cx18/cx18-version.h
+++ b/drivers/media/video/cx18/cx18-version.h
@@ -24,7 +24,7 @@
24 24
25#define CX18_DRIVER_NAME "cx18" 25#define CX18_DRIVER_NAME "cx18"
26#define CX18_DRIVER_VERSION_MAJOR 1 26#define CX18_DRIVER_VERSION_MAJOR 1
27#define CX18_DRIVER_VERSION_MINOR 4 27#define CX18_DRIVER_VERSION_MINOR 5
28#define CX18_DRIVER_VERSION_PATCHLEVEL 0 28#define CX18_DRIVER_VERSION_PATCHLEVEL 0
29 29
30#define CX18_VERSION __stringify(CX18_DRIVER_VERSION_MAJOR) "." __stringify(CX18_DRIVER_VERSION_MINOR) "." __stringify(CX18_DRIVER_VERSION_PATCHLEVEL) 30#define CX18_VERSION __stringify(CX18_DRIVER_VERSION_MAJOR) "." __stringify(CX18_DRIVER_VERSION_MINOR) "." __stringify(CX18_DRIVER_VERSION_PATCHLEVEL)
diff --git a/drivers/media/video/cx18/cx23418.h b/drivers/media/video/cx18/cx23418.h
index 935f557acbd..767a8d23e3f 100644
--- a/drivers/media/video/cx18/cx23418.h
+++ b/drivers/media/video/cx18/cx23418.h
@@ -342,6 +342,12 @@
342 ReturnCode */ 342 ReturnCode */
343#define CX18_CPU_GET_ENC_PTS (CPU_CMD_MASK_CAPTURE | 0x0022) 343#define CX18_CPU_GET_ENC_PTS (CPU_CMD_MASK_CAPTURE | 0x0022)
344 344
345/* Description: Set VFC parameters
346 IN[0] - task handle
347 IN[1] - VFC enable flag, 1 - enable, 0 - disable
348*/
349#define CX18_CPU_SET_VFC_PARAM (CPU_CMD_MASK_CAPTURE | 0x0023)
350
345/* Below is the list of commands related to the data exchange */ 351/* Below is the list of commands related to the data exchange */
346#define CPU_CMD_MASK_DE (CPU_CMD_MASK | 0x040000) 352#define CPU_CMD_MASK_DE (CPU_CMD_MASK | 0x040000)
347 353