diff options
author | Lad, Prabhakar <prabhakar.lad@ti.com> | 2012-06-28 08:28:36 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-07-30 18:06:33 -0400 |
commit | 2401dd25c70c07dcec8d7b5497cec4a7e74d2e31 (patch) | |
tree | 87852356fbd31c10f6ad1b1ff2d4f0dd1cbe38b2 /drivers/media/video/davinci/vpif_display.c | |
parent | 60aa38d87d7d50a89e43b77559307a95a42bf07e (diff) |
[media] davinci: vpif display: migrate driver to videobuf2
This patch migrates VPIF display driver to videobuf2 framework.
Signed-off-by: Lad, Prabhakar <prabhakar.lad@ti.com>
Signed-off-by: Manjunath Hadli <manjunath.hadli@ti.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/davinci/vpif_display.c')
-rw-r--r-- | drivers/media/video/davinci/vpif_display.c | 576 |
1 files changed, 269 insertions, 307 deletions
diff --git a/drivers/media/video/davinci/vpif_display.c b/drivers/media/video/davinci/vpif_display.c index e0070cd6f41e..787245923a20 100644 --- a/drivers/media/video/davinci/vpif_display.c +++ b/drivers/media/video/davinci/vpif_display.c | |||
@@ -82,89 +82,38 @@ static struct vpif_config_params config_params = { | |||
82 | 82 | ||
83 | static struct vpif_device vpif_obj = { {NULL} }; | 83 | static struct vpif_device vpif_obj = { {NULL} }; |
84 | static struct device *vpif_dev; | 84 | static struct device *vpif_dev; |
85 | static void vpif_calculate_offsets(struct channel_obj *ch); | ||
86 | static void vpif_config_addr(struct channel_obj *ch, int muxmode); | ||
85 | 87 | ||
86 | /* | 88 | /* |
87 | * vpif_uservirt_to_phys: This function is used to convert user | 89 | * buffer_prepare: This is the callback function called from vb2_qbuf() |
88 | * space virtual address to physical address. | ||
89 | */ | ||
90 | static u32 vpif_uservirt_to_phys(u32 virtp) | ||
91 | { | ||
92 | struct mm_struct *mm = current->mm; | ||
93 | unsigned long physp = 0; | ||
94 | struct vm_area_struct *vma; | ||
95 | |||
96 | vma = find_vma(mm, virtp); | ||
97 | |||
98 | /* For kernel direct-mapped memory, take the easy way */ | ||
99 | if (virtp >= PAGE_OFFSET) { | ||
100 | physp = virt_to_phys((void *)virtp); | ||
101 | } else if (vma && (vma->vm_flags & VM_IO) && (vma->vm_pgoff)) { | ||
102 | /* this will catch, kernel-allocated, mmaped-to-usermode addr */ | ||
103 | physp = (vma->vm_pgoff << PAGE_SHIFT) + (virtp - vma->vm_start); | ||
104 | } else { | ||
105 | /* otherwise, use get_user_pages() for general userland pages */ | ||
106 | int res, nr_pages = 1; | ||
107 | struct page *pages; | ||
108 | down_read(¤t->mm->mmap_sem); | ||
109 | |||
110 | res = get_user_pages(current, current->mm, | ||
111 | virtp, nr_pages, 1, 0, &pages, NULL); | ||
112 | up_read(¤t->mm->mmap_sem); | ||
113 | |||
114 | if (res == nr_pages) { | ||
115 | physp = __pa(page_address(&pages[0]) + | ||
116 | (virtp & ~PAGE_MASK)); | ||
117 | } else { | ||
118 | vpif_err("get_user_pages failed\n"); | ||
119 | return 0; | ||
120 | } | ||
121 | } | ||
122 | |||
123 | return physp; | ||
124 | } | ||
125 | |||
126 | /* | ||
127 | * buffer_prepare: This is the callback function called from videobuf_qbuf() | ||
128 | * function the buffer is prepared and user space virtual address is converted | 90 | * function the buffer is prepared and user space virtual address is converted |
129 | * into physical address | 91 | * into physical address |
130 | */ | 92 | */ |
131 | static int vpif_buffer_prepare(struct videobuf_queue *q, | 93 | static int vpif_buffer_prepare(struct vb2_buffer *vb) |
132 | struct videobuf_buffer *vb, | ||
133 | enum v4l2_field field) | ||
134 | { | 94 | { |
135 | struct vpif_fh *fh = q->priv_data; | 95 | struct vpif_fh *fh = vb2_get_drv_priv(vb->vb2_queue); |
96 | struct vb2_queue *q = vb->vb2_queue; | ||
136 | struct common_obj *common; | 97 | struct common_obj *common; |
137 | unsigned long addr; | 98 | unsigned long addr; |
138 | 99 | ||
139 | common = &fh->channel->common[VPIF_VIDEO_INDEX]; | 100 | common = &fh->channel->common[VPIF_VIDEO_INDEX]; |
140 | if (VIDEOBUF_NEEDS_INIT == vb->state) { | 101 | if (vb->state != VB2_BUF_STATE_ACTIVE && |
141 | vb->width = common->width; | 102 | vb->state != VB2_BUF_STATE_PREPARED) { |
142 | vb->height = common->height; | 103 | vb2_set_plane_payload(vb, 0, common->fmt.fmt.pix.sizeimage); |
143 | vb->size = vb->width * vb->height; | 104 | if (vb2_plane_vaddr(vb, 0) && |
144 | vb->field = field; | 105 | vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0)) |
145 | } | ||
146 | vb->state = VIDEOBUF_PREPARED; | ||
147 | |||
148 | /* if user pointer memory mechanism is used, get the physical | ||
149 | * address of the buffer */ | ||
150 | if (V4L2_MEMORY_USERPTR == common->memory) { | ||
151 | if (!vb->baddr) { | ||
152 | vpif_err("buffer_address is 0\n"); | ||
153 | return -EINVAL; | ||
154 | } | ||
155 | |||
156 | vb->boff = vpif_uservirt_to_phys(vb->baddr); | ||
157 | if (!ISALIGNED(vb->boff)) | ||
158 | goto buf_align_exit; | 106 | goto buf_align_exit; |
159 | } | ||
160 | 107 | ||
161 | addr = vb->boff; | 108 | addr = vb2_dma_contig_plane_dma_addr(vb, 0); |
162 | if (q->streaming && (V4L2_BUF_TYPE_SLICED_VBI_OUTPUT != q->type)) { | 109 | if (q->streaming && |
163 | if (!ISALIGNED(addr + common->ytop_off) || | 110 | (V4L2_BUF_TYPE_SLICED_VBI_OUTPUT != q->type)) { |
164 | !ISALIGNED(addr + common->ybtm_off) || | 111 | if (!ISALIGNED(addr + common->ytop_off) || |
165 | !ISALIGNED(addr + common->ctop_off) || | 112 | !ISALIGNED(addr + common->ybtm_off) || |
166 | !ISALIGNED(addr + common->cbtm_off)) | 113 | !ISALIGNED(addr + common->ctop_off) || |
167 | goto buf_align_exit; | 114 | !ISALIGNED(addr + common->cbtm_off)) |
115 | goto buf_align_exit; | ||
116 | } | ||
168 | } | 117 | } |
169 | return 0; | 118 | return 0; |
170 | 119 | ||
@@ -174,104 +123,251 @@ buf_align_exit: | |||
174 | } | 123 | } |
175 | 124 | ||
176 | /* | 125 | /* |
177 | * vpif_buffer_setup: This function allocates memory for the buffers | 126 | * vpif_buffer_queue_setup: This function allocates memory for the buffers |
178 | */ | 127 | */ |
179 | static int vpif_buffer_setup(struct videobuf_queue *q, unsigned int *count, | 128 | static int vpif_buffer_queue_setup(struct vb2_queue *vq, |
180 | unsigned int *size) | 129 | const struct v4l2_format *fmt, |
130 | unsigned int *nbuffers, unsigned int *nplanes, | ||
131 | unsigned int sizes[], void *alloc_ctxs[]) | ||
181 | { | 132 | { |
182 | struct vpif_fh *fh = q->priv_data; | 133 | struct vpif_fh *fh = vb2_get_drv_priv(vq); |
183 | struct channel_obj *ch = fh->channel; | 134 | struct channel_obj *ch = fh->channel; |
184 | struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; | 135 | struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; |
185 | 136 | unsigned long size; | |
186 | if (V4L2_MEMORY_MMAP != common->memory) | 137 | |
187 | return 0; | 138 | if (V4L2_MEMORY_MMAP == common->memory) { |
188 | 139 | size = config_params.channel_bufsize[ch->channel_id]; | |
189 | *size = config_params.channel_bufsize[ch->channel_id]; | 140 | /* |
190 | 141 | * Checking if the buffer size exceeds the available buffer | |
191 | /* | 142 | * ycmux_mode = 0 means 1 channel mode HD and |
192 | * Checking if the buffer size exceeds the available buffer | 143 | * ycmux_mode = 1 means 2 channels mode SD |
193 | * ycmux_mode = 0 means 1 channel mode HD and | 144 | */ |
194 | * ycmux_mode = 1 means 2 channels mode SD | 145 | if (ch->vpifparams.std_info.ycmux_mode == 0) { |
195 | */ | 146 | if (config_params.video_limit[ch->channel_id]) |
196 | if (ch->vpifparams.std_info.ycmux_mode == 0) { | 147 | while (size * *nbuffers > |
197 | if (config_params.video_limit[ch->channel_id]) | 148 | (config_params.video_limit[0] |
198 | while (*size * *count > (config_params.video_limit[0] | 149 | + config_params.video_limit[1])) |
199 | + config_params.video_limit[1])) | 150 | (*nbuffers)--; |
200 | (*count)--; | 151 | } else { |
201 | } else { | 152 | if (config_params.video_limit[ch->channel_id]) |
202 | if (config_params.video_limit[ch->channel_id]) | 153 | while (size * *nbuffers > |
203 | while (*size * *count > | ||
204 | config_params.video_limit[ch->channel_id]) | 154 | config_params.video_limit[ch->channel_id]) |
205 | (*count)--; | 155 | (*nbuffers)--; |
156 | } | ||
157 | } else { | ||
158 | size = common->fmt.fmt.pix.sizeimage; | ||
206 | } | 159 | } |
207 | 160 | ||
208 | if (*count < config_params.min_numbuffers) | 161 | if (*nbuffers < config_params.min_numbuffers) |
209 | *count = config_params.min_numbuffers; | 162 | *nbuffers = config_params.min_numbuffers; |
210 | 163 | ||
164 | *nplanes = 1; | ||
165 | sizes[0] = size; | ||
166 | alloc_ctxs[0] = common->alloc_ctx; | ||
211 | return 0; | 167 | return 0; |
212 | } | 168 | } |
213 | 169 | ||
214 | /* | 170 | /* |
215 | * vpif_buffer_queue: This function adds the buffer to DMA queue | 171 | * vpif_buffer_queue: This function adds the buffer to DMA queue |
216 | */ | 172 | */ |
217 | static void vpif_buffer_queue(struct videobuf_queue *q, | 173 | static void vpif_buffer_queue(struct vb2_buffer *vb) |
218 | struct videobuf_buffer *vb) | ||
219 | { | 174 | { |
220 | struct vpif_fh *fh = q->priv_data; | 175 | struct vpif_fh *fh = vb2_get_drv_priv(vb->vb2_queue); |
176 | struct vpif_disp_buffer *buf = container_of(vb, | ||
177 | struct vpif_disp_buffer, vb); | ||
178 | struct channel_obj *ch = fh->channel; | ||
221 | struct common_obj *common; | 179 | struct common_obj *common; |
222 | 180 | ||
223 | common = &fh->channel->common[VPIF_VIDEO_INDEX]; | 181 | common = &ch->common[VPIF_VIDEO_INDEX]; |
224 | 182 | ||
225 | /* add the buffer to the DMA queue */ | 183 | /* add the buffer to the DMA queue */ |
226 | list_add_tail(&vb->queue, &common->dma_queue); | 184 | list_add_tail(&buf->list, &common->dma_queue); |
227 | vb->state = VIDEOBUF_QUEUED; | ||
228 | } | 185 | } |
229 | 186 | ||
230 | /* | 187 | /* |
231 | * vpif_buffer_release: This function is called from the videobuf layer to | 188 | * vpif_buf_cleanup: This function is called from the videobuf2 layer to |
232 | * free memory allocated to the buffers | 189 | * free memory allocated to the buffers |
233 | */ | 190 | */ |
234 | static void vpif_buffer_release(struct videobuf_queue *q, | 191 | static void vpif_buf_cleanup(struct vb2_buffer *vb) |
235 | struct videobuf_buffer *vb) | ||
236 | { | 192 | { |
237 | struct vpif_fh *fh = q->priv_data; | 193 | struct vpif_fh *fh = vb2_get_drv_priv(vb->vb2_queue); |
194 | struct vpif_disp_buffer *buf = container_of(vb, | ||
195 | struct vpif_disp_buffer, vb); | ||
238 | struct channel_obj *ch = fh->channel; | 196 | struct channel_obj *ch = fh->channel; |
239 | struct common_obj *common; | 197 | struct common_obj *common; |
240 | unsigned int buf_size = 0; | 198 | unsigned long flags; |
241 | 199 | ||
242 | common = &ch->common[VPIF_VIDEO_INDEX]; | 200 | common = &ch->common[VPIF_VIDEO_INDEX]; |
243 | 201 | ||
244 | videobuf_dma_contig_free(q, vb); | 202 | spin_lock_irqsave(&common->irqlock, flags); |
245 | vb->state = VIDEOBUF_NEEDS_INIT; | 203 | if (vb->state == VB2_BUF_STATE_ACTIVE) |
204 | list_del_init(&buf->list); | ||
205 | spin_unlock_irqrestore(&common->irqlock, flags); | ||
206 | } | ||
207 | |||
208 | static void vpif_wait_prepare(struct vb2_queue *vq) | ||
209 | { | ||
210 | struct vpif_fh *fh = vb2_get_drv_priv(vq); | ||
211 | struct channel_obj *ch = fh->channel; | ||
212 | struct common_obj *common; | ||
213 | |||
214 | common = &ch->common[VPIF_VIDEO_INDEX]; | ||
215 | mutex_unlock(&common->lock); | ||
216 | } | ||
246 | 217 | ||
247 | if (V4L2_MEMORY_MMAP != common->memory) | 218 | static void vpif_wait_finish(struct vb2_queue *vq) |
248 | return; | 219 | { |
220 | struct vpif_fh *fh = vb2_get_drv_priv(vq); | ||
221 | struct channel_obj *ch = fh->channel; | ||
222 | struct common_obj *common; | ||
249 | 223 | ||
250 | buf_size = config_params.channel_bufsize[ch->channel_id]; | 224 | common = &ch->common[VPIF_VIDEO_INDEX]; |
225 | mutex_lock(&common->lock); | ||
226 | } | ||
227 | |||
228 | static int vpif_buffer_init(struct vb2_buffer *vb) | ||
229 | { | ||
230 | struct vpif_disp_buffer *buf = container_of(vb, | ||
231 | struct vpif_disp_buffer, vb); | ||
232 | |||
233 | INIT_LIST_HEAD(&buf->list); | ||
234 | |||
235 | return 0; | ||
251 | } | 236 | } |
252 | 237 | ||
253 | static struct videobuf_queue_ops video_qops = { | ||
254 | .buf_setup = vpif_buffer_setup, | ||
255 | .buf_prepare = vpif_buffer_prepare, | ||
256 | .buf_queue = vpif_buffer_queue, | ||
257 | .buf_release = vpif_buffer_release, | ||
258 | }; | ||
259 | static u8 channel_first_int[VPIF_NUMOBJECTS][2] = { {1, 1} }; | 238 | static u8 channel_first_int[VPIF_NUMOBJECTS][2] = { {1, 1} }; |
260 | 239 | ||
240 | static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count) | ||
241 | { | ||
242 | struct vpif_display_config *vpif_config_data = | ||
243 | vpif_dev->platform_data; | ||
244 | struct vpif_fh *fh = vb2_get_drv_priv(vq); | ||
245 | struct channel_obj *ch = fh->channel; | ||
246 | struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; | ||
247 | struct vpif_params *vpif = &ch->vpifparams; | ||
248 | unsigned long addr = 0; | ||
249 | int ret; | ||
250 | |||
251 | /* If buffer queue is empty, return error */ | ||
252 | if (list_empty(&common->dma_queue)) { | ||
253 | vpif_err("buffer queue is empty\n"); | ||
254 | return -EIO; | ||
255 | } | ||
256 | |||
257 | /* Get the next frame from the buffer queue */ | ||
258 | common->next_frm = common->cur_frm = | ||
259 | list_entry(common->dma_queue.next, | ||
260 | struct vpif_disp_buffer, list); | ||
261 | |||
262 | list_del(&common->cur_frm->list); | ||
263 | /* Mark state of the current frame to active */ | ||
264 | common->cur_frm->vb.state = VB2_BUF_STATE_ACTIVE; | ||
265 | |||
266 | /* Initialize field_id and started member */ | ||
267 | ch->field_id = 0; | ||
268 | common->started = 1; | ||
269 | addr = vb2_dma_contig_plane_dma_addr(&common->cur_frm->vb, 0); | ||
270 | /* Calculate the offset for Y and C data in the buffer */ | ||
271 | vpif_calculate_offsets(ch); | ||
272 | |||
273 | if ((ch->vpifparams.std_info.frm_fmt && | ||
274 | ((common->fmt.fmt.pix.field != V4L2_FIELD_NONE) | ||
275 | && (common->fmt.fmt.pix.field != V4L2_FIELD_ANY))) | ||
276 | || (!ch->vpifparams.std_info.frm_fmt | ||
277 | && (common->fmt.fmt.pix.field == V4L2_FIELD_NONE))) { | ||
278 | vpif_err("conflict in field format and std format\n"); | ||
279 | return -EINVAL; | ||
280 | } | ||
281 | |||
282 | /* clock settings */ | ||
283 | ret = | ||
284 | vpif_config_data->set_clock(ch->vpifparams.std_info.ycmux_mode, | ||
285 | ch->vpifparams.std_info.hd_sd); | ||
286 | if (ret < 0) { | ||
287 | vpif_err("can't set clock\n"); | ||
288 | return ret; | ||
289 | } | ||
290 | |||
291 | /* set the parameters and addresses */ | ||
292 | ret = vpif_set_video_params(vpif, ch->channel_id + 2); | ||
293 | if (ret < 0) | ||
294 | return ret; | ||
295 | |||
296 | common->started = ret; | ||
297 | vpif_config_addr(ch, ret); | ||
298 | common->set_addr((addr + common->ytop_off), | ||
299 | (addr + common->ybtm_off), | ||
300 | (addr + common->ctop_off), | ||
301 | (addr + common->cbtm_off)); | ||
302 | |||
303 | /* Set interrupt for both the fields in VPIF | ||
304 | Register enable channel in VPIF register */ | ||
305 | if (VPIF_CHANNEL2_VIDEO == ch->channel_id) { | ||
306 | channel2_intr_assert(); | ||
307 | channel2_intr_enable(1); | ||
308 | enable_channel2(1); | ||
309 | } | ||
310 | |||
311 | if ((VPIF_CHANNEL3_VIDEO == ch->channel_id) | ||
312 | || (common->started == 2)) { | ||
313 | channel3_intr_assert(); | ||
314 | channel3_intr_enable(1); | ||
315 | enable_channel3(1); | ||
316 | } | ||
317 | channel_first_int[VPIF_VIDEO_INDEX][ch->channel_id] = 1; | ||
318 | |||
319 | return 0; | ||
320 | } | ||
321 | |||
322 | /* abort streaming and wait for last buffer */ | ||
323 | static int vpif_stop_streaming(struct vb2_queue *vq) | ||
324 | { | ||
325 | struct vpif_fh *fh = vb2_get_drv_priv(vq); | ||
326 | struct channel_obj *ch = fh->channel; | ||
327 | struct common_obj *common; | ||
328 | |||
329 | if (!vb2_is_streaming(vq)) | ||
330 | return 0; | ||
331 | |||
332 | common = &ch->common[VPIF_VIDEO_INDEX]; | ||
333 | |||
334 | /* release all active buffers */ | ||
335 | while (!list_empty(&common->dma_queue)) { | ||
336 | common->next_frm = list_entry(common->dma_queue.next, | ||
337 | struct vpif_disp_buffer, list); | ||
338 | list_del(&common->next_frm->list); | ||
339 | vb2_buffer_done(&common->next_frm->vb, VB2_BUF_STATE_ERROR); | ||
340 | } | ||
341 | |||
342 | return 0; | ||
343 | } | ||
344 | |||
345 | static struct vb2_ops video_qops = { | ||
346 | .queue_setup = vpif_buffer_queue_setup, | ||
347 | .wait_prepare = vpif_wait_prepare, | ||
348 | .wait_finish = vpif_wait_finish, | ||
349 | .buf_init = vpif_buffer_init, | ||
350 | .buf_prepare = vpif_buffer_prepare, | ||
351 | .start_streaming = vpif_start_streaming, | ||
352 | .stop_streaming = vpif_stop_streaming, | ||
353 | .buf_cleanup = vpif_buf_cleanup, | ||
354 | .buf_queue = vpif_buffer_queue, | ||
355 | }; | ||
356 | |||
261 | static void process_progressive_mode(struct common_obj *common) | 357 | static void process_progressive_mode(struct common_obj *common) |
262 | { | 358 | { |
263 | unsigned long addr = 0; | 359 | unsigned long addr = 0; |
264 | 360 | ||
265 | /* Get the next buffer from buffer queue */ | 361 | /* Get the next buffer from buffer queue */ |
266 | common->next_frm = list_entry(common->dma_queue.next, | 362 | common->next_frm = list_entry(common->dma_queue.next, |
267 | struct videobuf_buffer, queue); | 363 | struct vpif_disp_buffer, list); |
268 | /* Remove that buffer from the buffer queue */ | 364 | /* Remove that buffer from the buffer queue */ |
269 | list_del(&common->next_frm->queue); | 365 | list_del(&common->next_frm->list); |
270 | /* Mark status of the buffer as active */ | 366 | /* Mark status of the buffer as active */ |
271 | common->next_frm->state = VIDEOBUF_ACTIVE; | 367 | common->next_frm->vb.state = VB2_BUF_STATE_ACTIVE; |
272 | 368 | ||
273 | /* Set top and bottom field addrs in VPIF registers */ | 369 | /* Set top and bottom field addrs in VPIF registers */ |
274 | addr = videobuf_to_dma_contig(common->next_frm); | 370 | addr = vb2_dma_contig_plane_dma_addr(&common->next_frm->vb, 0); |
275 | common->set_addr(addr + common->ytop_off, | 371 | common->set_addr(addr + common->ytop_off, |
276 | addr + common->ybtm_off, | 372 | addr + common->ybtm_off, |
277 | addr + common->ctop_off, | 373 | addr + common->ctop_off, |
@@ -289,11 +385,10 @@ static void process_interlaced_mode(int fid, struct common_obj *common) | |||
289 | /* one frame is displayed If next frame is | 385 | /* one frame is displayed If next frame is |
290 | * available, release cur_frm and move on */ | 386 | * available, release cur_frm and move on */ |
291 | /* Copy frame display time */ | 387 | /* Copy frame display time */ |
292 | do_gettimeofday(&common->cur_frm->ts); | 388 | do_gettimeofday(&common->cur_frm->vb.v4l2_buf.timestamp); |
293 | /* Change status of the cur_frm */ | 389 | /* Change status of the cur_frm */ |
294 | common->cur_frm->state = VIDEOBUF_DONE; | 390 | vb2_buffer_done(&common->cur_frm->vb, |
295 | /* unlock semaphore on cur_frm */ | 391 | VB2_BUF_STATE_DONE); |
296 | wake_up_interruptible(&common->cur_frm->done); | ||
297 | /* Make cur_frm pointing to next_frm */ | 392 | /* Make cur_frm pointing to next_frm */ |
298 | common->cur_frm = common->next_frm; | 393 | common->cur_frm = common->next_frm; |
299 | 394 | ||
@@ -344,9 +439,10 @@ static irqreturn_t vpif_channel_isr(int irq, void *dev_id) | |||
344 | if (!channel_first_int[i][channel_id]) { | 439 | if (!channel_first_int[i][channel_id]) { |
345 | /* Mark status of the cur_frm to | 440 | /* Mark status of the cur_frm to |
346 | * done and unlock semaphore on it */ | 441 | * done and unlock semaphore on it */ |
347 | do_gettimeofday(&common->cur_frm->ts); | 442 | do_gettimeofday(&common->cur_frm->vb. |
348 | common->cur_frm->state = VIDEOBUF_DONE; | 443 | v4l2_buf.timestamp); |
349 | wake_up_interruptible(&common->cur_frm->done); | 444 | vb2_buffer_done(&common->cur_frm->vb, |
445 | VB2_BUF_STATE_DONE); | ||
350 | /* Make cur_frm pointing to next_frm */ | 446 | /* Make cur_frm pointing to next_frm */ |
351 | common->cur_frm = common->next_frm; | 447 | common->cur_frm = common->next_frm; |
352 | } | 448 | } |
@@ -464,10 +560,7 @@ static void vpif_calculate_offsets(struct channel_obj *ch) | |||
464 | vid_ch->buf_field = common->fmt.fmt.pix.field; | 560 | vid_ch->buf_field = common->fmt.fmt.pix.field; |
465 | } | 561 | } |
466 | 562 | ||
467 | if (V4L2_MEMORY_USERPTR == common->memory) | 563 | sizeimage = common->fmt.fmt.pix.sizeimage; |
468 | sizeimage = common->fmt.fmt.pix.sizeimage; | ||
469 | else | ||
470 | sizeimage = config_params.channel_bufsize[ch->channel_id]; | ||
471 | 564 | ||
472 | hpitch = common->fmt.fmt.pix.bytesperline; | 565 | hpitch = common->fmt.fmt.pix.bytesperline; |
473 | vpitch = sizeimage / (hpitch * 2); | 566 | vpitch = sizeimage / (hpitch * 2); |
@@ -544,10 +637,7 @@ static int vpif_check_format(struct channel_obj *ch, | |||
544 | if (pixfmt->bytesperline <= 0) | 637 | if (pixfmt->bytesperline <= 0) |
545 | goto invalid_pitch_exit; | 638 | goto invalid_pitch_exit; |
546 | 639 | ||
547 | if (V4L2_MEMORY_USERPTR == common->memory) | 640 | sizeimage = pixfmt->sizeimage; |
548 | sizeimage = pixfmt->sizeimage; | ||
549 | else | ||
550 | sizeimage = config_params.channel_bufsize[ch->channel_id]; | ||
551 | 641 | ||
552 | if (vpif_update_resolution(ch)) | 642 | if (vpif_update_resolution(ch)) |
553 | return -EINVAL; | 643 | return -EINVAL; |
@@ -604,7 +694,7 @@ static int vpif_mmap(struct file *filep, struct vm_area_struct *vma) | |||
604 | 694 | ||
605 | vpif_dbg(2, debug, "vpif_mmap\n"); | 695 | vpif_dbg(2, debug, "vpif_mmap\n"); |
606 | 696 | ||
607 | return videobuf_mmap_mapper(&common->buffer_queue, vma); | 697 | return vb2_mmap(&common->buffer_queue, vma); |
608 | } | 698 | } |
609 | 699 | ||
610 | /* | 700 | /* |
@@ -617,7 +707,7 @@ static unsigned int vpif_poll(struct file *filep, poll_table *wait) | |||
617 | struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; | 707 | struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; |
618 | 708 | ||
619 | if (common->started) | 709 | if (common->started) |
620 | return videobuf_poll_stream(filep, &common->buffer_queue, wait); | 710 | return vb2_poll(&common->buffer_queue, filep, wait); |
621 | 711 | ||
622 | return 0; | 712 | return 0; |
623 | } | 713 | } |
@@ -686,9 +776,11 @@ static int vpif_release(struct file *filep) | |||
686 | channel3_intr_enable(0); | 776 | channel3_intr_enable(0); |
687 | } | 777 | } |
688 | common->started = 0; | 778 | common->started = 0; |
779 | |||
689 | /* Free buffers allocated */ | 780 | /* Free buffers allocated */ |
690 | videobuf_queue_cancel(&common->buffer_queue); | 781 | vb2_queue_release(&common->buffer_queue); |
691 | videobuf_mmap_free(&common->buffer_queue); | 782 | vb2_dma_contig_cleanup_ctx(common->alloc_ctx); |
783 | |||
692 | common->numbuffers = | 784 | common->numbuffers = |
693 | config_params.numbuffers[ch->channel_id]; | 785 | config_params.numbuffers[ch->channel_id]; |
694 | } | 786 | } |
@@ -827,6 +919,7 @@ static int vpif_reqbufs(struct file *file, void *priv, | |||
827 | struct channel_obj *ch = fh->channel; | 919 | struct channel_obj *ch = fh->channel; |
828 | struct common_obj *common; | 920 | struct common_obj *common; |
829 | enum v4l2_field field; | 921 | enum v4l2_field field; |
922 | struct vb2_queue *q; | ||
830 | u8 index = 0; | 923 | u8 index = 0; |
831 | 924 | ||
832 | /* This file handle has not initialized the channel, | 925 | /* This file handle has not initialized the channel, |
@@ -848,7 +941,6 @@ static int vpif_reqbufs(struct file *file, void *priv, | |||
848 | 941 | ||
849 | if (common->fmt.type != reqbuf->type || !vpif_dev) | 942 | if (common->fmt.type != reqbuf->type || !vpif_dev) |
850 | return -EINVAL; | 943 | return -EINVAL; |
851 | |||
852 | if (0 != common->io_usrs) | 944 | if (0 != common->io_usrs) |
853 | return -EBUSY; | 945 | return -EBUSY; |
854 | 946 | ||
@@ -860,14 +952,21 @@ static int vpif_reqbufs(struct file *file, void *priv, | |||
860 | } else { | 952 | } else { |
861 | field = V4L2_VBI_INTERLACED; | 953 | field = V4L2_VBI_INTERLACED; |
862 | } | 954 | } |
955 | /* Initialize videobuf2 queue as per the buffer type */ | ||
956 | common->alloc_ctx = vb2_dma_contig_init_ctx(vpif_dev); | ||
957 | if (!common->alloc_ctx) { | ||
958 | vpif_err("Failed to get the context\n"); | ||
959 | return -EINVAL; | ||
960 | } | ||
961 | q = &common->buffer_queue; | ||
962 | q->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; | ||
963 | q->io_modes = VB2_MMAP | VB2_USERPTR; | ||
964 | q->drv_priv = fh; | ||
965 | q->ops = &video_qops; | ||
966 | q->mem_ops = &vb2_dma_contig_memops; | ||
967 | q->buf_struct_size = sizeof(struct vpif_disp_buffer); | ||
863 | 968 | ||
864 | /* Initialize videobuf queue as per the buffer type */ | 969 | vb2_queue_init(q); |
865 | videobuf_queue_dma_contig_init(&common->buffer_queue, | ||
866 | &video_qops, vpif_dev, | ||
867 | &common->irqlock, | ||
868 | reqbuf->type, field, | ||
869 | sizeof(struct videobuf_buffer), fh, | ||
870 | &common->lock); | ||
871 | 970 | ||
872 | /* Set io allowed member of file handle to TRUE */ | 971 | /* Set io allowed member of file handle to TRUE */ |
873 | fh->io_allowed[index] = 1; | 972 | fh->io_allowed[index] = 1; |
@@ -876,9 +975,8 @@ static int vpif_reqbufs(struct file *file, void *priv, | |||
876 | /* Store type of memory requested in channel object */ | 975 | /* Store type of memory requested in channel object */ |
877 | common->memory = reqbuf->memory; | 976 | common->memory = reqbuf->memory; |
878 | INIT_LIST_HEAD(&common->dma_queue); | 977 | INIT_LIST_HEAD(&common->dma_queue); |
879 | |||
880 | /* Allocate buffers */ | 978 | /* Allocate buffers */ |
881 | return videobuf_reqbufs(&common->buffer_queue, reqbuf); | 979 | return vb2_reqbufs(&common->buffer_queue, reqbuf); |
882 | } | 980 | } |
883 | 981 | ||
884 | static int vpif_querybuf(struct file *file, void *priv, | 982 | static int vpif_querybuf(struct file *file, void *priv, |
@@ -891,22 +989,25 @@ static int vpif_querybuf(struct file *file, void *priv, | |||
891 | if (common->fmt.type != tbuf->type) | 989 | if (common->fmt.type != tbuf->type) |
892 | return -EINVAL; | 990 | return -EINVAL; |
893 | 991 | ||
894 | return videobuf_querybuf(&common->buffer_queue, tbuf); | 992 | return vb2_querybuf(&common->buffer_queue, tbuf); |
895 | } | 993 | } |
896 | 994 | ||
897 | static int vpif_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) | 995 | static int vpif_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) |
898 | { | 996 | { |
997 | struct vpif_fh *fh = NULL; | ||
998 | struct channel_obj *ch = NULL; | ||
999 | struct common_obj *common = NULL; | ||
899 | 1000 | ||
900 | struct vpif_fh *fh = priv; | 1001 | if (!buf || !priv) |
901 | struct channel_obj *ch = fh->channel; | 1002 | return -EINVAL; |
902 | struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; | ||
903 | struct v4l2_buffer tbuf = *buf; | ||
904 | struct videobuf_buffer *buf1; | ||
905 | unsigned long addr = 0; | ||
906 | unsigned long flags; | ||
907 | int ret = 0; | ||
908 | 1003 | ||
909 | if (common->fmt.type != tbuf.type) | 1004 | fh = priv; |
1005 | ch = fh->channel; | ||
1006 | if (!ch) | ||
1007 | return -EINVAL; | ||
1008 | |||
1009 | common = &(ch->common[VPIF_VIDEO_INDEX]); | ||
1010 | if (common->fmt.type != buf->type) | ||
910 | return -EINVAL; | 1011 | return -EINVAL; |
911 | 1012 | ||
912 | if (!fh->io_allowed[VPIF_VIDEO_INDEX]) { | 1013 | if (!fh->io_allowed[VPIF_VIDEO_INDEX]) { |
@@ -914,73 +1015,7 @@ static int vpif_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) | |||
914 | return -EACCES; | 1015 | return -EACCES; |
915 | } | 1016 | } |
916 | 1017 | ||
917 | if (!(list_empty(&common->dma_queue)) || | 1018 | return vb2_qbuf(&common->buffer_queue, buf); |
918 | (common->cur_frm != common->next_frm) || | ||
919 | !(common->started) || | ||
920 | (common->started && (0 == ch->field_id))) | ||
921 | return videobuf_qbuf(&common->buffer_queue, buf); | ||
922 | |||
923 | /* bufferqueue is empty store buffer address in VPIF registers */ | ||
924 | mutex_lock(&common->buffer_queue.vb_lock); | ||
925 | buf1 = common->buffer_queue.bufs[tbuf.index]; | ||
926 | if (buf1->memory != tbuf.memory) { | ||
927 | vpif_err("invalid buffer type\n"); | ||
928 | goto qbuf_exit; | ||
929 | } | ||
930 | |||
931 | if ((buf1->state == VIDEOBUF_QUEUED) || | ||
932 | (buf1->state == VIDEOBUF_ACTIVE)) { | ||
933 | vpif_err("invalid state\n"); | ||
934 | goto qbuf_exit; | ||
935 | } | ||
936 | |||
937 | switch (buf1->memory) { | ||
938 | case V4L2_MEMORY_MMAP: | ||
939 | if (buf1->baddr == 0) | ||
940 | goto qbuf_exit; | ||
941 | break; | ||
942 | |||
943 | case V4L2_MEMORY_USERPTR: | ||
944 | if (tbuf.length < buf1->bsize) | ||
945 | goto qbuf_exit; | ||
946 | |||
947 | if ((VIDEOBUF_NEEDS_INIT != buf1->state) | ||
948 | && (buf1->baddr != tbuf.m.userptr)) { | ||
949 | vpif_buffer_release(&common->buffer_queue, buf1); | ||
950 | buf1->baddr = tbuf.m.userptr; | ||
951 | } | ||
952 | break; | ||
953 | |||
954 | default: | ||
955 | goto qbuf_exit; | ||
956 | } | ||
957 | |||
958 | local_irq_save(flags); | ||
959 | ret = vpif_buffer_prepare(&common->buffer_queue, buf1, | ||
960 | common->buffer_queue.field); | ||
961 | if (ret < 0) { | ||
962 | local_irq_restore(flags); | ||
963 | goto qbuf_exit; | ||
964 | } | ||
965 | |||
966 | buf1->state = VIDEOBUF_ACTIVE; | ||
967 | addr = buf1->boff; | ||
968 | common->next_frm = buf1; | ||
969 | if (tbuf.type != V4L2_BUF_TYPE_SLICED_VBI_OUTPUT) { | ||
970 | common->set_addr((addr + common->ytop_off), | ||
971 | (addr + common->ybtm_off), | ||
972 | (addr + common->ctop_off), | ||
973 | (addr + common->cbtm_off)); | ||
974 | } | ||
975 | |||
976 | local_irq_restore(flags); | ||
977 | list_add_tail(&buf1->stream, &common->buffer_queue.stream); | ||
978 | mutex_unlock(&common->buffer_queue.vb_lock); | ||
979 | return 0; | ||
980 | |||
981 | qbuf_exit: | ||
982 | mutex_unlock(&common->buffer_queue.vb_lock); | ||
983 | return -EINVAL; | ||
984 | } | 1019 | } |
985 | 1020 | ||
986 | static int vpif_s_std(struct file *file, void *priv, v4l2_std_id *std_id) | 1021 | static int vpif_s_std(struct file *file, void *priv, v4l2_std_id *std_id) |
@@ -1047,7 +1082,7 @@ static int vpif_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) | |||
1047 | struct channel_obj *ch = fh->channel; | 1082 | struct channel_obj *ch = fh->channel; |
1048 | struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; | 1083 | struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; |
1049 | 1084 | ||
1050 | return videobuf_dqbuf(&common->buffer_queue, p, | 1085 | return vb2_dqbuf(&common->buffer_queue, p, |
1051 | (file->f_flags & O_NONBLOCK)); | 1086 | (file->f_flags & O_NONBLOCK)); |
1052 | } | 1087 | } |
1053 | 1088 | ||
@@ -1058,10 +1093,6 @@ static int vpif_streamon(struct file *file, void *priv, | |||
1058 | struct channel_obj *ch = fh->channel; | 1093 | struct channel_obj *ch = fh->channel; |
1059 | struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; | 1094 | struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; |
1060 | struct channel_obj *oth_ch = vpif_obj.dev[!ch->channel_id]; | 1095 | struct channel_obj *oth_ch = vpif_obj.dev[!ch->channel_id]; |
1061 | struct vpif_params *vpif = &ch->vpifparams; | ||
1062 | struct vpif_display_config *vpif_config_data = | ||
1063 | vpif_dev->platform_data; | ||
1064 | unsigned long addr = 0; | ||
1065 | int ret = 0; | 1096 | int ret = 0; |
1066 | 1097 | ||
1067 | if (buftype != V4L2_BUF_TYPE_VIDEO_OUTPUT) { | 1098 | if (buftype != V4L2_BUF_TYPE_VIDEO_OUTPUT) { |
@@ -1093,82 +1124,13 @@ static int vpif_streamon(struct file *file, void *priv, | |||
1093 | if (ret < 0) | 1124 | if (ret < 0) |
1094 | return ret; | 1125 | return ret; |
1095 | 1126 | ||
1096 | /* Call videobuf_streamon to start streaming in videobuf */ | 1127 | /* Call vb2_streamon to start streaming in videobuf2 */ |
1097 | ret = videobuf_streamon(&common->buffer_queue); | 1128 | ret = vb2_streamon(&common->buffer_queue, buftype); |
1098 | if (ret < 0) { | 1129 | if (ret < 0) { |
1099 | vpif_err("videobuf_streamon\n"); | 1130 | vpif_err("vb2_streamon\n"); |
1100 | return ret; | 1131 | return ret; |
1101 | } | 1132 | } |
1102 | 1133 | ||
1103 | /* If buffer queue is empty, return error */ | ||
1104 | if (list_empty(&common->dma_queue)) { | ||
1105 | vpif_err("buffer queue is empty\n"); | ||
1106 | return -EIO; | ||
1107 | } | ||
1108 | |||
1109 | /* Get the next frame from the buffer queue */ | ||
1110 | common->next_frm = common->cur_frm = | ||
1111 | list_entry(common->dma_queue.next, | ||
1112 | struct videobuf_buffer, queue); | ||
1113 | |||
1114 | list_del(&common->cur_frm->queue); | ||
1115 | /* Mark state of the current frame to active */ | ||
1116 | common->cur_frm->state = VIDEOBUF_ACTIVE; | ||
1117 | |||
1118 | /* Initialize field_id and started member */ | ||
1119 | ch->field_id = 0; | ||
1120 | common->started = 1; | ||
1121 | if (buftype == V4L2_BUF_TYPE_VIDEO_OUTPUT) { | ||
1122 | addr = common->cur_frm->boff; | ||
1123 | /* Calculate the offset for Y and C data in the buffer */ | ||
1124 | vpif_calculate_offsets(ch); | ||
1125 | |||
1126 | if ((ch->vpifparams.std_info.frm_fmt && | ||
1127 | ((common->fmt.fmt.pix.field != V4L2_FIELD_NONE) | ||
1128 | && (common->fmt.fmt.pix.field != V4L2_FIELD_ANY))) | ||
1129 | || (!ch->vpifparams.std_info.frm_fmt | ||
1130 | && (common->fmt.fmt.pix.field == V4L2_FIELD_NONE))) { | ||
1131 | vpif_err("conflict in field format and std format\n"); | ||
1132 | return -EINVAL; | ||
1133 | } | ||
1134 | |||
1135 | /* clock settings */ | ||
1136 | ret = | ||
1137 | vpif_config_data->set_clock(ch->vpifparams.std_info.ycmux_mode, | ||
1138 | ch->vpifparams.std_info.hd_sd); | ||
1139 | if (ret < 0) { | ||
1140 | vpif_err("can't set clock\n"); | ||
1141 | return ret; | ||
1142 | } | ||
1143 | |||
1144 | /* set the parameters and addresses */ | ||
1145 | ret = vpif_set_video_params(vpif, ch->channel_id + 2); | ||
1146 | if (ret < 0) | ||
1147 | return ret; | ||
1148 | |||
1149 | common->started = ret; | ||
1150 | vpif_config_addr(ch, ret); | ||
1151 | common->set_addr((addr + common->ytop_off), | ||
1152 | (addr + common->ybtm_off), | ||
1153 | (addr + common->ctop_off), | ||
1154 | (addr + common->cbtm_off)); | ||
1155 | |||
1156 | /* Set interrupt for both the fields in VPIF | ||
1157 | Register enable channel in VPIF register */ | ||
1158 | if (VPIF_CHANNEL2_VIDEO == ch->channel_id) { | ||
1159 | channel2_intr_assert(); | ||
1160 | channel2_intr_enable(1); | ||
1161 | enable_channel2(1); | ||
1162 | } | ||
1163 | |||
1164 | if ((VPIF_CHANNEL3_VIDEO == ch->channel_id) | ||
1165 | || (common->started == 2)) { | ||
1166 | channel3_intr_assert(); | ||
1167 | channel3_intr_enable(1); | ||
1168 | enable_channel3(1); | ||
1169 | } | ||
1170 | channel_first_int[VPIF_VIDEO_INDEX][ch->channel_id] = 1; | ||
1171 | } | ||
1172 | return ret; | 1134 | return ret; |
1173 | } | 1135 | } |
1174 | 1136 | ||
@@ -1208,7 +1170,7 @@ static int vpif_streamoff(struct file *file, void *priv, | |||
1208 | } | 1170 | } |
1209 | 1171 | ||
1210 | common->started = 0; | 1172 | common->started = 0; |
1211 | return videobuf_streamoff(&common->buffer_queue); | 1173 | return vb2_streamoff(&common->buffer_queue, buftype); |
1212 | } | 1174 | } |
1213 | 1175 | ||
1214 | static int vpif_cropcap(struct file *file, void *priv, | 1176 | static int vpif_cropcap(struct file *file, void *priv, |