1 // SPDX-License-Identifier: GPL-2.0-only
5 * TI OMAP3 ISP - Histogram module
7 * Copyright (C) 2010 Nokia Corporation
8 * Copyright (C) 2009 Texas Instruments, Inc.
10 * Contacts: David Cohen <dacohen@gmail.com>
11 * Laurent Pinchart <laurent.pinchart@ideasonboard.com>
12 * Sakari Ailus <sakari.ailus@iki.fi>
15 #include <linux/delay.h>
16 #include <linux/device.h>
17 #include <linux/dmaengine.h>
18 #include <linux/slab.h>
19 #include <linux/uaccess.h>
25 #define HIST_CONFIG_DMA 1
28 * hist_reset_mem - clear Histogram memory before start stats engine.
30 static void hist_reset_mem(struct ispstat
*hist
)
32 struct isp_device
*isp
= hist
->isp
;
33 struct omap3isp_hist_config
*conf
= hist
->priv
;
36 isp_reg_writel(isp
, 0, OMAP3_ISP_IOMEM_HIST
, ISPHIST_ADDR
);
39 * By setting it, the histogram internal buffer is being cleared at the
40 * same time it's being read. This bit must be cleared afterwards.
42 isp_reg_set(isp
, OMAP3_ISP_IOMEM_HIST
, ISPHIST_CNT
, ISPHIST_CNT_CLEAR
);
45 * We'll clear 4 words at each iteration for optimization. It avoids
46 * 3/4 of the jumps. We also know HIST_MEM_SIZE is divisible by 4.
48 for (i
= OMAP3ISP_HIST_MEM_SIZE
/ 4; i
> 0; i
--) {
49 isp_reg_readl(isp
, OMAP3_ISP_IOMEM_HIST
, ISPHIST_DATA
);
50 isp_reg_readl(isp
, OMAP3_ISP_IOMEM_HIST
, ISPHIST_DATA
);
51 isp_reg_readl(isp
, OMAP3_ISP_IOMEM_HIST
, ISPHIST_DATA
);
52 isp_reg_readl(isp
, OMAP3_ISP_IOMEM_HIST
, ISPHIST_DATA
);
54 isp_reg_clr(isp
, OMAP3_ISP_IOMEM_HIST
, ISPHIST_CNT
, ISPHIST_CNT_CLEAR
);
56 hist
->wait_acc_frames
= conf
->num_acc_frames
;
60 * hist_setup_regs - Helper function to update Histogram registers.
62 static void hist_setup_regs(struct ispstat
*hist
, void *priv
)
64 struct isp_device
*isp
= hist
->isp
;
65 struct omap3isp_hist_config
*conf
= priv
;
69 u32 reg_hor
[OMAP3ISP_HIST_MAX_REGIONS
];
70 u32 reg_ver
[OMAP3ISP_HIST_MAX_REGIONS
];
72 if (!hist
->update
|| hist
->state
== ISPSTAT_DISABLED
||
73 hist
->state
== ISPSTAT_DISABLING
)
76 cnt
= conf
->cfa
<< ISPHIST_CNT_CFA_SHIFT
;
78 wb_gain
= conf
->wg
[0] << ISPHIST_WB_GAIN_WG00_SHIFT
;
79 wb_gain
|= conf
->wg
[1] << ISPHIST_WB_GAIN_WG01_SHIFT
;
80 wb_gain
|= conf
->wg
[2] << ISPHIST_WB_GAIN_WG02_SHIFT
;
81 if (conf
->cfa
== OMAP3ISP_HIST_CFA_BAYER
)
82 wb_gain
|= conf
->wg
[3] << ISPHIST_WB_GAIN_WG03_SHIFT
;
84 /* Regions size and position */
85 for (c
= 0; c
< OMAP3ISP_HIST_MAX_REGIONS
; c
++) {
86 if (c
< conf
->num_regions
) {
87 reg_hor
[c
] = (conf
->region
[c
].h_start
<<
88 ISPHIST_REG_START_SHIFT
)
89 | (conf
->region
[c
].h_end
<<
90 ISPHIST_REG_END_SHIFT
);
91 reg_ver
[c
] = (conf
->region
[c
].v_start
<<
92 ISPHIST_REG_START_SHIFT
)
93 | (conf
->region
[c
].v_end
<<
94 ISPHIST_REG_END_SHIFT
);
101 cnt
|= conf
->hist_bins
<< ISPHIST_CNT_BINS_SHIFT
;
102 switch (conf
->hist_bins
) {
103 case OMAP3ISP_HIST_BINS_256
:
104 cnt
|= (ISPHIST_IN_BIT_WIDTH_CCDC
- 8) <<
105 ISPHIST_CNT_SHIFT_SHIFT
;
107 case OMAP3ISP_HIST_BINS_128
:
108 cnt
|= (ISPHIST_IN_BIT_WIDTH_CCDC
- 7) <<
109 ISPHIST_CNT_SHIFT_SHIFT
;
111 case OMAP3ISP_HIST_BINS_64
:
112 cnt
|= (ISPHIST_IN_BIT_WIDTH_CCDC
- 6) <<
113 ISPHIST_CNT_SHIFT_SHIFT
;
115 default: /* OMAP3ISP_HIST_BINS_32 */
116 cnt
|= (ISPHIST_IN_BIT_WIDTH_CCDC
- 5) <<
117 ISPHIST_CNT_SHIFT_SHIFT
;
121 hist_reset_mem(hist
);
123 isp_reg_writel(isp
, cnt
, OMAP3_ISP_IOMEM_HIST
, ISPHIST_CNT
);
124 isp_reg_writel(isp
, wb_gain
, OMAP3_ISP_IOMEM_HIST
, ISPHIST_WB_GAIN
);
125 isp_reg_writel(isp
, reg_hor
[0], OMAP3_ISP_IOMEM_HIST
, ISPHIST_R0_HORZ
);
126 isp_reg_writel(isp
, reg_ver
[0], OMAP3_ISP_IOMEM_HIST
, ISPHIST_R0_VERT
);
127 isp_reg_writel(isp
, reg_hor
[1], OMAP3_ISP_IOMEM_HIST
, ISPHIST_R1_HORZ
);
128 isp_reg_writel(isp
, reg_ver
[1], OMAP3_ISP_IOMEM_HIST
, ISPHIST_R1_VERT
);
129 isp_reg_writel(isp
, reg_hor
[2], OMAP3_ISP_IOMEM_HIST
, ISPHIST_R2_HORZ
);
130 isp_reg_writel(isp
, reg_ver
[2], OMAP3_ISP_IOMEM_HIST
, ISPHIST_R2_VERT
);
131 isp_reg_writel(isp
, reg_hor
[3], OMAP3_ISP_IOMEM_HIST
, ISPHIST_R3_HORZ
);
132 isp_reg_writel(isp
, reg_ver
[3], OMAP3_ISP_IOMEM_HIST
, ISPHIST_R3_VERT
);
135 hist
->config_counter
+= hist
->inc_config
;
136 hist
->inc_config
= 0;
137 hist
->buf_size
= conf
->buf_size
;
140 static void hist_enable(struct ispstat
*hist
, int enable
)
143 isp_reg_set(hist
->isp
, OMAP3_ISP_IOMEM_HIST
, ISPHIST_PCR
,
145 omap3isp_subclk_enable(hist
->isp
, OMAP3_ISP_SUBCLK_HIST
);
147 isp_reg_clr(hist
->isp
, OMAP3_ISP_IOMEM_HIST
, ISPHIST_PCR
,
149 omap3isp_subclk_disable(hist
->isp
, OMAP3_ISP_SUBCLK_HIST
);
153 static int hist_busy(struct ispstat
*hist
)
155 return isp_reg_readl(hist
->isp
, OMAP3_ISP_IOMEM_HIST
, ISPHIST_PCR
)
159 static void hist_dma_cb(void *data
)
161 struct ispstat
*hist
= data
;
163 /* FIXME: The DMA engine API can't report transfer errors :-/ */
165 isp_reg_clr(hist
->isp
, OMAP3_ISP_IOMEM_HIST
, ISPHIST_CNT
,
168 omap3isp_stat_dma_isr(hist
);
169 if (hist
->state
!= ISPSTAT_DISABLED
)
170 omap3isp_hist_dma_done(hist
->isp
);
173 static int hist_buf_dma(struct ispstat
*hist
)
175 dma_addr_t dma_addr
= hist
->active_buf
->dma_addr
;
176 struct dma_async_tx_descriptor
*tx
;
177 struct dma_slave_config cfg
;
181 if (unlikely(!dma_addr
)) {
182 dev_dbg(hist
->isp
->dev
, "hist: invalid DMA buffer address\n");
186 isp_reg_writel(hist
->isp
, 0, OMAP3_ISP_IOMEM_HIST
, ISPHIST_ADDR
);
187 isp_reg_set(hist
->isp
, OMAP3_ISP_IOMEM_HIST
, ISPHIST_CNT
,
189 omap3isp_flush(hist
->isp
);
191 memset(&cfg
, 0, sizeof(cfg
));
192 cfg
.src_addr
= hist
->isp
->mmio_hist_base_phys
+ ISPHIST_DATA
;
193 cfg
.src_addr_width
= DMA_SLAVE_BUSWIDTH_4_BYTES
;
194 cfg
.src_maxburst
= hist
->buf_size
/ 4;
196 ret
= dmaengine_slave_config(hist
->dma_ch
, &cfg
);
198 dev_dbg(hist
->isp
->dev
,
199 "hist: DMA slave configuration failed\n");
203 tx
= dmaengine_prep_slave_single(hist
->dma_ch
, dma_addr
,
204 hist
->buf_size
, DMA_DEV_TO_MEM
,
207 dev_dbg(hist
->isp
->dev
,
208 "hist: DMA slave preparation failed\n");
212 tx
->callback
= hist_dma_cb
;
213 tx
->callback_param
= hist
;
214 cookie
= tx
->tx_submit(tx
);
215 if (dma_submit_error(cookie
)) {
216 dev_dbg(hist
->isp
->dev
, "hist: DMA submission failed\n");
220 dma_async_issue_pending(hist
->dma_ch
);
222 return STAT_BUF_WAITING_DMA
;
225 hist_reset_mem(hist
);
229 static int hist_buf_pio(struct ispstat
*hist
)
231 struct isp_device
*isp
= hist
->isp
;
232 u32
*buf
= hist
->active_buf
->virt_addr
;
236 dev_dbg(isp
->dev
, "hist: invalid PIO buffer address\n");
237 hist_reset_mem(hist
);
241 isp_reg_writel(isp
, 0, OMAP3_ISP_IOMEM_HIST
, ISPHIST_ADDR
);
244 * By setting it, the histogram internal buffer is being cleared at the
245 * same time it's being read. This bit must be cleared just after all
248 isp_reg_set(isp
, OMAP3_ISP_IOMEM_HIST
, ISPHIST_CNT
, ISPHIST_CNT_CLEAR
);
251 * We'll read 4 times a 4-bytes-word at each iteration for
252 * optimization. It avoids 3/4 of the jumps. We also know buf_size is
255 for (i
= hist
->buf_size
/ 16; i
> 0; i
--) {
256 *buf
++ = isp_reg_readl(isp
, OMAP3_ISP_IOMEM_HIST
, ISPHIST_DATA
);
257 *buf
++ = isp_reg_readl(isp
, OMAP3_ISP_IOMEM_HIST
, ISPHIST_DATA
);
258 *buf
++ = isp_reg_readl(isp
, OMAP3_ISP_IOMEM_HIST
, ISPHIST_DATA
);
259 *buf
++ = isp_reg_readl(isp
, OMAP3_ISP_IOMEM_HIST
, ISPHIST_DATA
);
261 isp_reg_clr(hist
->isp
, OMAP3_ISP_IOMEM_HIST
, ISPHIST_CNT
,
264 return STAT_BUF_DONE
;
268 * hist_buf_process - Callback from ISP driver for HIST interrupt.
270 static int hist_buf_process(struct ispstat
*hist
)
272 struct omap3isp_hist_config
*user_cfg
= hist
->priv
;
275 if (atomic_read(&hist
->buf_err
) || hist
->state
!= ISPSTAT_ENABLED
) {
276 hist_reset_mem(hist
);
280 if (--(hist
->wait_acc_frames
))
284 ret
= hist_buf_dma(hist
);
286 ret
= hist_buf_pio(hist
);
288 hist
->wait_acc_frames
= user_cfg
->num_acc_frames
;
293 static u32
hist_get_buf_size(struct omap3isp_hist_config
*conf
)
295 return OMAP3ISP_HIST_MEM_SIZE_BINS(conf
->hist_bins
) * conf
->num_regions
;
299 * hist_validate_params - Helper function to check user given params.
300 * @new_conf: Pointer to user configuration structure.
302 * Returns 0 on success configuration.
304 static int hist_validate_params(struct ispstat
*hist
, void *new_conf
)
306 struct omap3isp_hist_config
*user_cfg
= new_conf
;
310 if (user_cfg
->cfa
> OMAP3ISP_HIST_CFA_FOVEONX3
)
313 /* Regions size and position */
315 if ((user_cfg
->num_regions
< OMAP3ISP_HIST_MIN_REGIONS
) ||
316 (user_cfg
->num_regions
> OMAP3ISP_HIST_MAX_REGIONS
))
320 for (c
= 0; c
< user_cfg
->num_regions
; c
++) {
321 if (user_cfg
->region
[c
].h_start
& ~ISPHIST_REG_START_END_MASK
)
323 if (user_cfg
->region
[c
].h_end
& ~ISPHIST_REG_START_END_MASK
)
325 if (user_cfg
->region
[c
].v_start
& ~ISPHIST_REG_START_END_MASK
)
327 if (user_cfg
->region
[c
].v_end
& ~ISPHIST_REG_START_END_MASK
)
329 if (user_cfg
->region
[c
].h_start
> user_cfg
->region
[c
].h_end
)
331 if (user_cfg
->region
[c
].v_start
> user_cfg
->region
[c
].v_end
)
335 switch (user_cfg
->num_regions
) {
337 if (user_cfg
->hist_bins
> OMAP3ISP_HIST_BINS_256
)
341 if (user_cfg
->hist_bins
> OMAP3ISP_HIST_BINS_128
)
344 default: /* 3 or 4 */
345 if (user_cfg
->hist_bins
> OMAP3ISP_HIST_BINS_64
)
350 buf_size
= hist_get_buf_size(user_cfg
);
351 if (buf_size
> user_cfg
->buf_size
)
352 /* User's buf_size request wasn't enough */
353 user_cfg
->buf_size
= buf_size
;
354 else if (user_cfg
->buf_size
> OMAP3ISP_HIST_MAX_BUF_SIZE
)
355 user_cfg
->buf_size
= OMAP3ISP_HIST_MAX_BUF_SIZE
;
360 static int hist_comp_params(struct ispstat
*hist
,
361 struct omap3isp_hist_config
*user_cfg
)
363 struct omap3isp_hist_config
*cur_cfg
= hist
->priv
;
366 if (cur_cfg
->cfa
!= user_cfg
->cfa
)
369 if (cur_cfg
->num_acc_frames
!= user_cfg
->num_acc_frames
)
372 if (cur_cfg
->hist_bins
!= user_cfg
->hist_bins
)
375 for (c
= 0; c
< OMAP3ISP_HIST_MAX_WG
; c
++) {
376 if (c
== 3 && user_cfg
->cfa
== OMAP3ISP_HIST_CFA_FOVEONX3
)
378 else if (cur_cfg
->wg
[c
] != user_cfg
->wg
[c
])
382 if (cur_cfg
->num_regions
!= user_cfg
->num_regions
)
386 for (c
= 0; c
< user_cfg
->num_regions
; c
++) {
387 if (cur_cfg
->region
[c
].h_start
!= user_cfg
->region
[c
].h_start
)
389 if (cur_cfg
->region
[c
].h_end
!= user_cfg
->region
[c
].h_end
)
391 if (cur_cfg
->region
[c
].v_start
!= user_cfg
->region
[c
].v_start
)
393 if (cur_cfg
->region
[c
].v_end
!= user_cfg
->region
[c
].v_end
)
401 * hist_update_params - Helper function to check and store user given params.
402 * @new_conf: Pointer to user configuration structure.
404 static void hist_set_params(struct ispstat
*hist
, void *new_conf
)
406 struct omap3isp_hist_config
*user_cfg
= new_conf
;
407 struct omap3isp_hist_config
*cur_cfg
= hist
->priv
;
409 if (!hist
->configured
|| hist_comp_params(hist
, user_cfg
)) {
410 memcpy(cur_cfg
, user_cfg
, sizeof(*user_cfg
));
411 if (user_cfg
->num_acc_frames
== 0)
412 user_cfg
->num_acc_frames
= 1;
416 * User might be asked for a bigger buffer than necessary for
417 * this configuration. In order to return the right amount of
418 * data during buffer request, let's calculate the size here
419 * instead of stick with user_cfg->buf_size.
421 cur_cfg
->buf_size
= hist_get_buf_size(cur_cfg
);
426 static long hist_ioctl(struct v4l2_subdev
*sd
, unsigned int cmd
, void *arg
)
428 struct ispstat
*stat
= v4l2_get_subdevdata(sd
);
431 case VIDIOC_OMAP3ISP_HIST_CFG
:
432 return omap3isp_stat_config(stat
, arg
);
433 case VIDIOC_OMAP3ISP_STAT_REQ
:
434 return omap3isp_stat_request_statistics(stat
, arg
);
435 case VIDIOC_OMAP3ISP_STAT_REQ_TIME32
:
436 return omap3isp_stat_request_statistics_time32(stat
, arg
);
437 case VIDIOC_OMAP3ISP_STAT_EN
: {
439 return omap3isp_stat_enable(stat
, !!*en
);
447 static const struct ispstat_ops hist_ops
= {
448 .validate_params
= hist_validate_params
,
449 .set_params
= hist_set_params
,
450 .setup_regs
= hist_setup_regs
,
451 .enable
= hist_enable
,
453 .buf_process
= hist_buf_process
,
456 static const struct v4l2_subdev_core_ops hist_subdev_core_ops
= {
458 .subscribe_event
= omap3isp_stat_subscribe_event
,
459 .unsubscribe_event
= omap3isp_stat_unsubscribe_event
,
462 static const struct v4l2_subdev_video_ops hist_subdev_video_ops
= {
463 .s_stream
= omap3isp_stat_s_stream
,
466 static const struct v4l2_subdev_ops hist_subdev_ops
= {
467 .core
= &hist_subdev_core_ops
,
468 .video
= &hist_subdev_video_ops
,
472 * omap3isp_hist_init - Module Initialization.
474 int omap3isp_hist_init(struct isp_device
*isp
)
476 struct ispstat
*hist
= &isp
->isp_hist
;
477 struct omap3isp_hist_config
*hist_cfg
;
480 hist_cfg
= kzalloc(sizeof(*hist_cfg
), GFP_KERNEL
);
481 if (hist_cfg
== NULL
)
486 if (HIST_CONFIG_DMA
) {
490 * We need slave capable channel without DMA request line for
491 * reading out the data.
492 * For this we can use dma_request_chan_by_mask() as we are
493 * happy with any channel as long as it is capable of slave
497 dma_cap_set(DMA_SLAVE
, mask
);
498 hist
->dma_ch
= dma_request_chan_by_mask(&mask
);
499 if (IS_ERR(hist
->dma_ch
)) {
500 ret
= PTR_ERR(hist
->dma_ch
);
501 if (ret
== -EPROBE_DEFER
)
506 "hist: DMA channel request failed, using PIO\n");
508 dev_dbg(isp
->dev
, "hist: using DMA channel %s\n",
509 dma_chan_name(hist
->dma_ch
));
513 hist
->ops
= &hist_ops
;
514 hist
->priv
= hist_cfg
;
515 hist
->event_type
= V4L2_EVENT_OMAP3ISP_HIST
;
517 ret
= omap3isp_stat_init(hist
, "histogram", &hist_subdev_ops
);
521 if (!IS_ERR_OR_NULL(hist
->dma_ch
))
522 dma_release_channel(hist
->dma_ch
);
530 * omap3isp_hist_cleanup - Module cleanup.
532 void omap3isp_hist_cleanup(struct isp_device
*isp
)
534 struct ispstat
*hist
= &isp
->isp_hist
;
537 dma_release_channel(hist
->dma_ch
);
539 omap3isp_stat_cleanup(hist
);