4 * TI OMAP3 ISP - Histogram module
6 * Copyright (C) 2010 Nokia Corporation
7 * Copyright (C) 2009 Texas Instruments, Inc.
9 * Contacts: David Cohen <dacohen@gmail.com>
10 * Laurent Pinchart <laurent.pinchart@ideasonboard.com>
11 * Sakari Ailus <sakari.ailus@iki.fi>
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License version 2 as
15 * published by the Free Software Foundation.
18 #include <linux/delay.h>
19 #include <linux/device.h>
20 #include <linux/dmaengine.h>
21 #include <linux/slab.h>
22 #include <linux/uaccess.h>
28 #define HIST_CONFIG_DMA 1
31 * hist_reset_mem - clear Histogram memory before start stats engine.
33 static void hist_reset_mem(struct ispstat
*hist
)
35 struct isp_device
*isp
= hist
->isp
;
36 struct omap3isp_hist_config
*conf
= hist
->priv
;
39 isp_reg_writel(isp
, 0, OMAP3_ISP_IOMEM_HIST
, ISPHIST_ADDR
);
42 * By setting it, the histogram internal buffer is being cleared at the
43 * same time it's being read. This bit must be cleared afterwards.
45 isp_reg_set(isp
, OMAP3_ISP_IOMEM_HIST
, ISPHIST_CNT
, ISPHIST_CNT_CLEAR
);
48 * We'll clear 4 words at each iteration for optimization. It avoids
49 * 3/4 of the jumps. We also know HIST_MEM_SIZE is divisible by 4.
51 for (i
= OMAP3ISP_HIST_MEM_SIZE
/ 4; i
> 0; i
--) {
52 isp_reg_readl(isp
, OMAP3_ISP_IOMEM_HIST
, ISPHIST_DATA
);
53 isp_reg_readl(isp
, OMAP3_ISP_IOMEM_HIST
, ISPHIST_DATA
);
54 isp_reg_readl(isp
, OMAP3_ISP_IOMEM_HIST
, ISPHIST_DATA
);
55 isp_reg_readl(isp
, OMAP3_ISP_IOMEM_HIST
, ISPHIST_DATA
);
57 isp_reg_clr(isp
, OMAP3_ISP_IOMEM_HIST
, ISPHIST_CNT
, ISPHIST_CNT_CLEAR
);
59 hist
->wait_acc_frames
= conf
->num_acc_frames
;
63 * hist_setup_regs - Helper function to update Histogram registers.
65 static void hist_setup_regs(struct ispstat
*hist
, void *priv
)
67 struct isp_device
*isp
= hist
->isp
;
68 struct omap3isp_hist_config
*conf
= priv
;
72 u32 reg_hor
[OMAP3ISP_HIST_MAX_REGIONS
];
73 u32 reg_ver
[OMAP3ISP_HIST_MAX_REGIONS
];
75 if (!hist
->update
|| hist
->state
== ISPSTAT_DISABLED
||
76 hist
->state
== ISPSTAT_DISABLING
)
79 cnt
= conf
->cfa
<< ISPHIST_CNT_CFA_SHIFT
;
81 wb_gain
= conf
->wg
[0] << ISPHIST_WB_GAIN_WG00_SHIFT
;
82 wb_gain
|= conf
->wg
[1] << ISPHIST_WB_GAIN_WG01_SHIFT
;
83 wb_gain
|= conf
->wg
[2] << ISPHIST_WB_GAIN_WG02_SHIFT
;
84 if (conf
->cfa
== OMAP3ISP_HIST_CFA_BAYER
)
85 wb_gain
|= conf
->wg
[3] << ISPHIST_WB_GAIN_WG03_SHIFT
;
87 /* Regions size and position */
88 for (c
= 0; c
< OMAP3ISP_HIST_MAX_REGIONS
; c
++) {
89 if (c
< conf
->num_regions
) {
90 reg_hor
[c
] = (conf
->region
[c
].h_start
<<
91 ISPHIST_REG_START_SHIFT
)
92 | (conf
->region
[c
].h_end
<<
93 ISPHIST_REG_END_SHIFT
);
94 reg_ver
[c
] = (conf
->region
[c
].v_start
<<
95 ISPHIST_REG_START_SHIFT
)
96 | (conf
->region
[c
].v_end
<<
97 ISPHIST_REG_END_SHIFT
);
104 cnt
|= conf
->hist_bins
<< ISPHIST_CNT_BINS_SHIFT
;
105 switch (conf
->hist_bins
) {
106 case OMAP3ISP_HIST_BINS_256
:
107 cnt
|= (ISPHIST_IN_BIT_WIDTH_CCDC
- 8) <<
108 ISPHIST_CNT_SHIFT_SHIFT
;
110 case OMAP3ISP_HIST_BINS_128
:
111 cnt
|= (ISPHIST_IN_BIT_WIDTH_CCDC
- 7) <<
112 ISPHIST_CNT_SHIFT_SHIFT
;
114 case OMAP3ISP_HIST_BINS_64
:
115 cnt
|= (ISPHIST_IN_BIT_WIDTH_CCDC
- 6) <<
116 ISPHIST_CNT_SHIFT_SHIFT
;
118 default: /* OMAP3ISP_HIST_BINS_32 */
119 cnt
|= (ISPHIST_IN_BIT_WIDTH_CCDC
- 5) <<
120 ISPHIST_CNT_SHIFT_SHIFT
;
124 hist_reset_mem(hist
);
126 isp_reg_writel(isp
, cnt
, OMAP3_ISP_IOMEM_HIST
, ISPHIST_CNT
);
127 isp_reg_writel(isp
, wb_gain
, OMAP3_ISP_IOMEM_HIST
, ISPHIST_WB_GAIN
);
128 isp_reg_writel(isp
, reg_hor
[0], OMAP3_ISP_IOMEM_HIST
, ISPHIST_R0_HORZ
);
129 isp_reg_writel(isp
, reg_ver
[0], OMAP3_ISP_IOMEM_HIST
, ISPHIST_R0_VERT
);
130 isp_reg_writel(isp
, reg_hor
[1], OMAP3_ISP_IOMEM_HIST
, ISPHIST_R1_HORZ
);
131 isp_reg_writel(isp
, reg_ver
[1], OMAP3_ISP_IOMEM_HIST
, ISPHIST_R1_VERT
);
132 isp_reg_writel(isp
, reg_hor
[2], OMAP3_ISP_IOMEM_HIST
, ISPHIST_R2_HORZ
);
133 isp_reg_writel(isp
, reg_ver
[2], OMAP3_ISP_IOMEM_HIST
, ISPHIST_R2_VERT
);
134 isp_reg_writel(isp
, reg_hor
[3], OMAP3_ISP_IOMEM_HIST
, ISPHIST_R3_HORZ
);
135 isp_reg_writel(isp
, reg_ver
[3], OMAP3_ISP_IOMEM_HIST
, ISPHIST_R3_VERT
);
138 hist
->config_counter
+= hist
->inc_config
;
139 hist
->inc_config
= 0;
140 hist
->buf_size
= conf
->buf_size
;
143 static void hist_enable(struct ispstat
*hist
, int enable
)
146 isp_reg_set(hist
->isp
, OMAP3_ISP_IOMEM_HIST
, ISPHIST_PCR
,
148 omap3isp_subclk_enable(hist
->isp
, OMAP3_ISP_SUBCLK_HIST
);
150 isp_reg_clr(hist
->isp
, OMAP3_ISP_IOMEM_HIST
, ISPHIST_PCR
,
152 omap3isp_subclk_disable(hist
->isp
, OMAP3_ISP_SUBCLK_HIST
);
156 static int hist_busy(struct ispstat
*hist
)
158 return isp_reg_readl(hist
->isp
, OMAP3_ISP_IOMEM_HIST
, ISPHIST_PCR
)
162 static void hist_dma_cb(void *data
)
164 struct ispstat
*hist
= data
;
166 /* FIXME: The DMA engine API can't report transfer errors :-/ */
168 isp_reg_clr(hist
->isp
, OMAP3_ISP_IOMEM_HIST
, ISPHIST_CNT
,
171 omap3isp_stat_dma_isr(hist
);
172 if (hist
->state
!= ISPSTAT_DISABLED
)
173 omap3isp_hist_dma_done(hist
->isp
);
176 static int hist_buf_dma(struct ispstat
*hist
)
178 dma_addr_t dma_addr
= hist
->active_buf
->dma_addr
;
179 struct dma_async_tx_descriptor
*tx
;
180 struct dma_slave_config cfg
;
184 if (unlikely(!dma_addr
)) {
185 dev_dbg(hist
->isp
->dev
, "hist: invalid DMA buffer address\n");
189 isp_reg_writel(hist
->isp
, 0, OMAP3_ISP_IOMEM_HIST
, ISPHIST_ADDR
);
190 isp_reg_set(hist
->isp
, OMAP3_ISP_IOMEM_HIST
, ISPHIST_CNT
,
192 omap3isp_flush(hist
->isp
);
194 memset(&cfg
, 0, sizeof(cfg
));
195 cfg
.src_addr
= hist
->isp
->mmio_hist_base_phys
+ ISPHIST_DATA
;
196 cfg
.src_addr_width
= DMA_SLAVE_BUSWIDTH_4_BYTES
;
197 cfg
.src_maxburst
= hist
->buf_size
/ 4;
199 ret
= dmaengine_slave_config(hist
->dma_ch
, &cfg
);
201 dev_dbg(hist
->isp
->dev
,
202 "hist: DMA slave configuration failed\n");
206 tx
= dmaengine_prep_slave_single(hist
->dma_ch
, dma_addr
,
207 hist
->buf_size
, DMA_DEV_TO_MEM
,
210 dev_dbg(hist
->isp
->dev
,
211 "hist: DMA slave preparation failed\n");
215 tx
->callback
= hist_dma_cb
;
216 tx
->callback_param
= hist
;
217 cookie
= tx
->tx_submit(tx
);
218 if (dma_submit_error(cookie
)) {
219 dev_dbg(hist
->isp
->dev
, "hist: DMA submission failed\n");
223 dma_async_issue_pending(hist
->dma_ch
);
225 return STAT_BUF_WAITING_DMA
;
228 hist_reset_mem(hist
);
232 static int hist_buf_pio(struct ispstat
*hist
)
234 struct isp_device
*isp
= hist
->isp
;
235 u32
*buf
= hist
->active_buf
->virt_addr
;
239 dev_dbg(isp
->dev
, "hist: invalid PIO buffer address\n");
240 hist_reset_mem(hist
);
244 isp_reg_writel(isp
, 0, OMAP3_ISP_IOMEM_HIST
, ISPHIST_ADDR
);
247 * By setting it, the histogram internal buffer is being cleared at the
248 * same time it's being read. This bit must be cleared just after all
251 isp_reg_set(isp
, OMAP3_ISP_IOMEM_HIST
, ISPHIST_CNT
, ISPHIST_CNT_CLEAR
);
254 * We'll read 4 times a 4-bytes-word at each iteration for
255 * optimization. It avoids 3/4 of the jumps. We also know buf_size is
258 for (i
= hist
->buf_size
/ 16; i
> 0; i
--) {
259 *buf
++ = isp_reg_readl(isp
, OMAP3_ISP_IOMEM_HIST
, ISPHIST_DATA
);
260 *buf
++ = isp_reg_readl(isp
, OMAP3_ISP_IOMEM_HIST
, ISPHIST_DATA
);
261 *buf
++ = isp_reg_readl(isp
, OMAP3_ISP_IOMEM_HIST
, ISPHIST_DATA
);
262 *buf
++ = isp_reg_readl(isp
, OMAP3_ISP_IOMEM_HIST
, ISPHIST_DATA
);
264 isp_reg_clr(hist
->isp
, OMAP3_ISP_IOMEM_HIST
, ISPHIST_CNT
,
267 return STAT_BUF_DONE
;
271 * hist_buf_process - Callback from ISP driver for HIST interrupt.
273 static int hist_buf_process(struct ispstat
*hist
)
275 struct omap3isp_hist_config
*user_cfg
= hist
->priv
;
278 if (atomic_read(&hist
->buf_err
) || hist
->state
!= ISPSTAT_ENABLED
) {
279 hist_reset_mem(hist
);
283 if (--(hist
->wait_acc_frames
))
287 ret
= hist_buf_dma(hist
);
289 ret
= hist_buf_pio(hist
);
291 hist
->wait_acc_frames
= user_cfg
->num_acc_frames
;
296 static u32
hist_get_buf_size(struct omap3isp_hist_config
*conf
)
298 return OMAP3ISP_HIST_MEM_SIZE_BINS(conf
->hist_bins
) * conf
->num_regions
;
302 * hist_validate_params - Helper function to check user given params.
303 * @new_conf: Pointer to user configuration structure.
305 * Returns 0 on success configuration.
307 static int hist_validate_params(struct ispstat
*hist
, void *new_conf
)
309 struct omap3isp_hist_config
*user_cfg
= new_conf
;
313 if (user_cfg
->cfa
> OMAP3ISP_HIST_CFA_FOVEONX3
)
316 /* Regions size and position */
318 if ((user_cfg
->num_regions
< OMAP3ISP_HIST_MIN_REGIONS
) ||
319 (user_cfg
->num_regions
> OMAP3ISP_HIST_MAX_REGIONS
))
323 for (c
= 0; c
< user_cfg
->num_regions
; c
++) {
324 if (user_cfg
->region
[c
].h_start
& ~ISPHIST_REG_START_END_MASK
)
326 if (user_cfg
->region
[c
].h_end
& ~ISPHIST_REG_START_END_MASK
)
328 if (user_cfg
->region
[c
].v_start
& ~ISPHIST_REG_START_END_MASK
)
330 if (user_cfg
->region
[c
].v_end
& ~ISPHIST_REG_START_END_MASK
)
332 if (user_cfg
->region
[c
].h_start
> user_cfg
->region
[c
].h_end
)
334 if (user_cfg
->region
[c
].v_start
> user_cfg
->region
[c
].v_end
)
338 switch (user_cfg
->num_regions
) {
340 if (user_cfg
->hist_bins
> OMAP3ISP_HIST_BINS_256
)
344 if (user_cfg
->hist_bins
> OMAP3ISP_HIST_BINS_128
)
347 default: /* 3 or 4 */
348 if (user_cfg
->hist_bins
> OMAP3ISP_HIST_BINS_64
)
353 buf_size
= hist_get_buf_size(user_cfg
);
354 if (buf_size
> user_cfg
->buf_size
)
355 /* User's buf_size request wasn't enough */
356 user_cfg
->buf_size
= buf_size
;
357 else if (user_cfg
->buf_size
> OMAP3ISP_HIST_MAX_BUF_SIZE
)
358 user_cfg
->buf_size
= OMAP3ISP_HIST_MAX_BUF_SIZE
;
363 static int hist_comp_params(struct ispstat
*hist
,
364 struct omap3isp_hist_config
*user_cfg
)
366 struct omap3isp_hist_config
*cur_cfg
= hist
->priv
;
369 if (cur_cfg
->cfa
!= user_cfg
->cfa
)
372 if (cur_cfg
->num_acc_frames
!= user_cfg
->num_acc_frames
)
375 if (cur_cfg
->hist_bins
!= user_cfg
->hist_bins
)
378 for (c
= 0; c
< OMAP3ISP_HIST_MAX_WG
; c
++) {
379 if (c
== 3 && user_cfg
->cfa
== OMAP3ISP_HIST_CFA_FOVEONX3
)
381 else if (cur_cfg
->wg
[c
] != user_cfg
->wg
[c
])
385 if (cur_cfg
->num_regions
!= user_cfg
->num_regions
)
389 for (c
= 0; c
< user_cfg
->num_regions
; c
++) {
390 if (cur_cfg
->region
[c
].h_start
!= user_cfg
->region
[c
].h_start
)
392 if (cur_cfg
->region
[c
].h_end
!= user_cfg
->region
[c
].h_end
)
394 if (cur_cfg
->region
[c
].v_start
!= user_cfg
->region
[c
].v_start
)
396 if (cur_cfg
->region
[c
].v_end
!= user_cfg
->region
[c
].v_end
)
404 * hist_update_params - Helper function to check and store user given params.
405 * @new_conf: Pointer to user configuration structure.
407 static void hist_set_params(struct ispstat
*hist
, void *new_conf
)
409 struct omap3isp_hist_config
*user_cfg
= new_conf
;
410 struct omap3isp_hist_config
*cur_cfg
= hist
->priv
;
412 if (!hist
->configured
|| hist_comp_params(hist
, user_cfg
)) {
413 memcpy(cur_cfg
, user_cfg
, sizeof(*user_cfg
));
414 if (user_cfg
->num_acc_frames
== 0)
415 user_cfg
->num_acc_frames
= 1;
419 * User might be asked for a bigger buffer than necessary for
420 * this configuration. In order to return the right amount of
421 * data during buffer request, let's calculate the size here
422 * instead of stick with user_cfg->buf_size.
424 cur_cfg
->buf_size
= hist_get_buf_size(cur_cfg
);
429 static long hist_ioctl(struct v4l2_subdev
*sd
, unsigned int cmd
, void *arg
)
431 struct ispstat
*stat
= v4l2_get_subdevdata(sd
);
434 case VIDIOC_OMAP3ISP_HIST_CFG
:
435 return omap3isp_stat_config(stat
, arg
);
436 case VIDIOC_OMAP3ISP_STAT_REQ
:
437 return omap3isp_stat_request_statistics(stat
, arg
);
438 case VIDIOC_OMAP3ISP_STAT_EN
: {
440 return omap3isp_stat_enable(stat
, !!*en
);
448 static const struct ispstat_ops hist_ops
= {
449 .validate_params
= hist_validate_params
,
450 .set_params
= hist_set_params
,
451 .setup_regs
= hist_setup_regs
,
452 .enable
= hist_enable
,
454 .buf_process
= hist_buf_process
,
457 static const struct v4l2_subdev_core_ops hist_subdev_core_ops
= {
459 .subscribe_event
= omap3isp_stat_subscribe_event
,
460 .unsubscribe_event
= omap3isp_stat_unsubscribe_event
,
463 static const struct v4l2_subdev_video_ops hist_subdev_video_ops
= {
464 .s_stream
= omap3isp_stat_s_stream
,
467 static const struct v4l2_subdev_ops hist_subdev_ops
= {
468 .core
= &hist_subdev_core_ops
,
469 .video
= &hist_subdev_video_ops
,
473 * omap3isp_hist_init - Module Initialization.
475 int omap3isp_hist_init(struct isp_device
*isp
)
477 struct ispstat
*hist
= &isp
->isp_hist
;
478 struct omap3isp_hist_config
*hist_cfg
;
481 hist_cfg
= devm_kzalloc(isp
->dev
, sizeof(*hist_cfg
), GFP_KERNEL
);
482 if (hist_cfg
== NULL
)
487 if (HIST_CONFIG_DMA
) {
491 * We need slave capable channel without DMA request line for
492 * reading out the data.
493 * For this we can use dma_request_chan_by_mask() as we are
494 * happy with any channel as long as it is capable of slave
498 dma_cap_set(DMA_SLAVE
, mask
);
499 hist
->dma_ch
= dma_request_chan_by_mask(&mask
);
500 if (IS_ERR(hist
->dma_ch
)) {
501 ret
= PTR_ERR(hist
->dma_ch
);
502 if (ret
== -EPROBE_DEFER
)
507 "hist: DMA channel request failed, using PIO\n");
509 dev_dbg(isp
->dev
, "hist: using DMA channel %s\n",
510 dma_chan_name(hist
->dma_ch
));
514 hist
->ops
= &hist_ops
;
515 hist
->priv
= hist_cfg
;
516 hist
->event_type
= V4L2_EVENT_OMAP3ISP_HIST
;
518 ret
= omap3isp_stat_init(hist
, "histogram", &hist_subdev_ops
);
521 dma_release_channel(hist
->dma_ch
);
528 * omap3isp_hist_cleanup - Module cleanup.
530 void omap3isp_hist_cleanup(struct isp_device
*isp
)
532 struct ispstat
*hist
= &isp
->isp_hist
;
535 dma_release_channel(hist
->dma_ch
);
537 omap3isp_stat_cleanup(hist
);