4 * STAT module for TI's OMAP3 Camera ISP
6 * Copyright (C) 2009 Texas Instruments, Inc.
9 * Sergio Aguirre <saaguirre@ti.com>
12 * This package is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2 as
14 * published by the Free Software Foundation.
16 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
21 #include <linux/dma-mapping.h>
22 #include <linux/uaccess.h>
26 /* Get next free buffer to write the statistics to and mark it active. */
27 struct ispstat_buffer
*ispstat_buf_next(struct ispstat
*stat
)
30 struct ispstat_buffer
*found
= NULL
;
34 do_gettimeofday(&stat
->active_buf
->ts
);
36 spin_lock_irqsave(&stat
->lock
, flags
);
38 if (stat
->active_buf
) {
39 stat
->active_buf
->config_counter
= stat
->config_counter
;
40 stat
->active_buf
->frame_number
= stat
->frame_number
;
43 for (i
= 0; i
< stat
->nbufs
; i
++) {
44 struct ispstat_buffer
*curr
= &stat
->buf
[i
];
47 * Don't select the buffer which is being copied to
50 if (curr
== stat
->locked_buf
)
54 || (curr
->frame_number
> found
->frame_number
55 && (curr
->frame_number
- found
->frame_number
56 > stat
->max_frame
/ 2))
57 || (curr
->frame_number
< found
->frame_number
58 && (found
->frame_number
- curr
->frame_number
59 < stat
->max_frame
/ 2))) {
64 stat
->active_buf
= found
;
67 if (stat
->frame_number
== stat
->max_frame
)
68 stat
->frame_number
= 0;
70 spin_unlock_irqrestore(&stat
->lock
, flags
);
75 /* Get buffer to userspace. */
76 static struct ispstat_buffer
*ispstat_buf_find(
77 struct ispstat
*stat
, u32 frame_number
)
79 struct ispstat_buffer
*latest
= NULL
;
82 for (i
= 0; i
< stat
->nbufs
; i
++) {
83 struct ispstat_buffer
*curr
= &stat
->buf
[i
];
85 /* We cannot deal with the active buffer. */
86 if (curr
== stat
->active_buf
)
89 /* Don't take uninitialised buffers. */
90 if (curr
->frame_number
== stat
->max_frame
)
93 /* Found correct number. */
94 if (curr
->frame_number
== frame_number
) {
99 /* Select first buffer or a better one. */
101 || (curr
->frame_number
< latest
->frame_number
102 && (latest
->frame_number
- curr
->frame_number
103 > stat
->max_frame
/ 2))
104 || (curr
->frame_number
> latest
->frame_number
105 && (curr
->frame_number
- latest
->frame_number
106 < stat
->max_frame
/ 2)))
114 * ispstat_stats_available - Check for stats available of specified frame.
115 * @aewbdata: Pointer to return AE AWB statistics data
117 * Returns 0 if successful, or -1 if statistics are unavailable.
119 struct ispstat_buffer
*ispstat_buf_get(struct ispstat
*stat
,
121 unsigned int frame_number
)
125 struct ispstat_buffer
*buf
;
127 spin_lock_irqsave(&stat
->lock
, flags
);
129 buf
= ispstat_buf_find(stat
, frame_number
);
131 spin_unlock_irqrestore(&stat
->lock
, flags
);
132 return ERR_PTR(-EBUSY
);
135 stat
->locked_buf
= buf
;
137 spin_unlock_irqrestore(&stat
->lock
, flags
);
139 rval
= copy_to_user((void *)ptr
,
145 "failed copying %d bytes of stat data\n", rval
);
146 buf
= ERR_PTR(-EFAULT
);
147 ispstat_buf_release(stat
);
153 void ispstat_buf_release(struct ispstat
*stat
)
157 spin_lock_irqsave(&stat
->lock
, flags
);
158 stat
->locked_buf
= NULL
;
159 spin_unlock_irqrestore(&stat
->lock
, flags
);
162 void ispstat_bufs_free(struct ispstat
*stat
)
164 struct isp_device
*isp
= dev_get_drvdata(stat
->dev
);
167 for (i
= 0; i
< stat
->nbufs
; i
++) {
168 struct ispstat_buffer
*buf
= &stat
->buf
[i
];
170 if (!buf
->iommu_addr
)
173 iommu_vfree(isp
->iommu
, buf
->iommu_addr
);
177 stat
->buf_alloc_size
= 0;
180 int ispstat_bufs_alloc(struct ispstat
*stat
,
183 struct isp_device
*isp
= dev_get_drvdata(stat
->dev
);
187 spin_lock_irqsave(&stat
->lock
, flags
);
189 BUG_ON(stat
->locked_buf
!= NULL
);
191 /* Are the old buffers big enough? */
192 if (stat
->buf_alloc_size
>= size
) {
193 for (i
= 0; i
< stat
->nbufs
; i
++)
194 stat
->buf
[i
].frame_number
= stat
->max_frame
;
195 spin_unlock_irqrestore(&stat
->lock
, flags
);
199 if (isp
->running
!= ISP_STOPPED
) {
200 dev_info(stat
->dev
, "stat: trying to configure when busy\n");
201 spin_unlock_irqrestore(&stat
->lock
, flags
);
205 spin_unlock_irqrestore(&stat
->lock
, flags
);
207 ispstat_bufs_free(stat
);
209 for (i
= 0; i
< stat
->nbufs
; i
++) {
210 struct ispstat_buffer
*buf
= &stat
->buf
[i
];
212 buf
->iommu_addr
= iommu_vmalloc(isp
->iommu
, 0, size
,
214 if (buf
->iommu_addr
== 0) {
215 dev_info(stat
->dev
, "stat: Can't acquire memory for "
217 ispstat_bufs_free(stat
);
220 buf
->virt_addr
= da_to_va(isp
->iommu
, (u32
)buf
->iommu_addr
);
221 buf
->frame_number
= stat
->max_frame
;
224 stat
->buf_alloc_size
= size
;
227 stat
->buf_size
= size
;
228 stat
->active_buf
= NULL
;
233 int ispstat_init(struct device
*dev
, struct ispstat
*stat
,
234 unsigned int nbufs
, unsigned int max_frame
)
237 BUG_ON(max_frame
< 2);
238 BUG_ON(nbufs
>= max_frame
);
240 memset(stat
, 0, sizeof(*stat
));
242 stat
->buf
= kcalloc(nbufs
, sizeof(*stat
->buf
), GFP_KERNEL
);
246 spin_lock_init(&stat
->lock
);
249 stat
->max_frame
= max_frame
;
254 void ispstat_free(struct ispstat
*stat
)
256 ispstat_bufs_free(stat
);