diff options
author | Lad, Prabhakar <prabhakar.csengg@gmail.com> | 2014-05-16 09:33:09 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <m.chehab@samsung.com> | 2014-05-23 18:01:30 -0400 |
commit | 54a445a41bac7c320ee00afa633fe869428697c4 (patch) | |
tree | 073d01c3ed306e543f015cebae7b231ac367aec6 /drivers/media/platform/davinci/vpif_display.c | |
parent | d10ed5c1906e708e6a9fc26e9dd25b479b5439e9 (diff) |
[media] media: davinci: vpif_display: release buffers in case start_streaming() call back fails
this patch adds support to release the buffer by calling
vb2_buffer_done(), with state marked as VB2_BUF_STATE_QUEUED
if start_streaming() call back fails.
Signed-off-by: Lad, Prabhakar <prabhakar.csengg@gmail.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
Diffstat (limited to 'drivers/media/platform/davinci/vpif_display.c')
-rw-r--r-- | drivers/media/platform/davinci/vpif_display.c | 42 |
1 files changed, 26 insertions, 16 deletions
diff --git a/drivers/media/platform/davinci/vpif_display.c b/drivers/media/platform/davinci/vpif_display.c index 8bb9f022d225..1a17a455b44f 100644 --- a/drivers/media/platform/davinci/vpif_display.c +++ b/drivers/media/platform/davinci/vpif_display.c | |||
@@ -196,26 +196,16 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count) | |||
196 | struct channel_obj *ch = vb2_get_drv_priv(vq); | 196 | struct channel_obj *ch = vb2_get_drv_priv(vq); |
197 | struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; | 197 | struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; |
198 | struct vpif_params *vpif = &ch->vpifparams; | 198 | struct vpif_params *vpif = &ch->vpifparams; |
199 | unsigned long addr = 0; | 199 | struct vpif_disp_buffer *buf, *tmp; |
200 | unsigned long flags; | 200 | unsigned long addr, flags; |
201 | int ret; | 201 | int ret; |
202 | 202 | ||
203 | spin_lock_irqsave(&common->irqlock, flags); | 203 | spin_lock_irqsave(&common->irqlock, flags); |
204 | 204 | ||
205 | /* Get the next frame from the buffer queue */ | ||
206 | common->next_frm = common->cur_frm = | ||
207 | list_entry(common->dma_queue.next, | ||
208 | struct vpif_disp_buffer, list); | ||
209 | |||
210 | list_del(&common->cur_frm->list); | ||
211 | spin_unlock_irqrestore(&common->irqlock, flags); | ||
212 | /* Mark state of the current frame to active */ | ||
213 | common->cur_frm->vb.state = VB2_BUF_STATE_ACTIVE; | ||
214 | |||
215 | /* Initialize field_id and started member */ | 205 | /* Initialize field_id and started member */ |
216 | ch->field_id = 0; | 206 | ch->field_id = 0; |
217 | common->started = 1; | 207 | common->started = 1; |
218 | addr = vb2_dma_contig_plane_dma_addr(&common->cur_frm->vb, 0); | 208 | |
219 | /* Calculate the offset for Y and C data in the buffer */ | 209 | /* Calculate the offset for Y and C data in the buffer */ |
220 | vpif_calculate_offsets(ch); | 210 | vpif_calculate_offsets(ch); |
221 | 211 | ||
@@ -225,7 +215,8 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count) | |||
225 | || (!ch->vpifparams.std_info.frm_fmt | 215 | || (!ch->vpifparams.std_info.frm_fmt |
226 | && (common->fmt.fmt.pix.field == V4L2_FIELD_NONE))) { | 216 | && (common->fmt.fmt.pix.field == V4L2_FIELD_NONE))) { |
227 | vpif_err("conflict in field format and std format\n"); | 217 | vpif_err("conflict in field format and std format\n"); |
228 | return -EINVAL; | 218 | ret = -EINVAL; |
219 | goto err; | ||
229 | } | 220 | } |
230 | 221 | ||
231 | /* clock settings */ | 222 | /* clock settings */ |
@@ -234,17 +225,28 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count) | |||
234 | ycmux_mode, ch->vpifparams.std_info.hd_sd); | 225 | ycmux_mode, ch->vpifparams.std_info.hd_sd); |
235 | if (ret < 0) { | 226 | if (ret < 0) { |
236 | vpif_err("can't set clock\n"); | 227 | vpif_err("can't set clock\n"); |
237 | return ret; | 228 | goto err; |
238 | } | 229 | } |
239 | } | 230 | } |
240 | 231 | ||
241 | /* set the parameters and addresses */ | 232 | /* set the parameters and addresses */ |
242 | ret = vpif_set_video_params(vpif, ch->channel_id + 2); | 233 | ret = vpif_set_video_params(vpif, ch->channel_id + 2); |
243 | if (ret < 0) | 234 | if (ret < 0) |
244 | return ret; | 235 | goto err; |
245 | 236 | ||
246 | common->started = ret; | 237 | common->started = ret; |
247 | vpif_config_addr(ch, ret); | 238 | vpif_config_addr(ch, ret); |
239 | /* Get the next frame from the buffer queue */ | ||
240 | common->next_frm = common->cur_frm = | ||
241 | list_entry(common->dma_queue.next, | ||
242 | struct vpif_disp_buffer, list); | ||
243 | |||
244 | list_del(&common->cur_frm->list); | ||
245 | spin_unlock_irqrestore(&common->irqlock, flags); | ||
246 | /* Mark state of the current frame to active */ | ||
247 | common->cur_frm->vb.state = VB2_BUF_STATE_ACTIVE; | ||
248 | |||
249 | addr = vb2_dma_contig_plane_dma_addr(&common->cur_frm->vb, 0); | ||
248 | common->set_addr((addr + common->ytop_off), | 250 | common->set_addr((addr + common->ytop_off), |
249 | (addr + common->ybtm_off), | 251 | (addr + common->ybtm_off), |
250 | (addr + common->ctop_off), | 252 | (addr + common->ctop_off), |
@@ -271,6 +273,14 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count) | |||
271 | } | 273 | } |
272 | 274 | ||
273 | return 0; | 275 | return 0; |
276 | |||
277 | err: | ||
278 | list_for_each_entry_safe(buf, tmp, &common->dma_queue, list) { | ||
279 | list_del(&buf->list); | ||
280 | vb2_buffer_done(&buf->vb, VB2_BUF_STATE_QUEUED); | ||
281 | } | ||
282 | |||
283 | return ret; | ||
274 | } | 284 | } |
275 | 285 | ||
276 | /* abort streaming and wait for last buffer */ | 286 | /* abort streaming and wait for last buffer */ |