diff options
author | Hans Verkuil <hans.verkuil@cisco.com> | 2014-04-11 04:02:29 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <m.chehab@samsung.com> | 2014-04-16 17:54:30 -0400 |
commit | 5f26f2501b81190b60a0b72d611668fb6a59dd24 (patch) | |
tree | a46059b71f8e277b4fcef7c5e5a0d2b2ae148159 /Documentation/video4linux/v4l2-pci-skeleton.c | |
parent | b050b29e071a0b11262ad513700ab073f58c45b2 (diff) |
[media] v4l2-pci-skeleton.c: fix alternate field handling
For interlaced HDTV timings the correct field setting is FIELD_ALTERNATE,
not INTERLACED. Update this template driver accordingly:
- add check for the invalid combination of read() and FIELD_ALTERNATE.
- in the interrupt handler set v4l2_buffer field to alternating TOP and
BOTTOM.
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
Diffstat (limited to 'Documentation/video4linux/v4l2-pci-skeleton.c')
-rw-r--r-- | Documentation/video4linux/v4l2-pci-skeleton.c | 39 |
1 files changed, 28 insertions, 11 deletions
diff --git a/Documentation/video4linux/v4l2-pci-skeleton.c b/Documentation/video4linux/v4l2-pci-skeleton.c index 3a1c0d2dafce..80251dc2c6cf 100644 --- a/Documentation/video4linux/v4l2-pci-skeleton.c +++ b/Documentation/video4linux/v4l2-pci-skeleton.c | |||
@@ -77,7 +77,8 @@ struct skeleton { | |||
77 | 77 | ||
78 | spinlock_t qlock; | 78 | spinlock_t qlock; |
79 | struct list_head buf_list; | 79 | struct list_head buf_list; |
80 | unsigned int sequence; | 80 | unsigned field; |
81 | unsigned sequence; | ||
81 | }; | 82 | }; |
82 | 83 | ||
83 | struct skel_buffer { | 84 | struct skel_buffer { |
@@ -124,7 +125,7 @@ static const struct v4l2_dv_timings_cap skel_timings_cap = { | |||
124 | * Interrupt handler: typically interrupts happen after a new frame has been | 125 | * Interrupt handler: typically interrupts happen after a new frame has been |
125 | * captured. It is the job of the handler to remove the new frame from the | 126 | * captured. It is the job of the handler to remove the new frame from the |
126 | * internal list and give it back to the vb2 framework, updating the sequence | 127 | * internal list and give it back to the vb2 framework, updating the sequence |
127 | * counter and timestamp at the same time. | 128 | * counter, field and timestamp at the same time. |
128 | */ | 129 | */ |
129 | static irqreturn_t skeleton_irq(int irq, void *dev_id) | 130 | static irqreturn_t skeleton_irq(int irq, void *dev_id) |
130 | { | 131 | { |
@@ -139,8 +140,15 @@ static irqreturn_t skeleton_irq(int irq, void *dev_id) | |||
139 | spin_lock(&skel->qlock); | 140 | spin_lock(&skel->qlock); |
140 | list_del(&new_buf->list); | 141 | list_del(&new_buf->list); |
141 | spin_unlock(&skel->qlock); | 142 | spin_unlock(&skel->qlock); |
142 | new_buf->vb.v4l2_buf.sequence = skel->sequence++; | ||
143 | v4l2_get_timestamp(&new_buf->vb.v4l2_buf.timestamp); | 143 | v4l2_get_timestamp(&new_buf->vb.v4l2_buf.timestamp); |
144 | new_buf->vb.v4l2_buf.sequence = skel->sequence++; | ||
145 | new_buf->vb.v4l2_buf.field = skel->field; | ||
146 | if (skel->format.field == V4L2_FIELD_ALTERNATE) { | ||
147 | if (skel->field == V4L2_FIELD_BOTTOM) | ||
148 | skel->field = V4L2_FIELD_TOP; | ||
149 | else if (skel->field == V4L2_FIELD_TOP) | ||
150 | skel->field = V4L2_FIELD_BOTTOM; | ||
151 | } | ||
144 | vb2_buffer_done(&new_buf->vb, VB2_BUF_STATE_DONE); | 152 | vb2_buffer_done(&new_buf->vb, VB2_BUF_STATE_DONE); |
145 | } | 153 | } |
146 | #endif | 154 | #endif |
@@ -160,6 +168,17 @@ static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, | |||
160 | { | 168 | { |
161 | struct skeleton *skel = vb2_get_drv_priv(vq); | 169 | struct skeleton *skel = vb2_get_drv_priv(vq); |
162 | 170 | ||
171 | skel->field = skel->format.field; | ||
172 | if (skel->field == V4L2_FIELD_ALTERNATE) { | ||
173 | /* | ||
174 | * You cannot use read() with FIELD_ALTERNATE since the field | ||
175 | * information (TOP/BOTTOM) cannot be passed back to the user. | ||
176 | */ | ||
177 | if (vb2_fileio_is_active(q)) | ||
178 | return -EINVAL; | ||
179 | skel->field = V4L2_FIELD_TOP; | ||
180 | } | ||
181 | |||
163 | if (vq->num_buffers + *nbuffers < 3) | 182 | if (vq->num_buffers + *nbuffers < 3) |
164 | *nbuffers = 3 - vq->num_buffers; | 183 | *nbuffers = 3 - vq->num_buffers; |
165 | 184 | ||
@@ -173,10 +192,7 @@ static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, | |||
173 | 192 | ||
174 | /* | 193 | /* |
175 | * Prepare the buffer for queueing to the DMA engine: check and set the | 194 | * Prepare the buffer for queueing to the DMA engine: check and set the |
176 | * payload size and fill in the field. Note: if the format's field is | 195 | * payload size. |
177 | * V4L2_FIELD_ALTERNATE, then vb->v4l2_buf.field should be set in the | ||
178 | * interrupt handler since that's usually where you know if the TOP or | ||
179 | * BOTTOM field has been captured. | ||
180 | */ | 196 | */ |
181 | static int buffer_prepare(struct vb2_buffer *vb) | 197 | static int buffer_prepare(struct vb2_buffer *vb) |
182 | { | 198 | { |
@@ -190,7 +206,6 @@ static int buffer_prepare(struct vb2_buffer *vb) | |||
190 | } | 206 | } |
191 | 207 | ||
192 | vb2_set_plane_payload(vb, 0, size); | 208 | vb2_set_plane_payload(vb, 0, size); |
193 | vb->v4l2_buf.field = skel->format.field; | ||
194 | return 0; | 209 | return 0; |
195 | } | 210 | } |
196 | 211 | ||
@@ -319,10 +334,12 @@ static void skeleton_fill_pix_format(struct skeleton *skel, | |||
319 | /* HDMI input */ | 334 | /* HDMI input */ |
320 | pix->width = skel->timings.bt.width; | 335 | pix->width = skel->timings.bt.width; |
321 | pix->height = skel->timings.bt.height; | 336 | pix->height = skel->timings.bt.height; |
322 | if (skel->timings.bt.interlaced) | 337 | if (skel->timings.bt.interlaced) { |
323 | pix->field = V4L2_FIELD_INTERLACED; | 338 | pix->field = V4L2_FIELD_ALTERNATE; |
324 | else | 339 | pix->height /= 2; |
340 | } else { | ||
325 | pix->field = V4L2_FIELD_NONE; | 341 | pix->field = V4L2_FIELD_NONE; |
342 | } | ||
326 | pix->colorspace = V4L2_COLORSPACE_REC709; | 343 | pix->colorspace = V4L2_COLORSPACE_REC709; |
327 | } | 344 | } |
328 | 345 | ||