162306a36Sopenharmony_ci// SPDX-License-Identifier: (GPL-2.0+ OR MIT) 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Rockchip ISP1 Driver - Stats subdevice 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2017 Rockchip Electronics Co., Ltd. 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <media/v4l2-common.h> 962306a36Sopenharmony_ci#include <media/v4l2-event.h> 1062306a36Sopenharmony_ci#include <media/v4l2-ioctl.h> 1162306a36Sopenharmony_ci#include <media/videobuf2-core.h> 1262306a36Sopenharmony_ci#include <media/videobuf2-vmalloc.h> /* for ISP statistics */ 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci#include "rkisp1-common.h" 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci#define RKISP1_STATS_DEV_NAME RKISP1_DRIVER_NAME "_stats" 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci#define RKISP1_ISP_STATS_REQ_BUFS_MIN 2 1962306a36Sopenharmony_ci#define RKISP1_ISP_STATS_REQ_BUFS_MAX 8 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_cistatic int rkisp1_stats_enum_fmt_meta_cap(struct file *file, void *priv, 2262306a36Sopenharmony_ci struct v4l2_fmtdesc *f) 2362306a36Sopenharmony_ci{ 2462306a36Sopenharmony_ci struct video_device *video = video_devdata(file); 2562306a36Sopenharmony_ci struct rkisp1_stats *stats = video_get_drvdata(video); 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci if (f->index > 0 || f->type != video->queue->type) 2862306a36Sopenharmony_ci return -EINVAL; 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci f->pixelformat = stats->vdev_fmt.fmt.meta.dataformat; 3162306a36Sopenharmony_ci return 0; 3262306a36Sopenharmony_ci} 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_cistatic int rkisp1_stats_g_fmt_meta_cap(struct file *file, void *priv, 3562306a36Sopenharmony_ci struct v4l2_format *f) 3662306a36Sopenharmony_ci{ 3762306a36Sopenharmony_ci struct video_device *video = video_devdata(file); 3862306a36Sopenharmony_ci struct rkisp1_stats *stats = video_get_drvdata(video); 3962306a36Sopenharmony_ci struct v4l2_meta_format *meta = &f->fmt.meta; 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci if (f->type != video->queue->type) 4262306a36Sopenharmony_ci return -EINVAL; 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci memset(meta, 0, sizeof(*meta)); 4562306a36Sopenharmony_ci meta->dataformat = stats->vdev_fmt.fmt.meta.dataformat; 4662306a36Sopenharmony_ci meta->buffersize = stats->vdev_fmt.fmt.meta.buffersize; 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci return 0; 4962306a36Sopenharmony_ci} 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_cistatic int rkisp1_stats_querycap(struct file *file, 5262306a36Sopenharmony_ci void *priv, struct v4l2_capability *cap) 5362306a36Sopenharmony_ci{ 5462306a36Sopenharmony_ci struct video_device *vdev = video_devdata(file); 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci strscpy(cap->driver, RKISP1_DRIVER_NAME, sizeof(cap->driver)); 5762306a36Sopenharmony_ci strscpy(cap->card, vdev->name, sizeof(cap->card)); 5862306a36Sopenharmony_ci strscpy(cap->bus_info, RKISP1_BUS_INFO, sizeof(cap->bus_info)); 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci return 0; 6162306a36Sopenharmony_ci} 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci/* ISP video device IOCTLs */ 6462306a36Sopenharmony_cistatic const struct v4l2_ioctl_ops rkisp1_stats_ioctl = { 6562306a36Sopenharmony_ci .vidioc_reqbufs = vb2_ioctl_reqbufs, 6662306a36Sopenharmony_ci .vidioc_querybuf = vb2_ioctl_querybuf, 6762306a36Sopenharmony_ci .vidioc_create_bufs = vb2_ioctl_create_bufs, 6862306a36Sopenharmony_ci .vidioc_qbuf = vb2_ioctl_qbuf, 6962306a36Sopenharmony_ci .vidioc_dqbuf = vb2_ioctl_dqbuf, 7062306a36Sopenharmony_ci .vidioc_prepare_buf = vb2_ioctl_prepare_buf, 7162306a36Sopenharmony_ci .vidioc_expbuf = vb2_ioctl_expbuf, 7262306a36Sopenharmony_ci .vidioc_streamon = vb2_ioctl_streamon, 7362306a36Sopenharmony_ci .vidioc_streamoff = vb2_ioctl_streamoff, 7462306a36Sopenharmony_ci .vidioc_enum_fmt_meta_cap = rkisp1_stats_enum_fmt_meta_cap, 7562306a36Sopenharmony_ci .vidioc_g_fmt_meta_cap = rkisp1_stats_g_fmt_meta_cap, 7662306a36Sopenharmony_ci .vidioc_s_fmt_meta_cap = rkisp1_stats_g_fmt_meta_cap, 7762306a36Sopenharmony_ci .vidioc_try_fmt_meta_cap = rkisp1_stats_g_fmt_meta_cap, 7862306a36Sopenharmony_ci .vidioc_querycap = rkisp1_stats_querycap, 7962306a36Sopenharmony_ci .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, 8062306a36Sopenharmony_ci .vidioc_unsubscribe_event = v4l2_event_unsubscribe, 8162306a36Sopenharmony_ci}; 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_cistatic const struct v4l2_file_operations rkisp1_stats_fops = { 8462306a36Sopenharmony_ci .mmap = vb2_fop_mmap, 8562306a36Sopenharmony_ci .unlocked_ioctl = video_ioctl2, 8662306a36Sopenharmony_ci .poll = vb2_fop_poll, 8762306a36Sopenharmony_ci .open = v4l2_fh_open, 8862306a36Sopenharmony_ci .release = vb2_fop_release 8962306a36Sopenharmony_ci}; 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_cistatic int rkisp1_stats_vb2_queue_setup(struct vb2_queue *vq, 9262306a36Sopenharmony_ci unsigned int *num_buffers, 9362306a36Sopenharmony_ci unsigned int *num_planes, 9462306a36Sopenharmony_ci unsigned int sizes[], 9562306a36Sopenharmony_ci struct device *alloc_devs[]) 9662306a36Sopenharmony_ci{ 9762306a36Sopenharmony_ci *num_planes = 1; 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci *num_buffers = clamp_t(u32, *num_buffers, RKISP1_ISP_STATS_REQ_BUFS_MIN, 10062306a36Sopenharmony_ci RKISP1_ISP_STATS_REQ_BUFS_MAX); 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci sizes[0] = sizeof(struct rkisp1_stat_buffer); 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci return 0; 10562306a36Sopenharmony_ci} 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_cistatic void rkisp1_stats_vb2_buf_queue(struct vb2_buffer *vb) 10862306a36Sopenharmony_ci{ 10962306a36Sopenharmony_ci struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 11062306a36Sopenharmony_ci struct rkisp1_buffer *stats_buf = 11162306a36Sopenharmony_ci container_of(vbuf, struct rkisp1_buffer, vb); 11262306a36Sopenharmony_ci struct vb2_queue *vq = vb->vb2_queue; 11362306a36Sopenharmony_ci struct rkisp1_stats *stats_dev = vq->drv_priv; 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci spin_lock_irq(&stats_dev->lock); 11762306a36Sopenharmony_ci list_add_tail(&stats_buf->queue, &stats_dev->stat); 11862306a36Sopenharmony_ci spin_unlock_irq(&stats_dev->lock); 11962306a36Sopenharmony_ci} 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_cistatic int rkisp1_stats_vb2_buf_prepare(struct vb2_buffer *vb) 12262306a36Sopenharmony_ci{ 12362306a36Sopenharmony_ci if (vb2_plane_size(vb, 0) < sizeof(struct rkisp1_stat_buffer)) 12462306a36Sopenharmony_ci return -EINVAL; 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci vb2_set_plane_payload(vb, 0, sizeof(struct rkisp1_stat_buffer)); 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci return 0; 12962306a36Sopenharmony_ci} 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_cistatic void rkisp1_stats_vb2_stop_streaming(struct vb2_queue *vq) 13262306a36Sopenharmony_ci{ 13362306a36Sopenharmony_ci struct rkisp1_stats *stats = vq->drv_priv; 13462306a36Sopenharmony_ci struct rkisp1_buffer *buf; 13562306a36Sopenharmony_ci unsigned int i; 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci spin_lock_irq(&stats->lock); 13862306a36Sopenharmony_ci for (i = 0; i < RKISP1_ISP_STATS_REQ_BUFS_MAX; i++) { 13962306a36Sopenharmony_ci if (list_empty(&stats->stat)) 14062306a36Sopenharmony_ci break; 14162306a36Sopenharmony_ci buf = list_first_entry(&stats->stat, 14262306a36Sopenharmony_ci struct rkisp1_buffer, queue); 14362306a36Sopenharmony_ci list_del(&buf->queue); 14462306a36Sopenharmony_ci vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); 14562306a36Sopenharmony_ci } 14662306a36Sopenharmony_ci spin_unlock_irq(&stats->lock); 14762306a36Sopenharmony_ci} 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_cistatic const struct vb2_ops rkisp1_stats_vb2_ops = { 15062306a36Sopenharmony_ci .queue_setup = rkisp1_stats_vb2_queue_setup, 15162306a36Sopenharmony_ci .buf_queue = rkisp1_stats_vb2_buf_queue, 15262306a36Sopenharmony_ci .buf_prepare = rkisp1_stats_vb2_buf_prepare, 15362306a36Sopenharmony_ci .wait_prepare = vb2_ops_wait_prepare, 15462306a36Sopenharmony_ci .wait_finish = vb2_ops_wait_finish, 15562306a36Sopenharmony_ci .stop_streaming = rkisp1_stats_vb2_stop_streaming, 15662306a36Sopenharmony_ci}; 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_cistatic int 15962306a36Sopenharmony_cirkisp1_stats_init_vb2_queue(struct vb2_queue *q, struct rkisp1_stats *stats) 16062306a36Sopenharmony_ci{ 16162306a36Sopenharmony_ci struct rkisp1_vdev_node *node; 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci node = container_of(q, struct rkisp1_vdev_node, buf_queue); 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci q->type = V4L2_BUF_TYPE_META_CAPTURE; 16662306a36Sopenharmony_ci q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; 16762306a36Sopenharmony_ci q->drv_priv = stats; 16862306a36Sopenharmony_ci q->ops = &rkisp1_stats_vb2_ops; 16962306a36Sopenharmony_ci q->mem_ops = &vb2_vmalloc_memops; 17062306a36Sopenharmony_ci q->buf_struct_size = sizeof(struct rkisp1_buffer); 17162306a36Sopenharmony_ci q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; 17262306a36Sopenharmony_ci q->lock = &node->vlock; 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci return vb2_queue_init(q); 17562306a36Sopenharmony_ci} 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_cistatic void rkisp1_stats_get_awb_meas_v10(struct rkisp1_stats *stats, 17862306a36Sopenharmony_ci struct rkisp1_stat_buffer *pbuf) 17962306a36Sopenharmony_ci{ 18062306a36Sopenharmony_ci /* Protect against concurrent access from ISR? */ 18162306a36Sopenharmony_ci struct rkisp1_device *rkisp1 = stats->rkisp1; 18262306a36Sopenharmony_ci u32 reg_val; 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci pbuf->meas_type |= RKISP1_CIF_ISP_STAT_AWB; 18562306a36Sopenharmony_ci reg_val = rkisp1_read(rkisp1, RKISP1_CIF_ISP_AWB_WHITE_CNT_V10); 18662306a36Sopenharmony_ci pbuf->params.awb.awb_mean[0].cnt = 18762306a36Sopenharmony_ci RKISP1_CIF_ISP_AWB_GET_PIXEL_CNT(reg_val); 18862306a36Sopenharmony_ci reg_val = rkisp1_read(rkisp1, RKISP1_CIF_ISP_AWB_MEAN_V10); 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci pbuf->params.awb.awb_mean[0].mean_cr_or_r = 19162306a36Sopenharmony_ci RKISP1_CIF_ISP_AWB_GET_MEAN_CR_R(reg_val); 19262306a36Sopenharmony_ci pbuf->params.awb.awb_mean[0].mean_cb_or_b = 19362306a36Sopenharmony_ci RKISP1_CIF_ISP_AWB_GET_MEAN_CB_B(reg_val); 19462306a36Sopenharmony_ci pbuf->params.awb.awb_mean[0].mean_y_or_g = 19562306a36Sopenharmony_ci RKISP1_CIF_ISP_AWB_GET_MEAN_Y_G(reg_val); 19662306a36Sopenharmony_ci} 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_cistatic void rkisp1_stats_get_awb_meas_v12(struct rkisp1_stats *stats, 19962306a36Sopenharmony_ci struct rkisp1_stat_buffer *pbuf) 20062306a36Sopenharmony_ci{ 20162306a36Sopenharmony_ci /* Protect against concurrent access from ISR? */ 20262306a36Sopenharmony_ci struct rkisp1_device *rkisp1 = stats->rkisp1; 20362306a36Sopenharmony_ci u32 reg_val; 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci pbuf->meas_type |= RKISP1_CIF_ISP_STAT_AWB; 20662306a36Sopenharmony_ci reg_val = rkisp1_read(rkisp1, RKISP1_CIF_ISP_AWB_WHITE_CNT_V12); 20762306a36Sopenharmony_ci pbuf->params.awb.awb_mean[0].cnt = 20862306a36Sopenharmony_ci RKISP1_CIF_ISP_AWB_GET_PIXEL_CNT(reg_val); 20962306a36Sopenharmony_ci reg_val = rkisp1_read(rkisp1, RKISP1_CIF_ISP_AWB_MEAN_V12); 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ci pbuf->params.awb.awb_mean[0].mean_cr_or_r = 21262306a36Sopenharmony_ci RKISP1_CIF_ISP_AWB_GET_MEAN_CR_R(reg_val); 21362306a36Sopenharmony_ci pbuf->params.awb.awb_mean[0].mean_cb_or_b = 21462306a36Sopenharmony_ci RKISP1_CIF_ISP_AWB_GET_MEAN_CB_B(reg_val); 21562306a36Sopenharmony_ci pbuf->params.awb.awb_mean[0].mean_y_or_g = 21662306a36Sopenharmony_ci RKISP1_CIF_ISP_AWB_GET_MEAN_Y_G(reg_val); 21762306a36Sopenharmony_ci} 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_cistatic void rkisp1_stats_get_aec_meas_v10(struct rkisp1_stats *stats, 22062306a36Sopenharmony_ci struct rkisp1_stat_buffer *pbuf) 22162306a36Sopenharmony_ci{ 22262306a36Sopenharmony_ci struct rkisp1_device *rkisp1 = stats->rkisp1; 22362306a36Sopenharmony_ci unsigned int i; 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci pbuf->meas_type |= RKISP1_CIF_ISP_STAT_AUTOEXP; 22662306a36Sopenharmony_ci for (i = 0; i < RKISP1_CIF_ISP_AE_MEAN_MAX_V10; i++) 22762306a36Sopenharmony_ci pbuf->params.ae.exp_mean[i] = 22862306a36Sopenharmony_ci (u8)rkisp1_read(rkisp1, 22962306a36Sopenharmony_ci RKISP1_CIF_ISP_EXP_MEAN_00_V10 + i * 4); 23062306a36Sopenharmony_ci} 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_cistatic void rkisp1_stats_get_aec_meas_v12(struct rkisp1_stats *stats, 23362306a36Sopenharmony_ci struct rkisp1_stat_buffer *pbuf) 23462306a36Sopenharmony_ci{ 23562306a36Sopenharmony_ci struct rkisp1_device *rkisp1 = stats->rkisp1; 23662306a36Sopenharmony_ci u32 value; 23762306a36Sopenharmony_ci int i; 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci pbuf->meas_type |= RKISP1_CIF_ISP_STAT_AUTOEXP; 24062306a36Sopenharmony_ci for (i = 0; i < RKISP1_CIF_ISP_AE_MEAN_MAX_V12 / 4; i++) { 24162306a36Sopenharmony_ci value = rkisp1_read(rkisp1, RKISP1_CIF_ISP_EXP_MEAN_V12 + i * 4); 24262306a36Sopenharmony_ci pbuf->params.ae.exp_mean[4 * i + 0] = 24362306a36Sopenharmony_ci RKISP1_CIF_ISP_EXP_GET_MEAN_xy0_V12(value); 24462306a36Sopenharmony_ci pbuf->params.ae.exp_mean[4 * i + 1] = 24562306a36Sopenharmony_ci RKISP1_CIF_ISP_EXP_GET_MEAN_xy1_V12(value); 24662306a36Sopenharmony_ci pbuf->params.ae.exp_mean[4 * i + 2] = 24762306a36Sopenharmony_ci RKISP1_CIF_ISP_EXP_GET_MEAN_xy2_V12(value); 24862306a36Sopenharmony_ci pbuf->params.ae.exp_mean[4 * i + 3] = 24962306a36Sopenharmony_ci RKISP1_CIF_ISP_EXP_GET_MEAN_xy3_V12(value); 25062306a36Sopenharmony_ci } 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci value = rkisp1_read(rkisp1, RKISP1_CIF_ISP_EXP_MEAN_V12 + i * 4); 25362306a36Sopenharmony_ci pbuf->params.ae.exp_mean[4 * i + 0] = RKISP1_CIF_ISP_EXP_GET_MEAN_xy0_V12(value); 25462306a36Sopenharmony_ci} 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_cistatic void rkisp1_stats_get_afc_meas(struct rkisp1_stats *stats, 25762306a36Sopenharmony_ci struct rkisp1_stat_buffer *pbuf) 25862306a36Sopenharmony_ci{ 25962306a36Sopenharmony_ci struct rkisp1_device *rkisp1 = stats->rkisp1; 26062306a36Sopenharmony_ci struct rkisp1_cif_isp_af_stat *af; 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci pbuf->meas_type |= RKISP1_CIF_ISP_STAT_AFM; 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_ci af = &pbuf->params.af; 26562306a36Sopenharmony_ci af->window[0].sum = rkisp1_read(rkisp1, RKISP1_CIF_ISP_AFM_SUM_A); 26662306a36Sopenharmony_ci af->window[0].lum = rkisp1_read(rkisp1, RKISP1_CIF_ISP_AFM_LUM_A); 26762306a36Sopenharmony_ci af->window[1].sum = rkisp1_read(rkisp1, RKISP1_CIF_ISP_AFM_SUM_B); 26862306a36Sopenharmony_ci af->window[1].lum = rkisp1_read(rkisp1, RKISP1_CIF_ISP_AFM_LUM_B); 26962306a36Sopenharmony_ci af->window[2].sum = rkisp1_read(rkisp1, RKISP1_CIF_ISP_AFM_SUM_C); 27062306a36Sopenharmony_ci af->window[2].lum = rkisp1_read(rkisp1, RKISP1_CIF_ISP_AFM_LUM_C); 27162306a36Sopenharmony_ci} 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_cistatic void rkisp1_stats_get_hst_meas_v10(struct rkisp1_stats *stats, 27462306a36Sopenharmony_ci struct rkisp1_stat_buffer *pbuf) 27562306a36Sopenharmony_ci{ 27662306a36Sopenharmony_ci struct rkisp1_device *rkisp1 = stats->rkisp1; 27762306a36Sopenharmony_ci unsigned int i; 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci pbuf->meas_type |= RKISP1_CIF_ISP_STAT_HIST; 28062306a36Sopenharmony_ci for (i = 0; i < RKISP1_CIF_ISP_HIST_BIN_N_MAX_V10; i++) { 28162306a36Sopenharmony_ci u32 reg_val = rkisp1_read(rkisp1, RKISP1_CIF_ISP_HIST_BIN_0_V10 + i * 4); 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ci pbuf->params.hist.hist_bins[i] = RKISP1_CIF_ISP_HIST_GET_BIN_V10(reg_val); 28462306a36Sopenharmony_ci } 28562306a36Sopenharmony_ci} 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_cistatic void rkisp1_stats_get_hst_meas_v12(struct rkisp1_stats *stats, 28862306a36Sopenharmony_ci struct rkisp1_stat_buffer *pbuf) 28962306a36Sopenharmony_ci{ 29062306a36Sopenharmony_ci struct rkisp1_device *rkisp1 = stats->rkisp1; 29162306a36Sopenharmony_ci u32 value; 29262306a36Sopenharmony_ci int i; 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_ci pbuf->meas_type |= RKISP1_CIF_ISP_STAT_HIST; 29562306a36Sopenharmony_ci for (i = 0; i < RKISP1_CIF_ISP_HIST_BIN_N_MAX_V12 / 2; i++) { 29662306a36Sopenharmony_ci value = rkisp1_read(rkisp1, RKISP1_CIF_ISP_HIST_BIN_V12 + i * 4); 29762306a36Sopenharmony_ci pbuf->params.hist.hist_bins[2 * i] = 29862306a36Sopenharmony_ci RKISP1_CIF_ISP_HIST_GET_BIN0_V12(value); 29962306a36Sopenharmony_ci pbuf->params.hist.hist_bins[2 * i + 1] = 30062306a36Sopenharmony_ci RKISP1_CIF_ISP_HIST_GET_BIN1_V12(value); 30162306a36Sopenharmony_ci } 30262306a36Sopenharmony_ci} 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_cistatic void rkisp1_stats_get_bls_meas(struct rkisp1_stats *stats, 30562306a36Sopenharmony_ci struct rkisp1_stat_buffer *pbuf) 30662306a36Sopenharmony_ci{ 30762306a36Sopenharmony_ci struct rkisp1_device *rkisp1 = stats->rkisp1; 30862306a36Sopenharmony_ci const struct rkisp1_mbus_info *in_fmt = rkisp1->isp.sink_fmt; 30962306a36Sopenharmony_ci struct rkisp1_cif_isp_bls_meas_val *bls_val; 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_ci bls_val = &pbuf->params.ae.bls_val; 31262306a36Sopenharmony_ci if (in_fmt->bayer_pat == RKISP1_RAW_BGGR) { 31362306a36Sopenharmony_ci bls_val->meas_b = 31462306a36Sopenharmony_ci rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_A_MEASURED); 31562306a36Sopenharmony_ci bls_val->meas_gb = 31662306a36Sopenharmony_ci rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_B_MEASURED); 31762306a36Sopenharmony_ci bls_val->meas_gr = 31862306a36Sopenharmony_ci rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_C_MEASURED); 31962306a36Sopenharmony_ci bls_val->meas_r = 32062306a36Sopenharmony_ci rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_D_MEASURED); 32162306a36Sopenharmony_ci } else if (in_fmt->bayer_pat == RKISP1_RAW_GBRG) { 32262306a36Sopenharmony_ci bls_val->meas_gb = 32362306a36Sopenharmony_ci rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_A_MEASURED); 32462306a36Sopenharmony_ci bls_val->meas_b = 32562306a36Sopenharmony_ci rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_B_MEASURED); 32662306a36Sopenharmony_ci bls_val->meas_r = 32762306a36Sopenharmony_ci rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_C_MEASURED); 32862306a36Sopenharmony_ci bls_val->meas_gr = 32962306a36Sopenharmony_ci rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_D_MEASURED); 33062306a36Sopenharmony_ci } else if (in_fmt->bayer_pat == RKISP1_RAW_GRBG) { 33162306a36Sopenharmony_ci bls_val->meas_gr = 33262306a36Sopenharmony_ci rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_A_MEASURED); 33362306a36Sopenharmony_ci bls_val->meas_r = 33462306a36Sopenharmony_ci rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_B_MEASURED); 33562306a36Sopenharmony_ci bls_val->meas_b = 33662306a36Sopenharmony_ci rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_C_MEASURED); 33762306a36Sopenharmony_ci bls_val->meas_gb = 33862306a36Sopenharmony_ci rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_D_MEASURED); 33962306a36Sopenharmony_ci } else if (in_fmt->bayer_pat == RKISP1_RAW_RGGB) { 34062306a36Sopenharmony_ci bls_val->meas_r = 34162306a36Sopenharmony_ci rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_A_MEASURED); 34262306a36Sopenharmony_ci bls_val->meas_gr = 34362306a36Sopenharmony_ci rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_B_MEASURED); 34462306a36Sopenharmony_ci bls_val->meas_gb = 34562306a36Sopenharmony_ci rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_C_MEASURED); 34662306a36Sopenharmony_ci bls_val->meas_b = 34762306a36Sopenharmony_ci rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_D_MEASURED); 34862306a36Sopenharmony_ci } 34962306a36Sopenharmony_ci} 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_cistatic const struct rkisp1_stats_ops rkisp1_v10_stats_ops = { 35262306a36Sopenharmony_ci .get_awb_meas = rkisp1_stats_get_awb_meas_v10, 35362306a36Sopenharmony_ci .get_aec_meas = rkisp1_stats_get_aec_meas_v10, 35462306a36Sopenharmony_ci .get_hst_meas = rkisp1_stats_get_hst_meas_v10, 35562306a36Sopenharmony_ci}; 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_cistatic struct rkisp1_stats_ops rkisp1_v12_stats_ops = { 35862306a36Sopenharmony_ci .get_awb_meas = rkisp1_stats_get_awb_meas_v12, 35962306a36Sopenharmony_ci .get_aec_meas = rkisp1_stats_get_aec_meas_v12, 36062306a36Sopenharmony_ci .get_hst_meas = rkisp1_stats_get_hst_meas_v12, 36162306a36Sopenharmony_ci}; 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_cistatic void 36462306a36Sopenharmony_cirkisp1_stats_send_measurement(struct rkisp1_stats *stats, u32 isp_ris) 36562306a36Sopenharmony_ci{ 36662306a36Sopenharmony_ci struct rkisp1_stat_buffer *cur_stat_buf; 36762306a36Sopenharmony_ci struct rkisp1_buffer *cur_buf = NULL; 36862306a36Sopenharmony_ci unsigned int frame_sequence = stats->rkisp1->isp.frame_sequence; 36962306a36Sopenharmony_ci u64 timestamp = ktime_get_ns(); 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ci /* get one empty buffer */ 37262306a36Sopenharmony_ci if (!list_empty(&stats->stat)) { 37362306a36Sopenharmony_ci cur_buf = list_first_entry(&stats->stat, 37462306a36Sopenharmony_ci struct rkisp1_buffer, queue); 37562306a36Sopenharmony_ci list_del(&cur_buf->queue); 37662306a36Sopenharmony_ci } 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_ci if (!cur_buf) 37962306a36Sopenharmony_ci return; 38062306a36Sopenharmony_ci 38162306a36Sopenharmony_ci cur_stat_buf = (struct rkisp1_stat_buffer *) 38262306a36Sopenharmony_ci vb2_plane_vaddr(&cur_buf->vb.vb2_buf, 0); 38362306a36Sopenharmony_ci if (isp_ris & RKISP1_CIF_ISP_AWB_DONE) 38462306a36Sopenharmony_ci stats->ops->get_awb_meas(stats, cur_stat_buf); 38562306a36Sopenharmony_ci 38662306a36Sopenharmony_ci if (isp_ris & RKISP1_CIF_ISP_AFM_FIN) 38762306a36Sopenharmony_ci rkisp1_stats_get_afc_meas(stats, cur_stat_buf); 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_ci if (isp_ris & RKISP1_CIF_ISP_EXP_END) { 39062306a36Sopenharmony_ci stats->ops->get_aec_meas(stats, cur_stat_buf); 39162306a36Sopenharmony_ci rkisp1_stats_get_bls_meas(stats, cur_stat_buf); 39262306a36Sopenharmony_ci } 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci if (isp_ris & RKISP1_CIF_ISP_HIST_MEASURE_RDY) 39562306a36Sopenharmony_ci stats->ops->get_hst_meas(stats, cur_stat_buf); 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_ci vb2_set_plane_payload(&cur_buf->vb.vb2_buf, 0, 39862306a36Sopenharmony_ci sizeof(struct rkisp1_stat_buffer)); 39962306a36Sopenharmony_ci cur_buf->vb.sequence = frame_sequence; 40062306a36Sopenharmony_ci cur_buf->vb.vb2_buf.timestamp = timestamp; 40162306a36Sopenharmony_ci vb2_buffer_done(&cur_buf->vb.vb2_buf, VB2_BUF_STATE_DONE); 40262306a36Sopenharmony_ci} 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_civoid rkisp1_stats_isr(struct rkisp1_stats *stats, u32 isp_ris) 40562306a36Sopenharmony_ci{ 40662306a36Sopenharmony_ci struct rkisp1_device *rkisp1 = stats->rkisp1; 40762306a36Sopenharmony_ci unsigned int isp_mis_tmp = 0; 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_ci spin_lock(&stats->lock); 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_ci rkisp1_write(rkisp1, RKISP1_CIF_ISP_ICR, RKISP1_STATS_MEAS_MASK); 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_ci isp_mis_tmp = rkisp1_read(rkisp1, RKISP1_CIF_ISP_MIS); 41462306a36Sopenharmony_ci if (isp_mis_tmp & RKISP1_STATS_MEAS_MASK) 41562306a36Sopenharmony_ci rkisp1->debug.stats_error++; 41662306a36Sopenharmony_ci 41762306a36Sopenharmony_ci if (isp_ris & RKISP1_STATS_MEAS_MASK) 41862306a36Sopenharmony_ci rkisp1_stats_send_measurement(stats, isp_ris); 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_ci spin_unlock(&stats->lock); 42162306a36Sopenharmony_ci} 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_cistatic void rkisp1_init_stats(struct rkisp1_stats *stats) 42462306a36Sopenharmony_ci{ 42562306a36Sopenharmony_ci stats->vdev_fmt.fmt.meta.dataformat = 42662306a36Sopenharmony_ci V4L2_META_FMT_RK_ISP1_STAT_3A; 42762306a36Sopenharmony_ci stats->vdev_fmt.fmt.meta.buffersize = 42862306a36Sopenharmony_ci sizeof(struct rkisp1_stat_buffer); 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_ci if (stats->rkisp1->info->isp_ver == RKISP1_V12) 43162306a36Sopenharmony_ci stats->ops = &rkisp1_v12_stats_ops; 43262306a36Sopenharmony_ci else 43362306a36Sopenharmony_ci stats->ops = &rkisp1_v10_stats_ops; 43462306a36Sopenharmony_ci} 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_ciint rkisp1_stats_register(struct rkisp1_device *rkisp1) 43762306a36Sopenharmony_ci{ 43862306a36Sopenharmony_ci struct rkisp1_stats *stats = &rkisp1->stats; 43962306a36Sopenharmony_ci struct rkisp1_vdev_node *node = &stats->vnode; 44062306a36Sopenharmony_ci struct video_device *vdev = &node->vdev; 44162306a36Sopenharmony_ci int ret; 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_ci stats->rkisp1 = rkisp1; 44462306a36Sopenharmony_ci mutex_init(&node->vlock); 44562306a36Sopenharmony_ci INIT_LIST_HEAD(&stats->stat); 44662306a36Sopenharmony_ci spin_lock_init(&stats->lock); 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_ci strscpy(vdev->name, RKISP1_STATS_DEV_NAME, sizeof(vdev->name)); 44962306a36Sopenharmony_ci 45062306a36Sopenharmony_ci video_set_drvdata(vdev, stats); 45162306a36Sopenharmony_ci vdev->ioctl_ops = &rkisp1_stats_ioctl; 45262306a36Sopenharmony_ci vdev->fops = &rkisp1_stats_fops; 45362306a36Sopenharmony_ci vdev->release = video_device_release_empty; 45462306a36Sopenharmony_ci vdev->lock = &node->vlock; 45562306a36Sopenharmony_ci vdev->v4l2_dev = &rkisp1->v4l2_dev; 45662306a36Sopenharmony_ci vdev->queue = &node->buf_queue; 45762306a36Sopenharmony_ci vdev->device_caps = V4L2_CAP_META_CAPTURE | V4L2_CAP_STREAMING; 45862306a36Sopenharmony_ci vdev->vfl_dir = VFL_DIR_RX; 45962306a36Sopenharmony_ci rkisp1_stats_init_vb2_queue(vdev->queue, stats); 46062306a36Sopenharmony_ci rkisp1_init_stats(stats); 46162306a36Sopenharmony_ci video_set_drvdata(vdev, stats); 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_ci node->pad.flags = MEDIA_PAD_FL_SINK; 46462306a36Sopenharmony_ci ret = media_entity_pads_init(&vdev->entity, 1, &node->pad); 46562306a36Sopenharmony_ci if (ret) 46662306a36Sopenharmony_ci goto error; 46762306a36Sopenharmony_ci 46862306a36Sopenharmony_ci ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1); 46962306a36Sopenharmony_ci if (ret) { 47062306a36Sopenharmony_ci dev_err(&vdev->dev, 47162306a36Sopenharmony_ci "failed to register %s, ret=%d\n", vdev->name, ret); 47262306a36Sopenharmony_ci goto error; 47362306a36Sopenharmony_ci } 47462306a36Sopenharmony_ci 47562306a36Sopenharmony_ci return 0; 47662306a36Sopenharmony_ci 47762306a36Sopenharmony_cierror: 47862306a36Sopenharmony_ci media_entity_cleanup(&vdev->entity); 47962306a36Sopenharmony_ci mutex_destroy(&node->vlock); 48062306a36Sopenharmony_ci stats->rkisp1 = NULL; 48162306a36Sopenharmony_ci return ret; 48262306a36Sopenharmony_ci} 48362306a36Sopenharmony_ci 48462306a36Sopenharmony_civoid rkisp1_stats_unregister(struct rkisp1_device *rkisp1) 48562306a36Sopenharmony_ci{ 48662306a36Sopenharmony_ci struct rkisp1_stats *stats = &rkisp1->stats; 48762306a36Sopenharmony_ci struct rkisp1_vdev_node *node = &stats->vnode; 48862306a36Sopenharmony_ci struct video_device *vdev = &node->vdev; 48962306a36Sopenharmony_ci 49062306a36Sopenharmony_ci if (!stats->rkisp1) 49162306a36Sopenharmony_ci return; 49262306a36Sopenharmony_ci 49362306a36Sopenharmony_ci vb2_video_unregister_device(vdev); 49462306a36Sopenharmony_ci media_entity_cleanup(&vdev->entity); 49562306a36Sopenharmony_ci mutex_destroy(&node->vlock); 49662306a36Sopenharmony_ci} 497