1 // SPDX-License-Identifier: (GPL-2.0-only OR MIT) 2 /* 3 * Copyright (C) 2024 Amlogic, Inc. All rights reserved 4 */ 5 6 #include <linux/cleanup.h> 7 #include <linux/media/amlogic/c3-isp-config.h> 8 #include <linux/pm_runtime.h> 9 10 #include <media/v4l2-ioctl.h> 11 #include <media/v4l2-mc.h> 12 #include <media/videobuf2-dma-contig.h> 13 14 #include "c3-isp-common.h" 15 #include "c3-isp-regs.h" 16 17 /* Hardware configuration */ 18 19 static void c3_isp_stats_cfg_dmawr_addr(struct c3_isp_stats *stats) 20 { 21 u32 awb_dma_size = sizeof(struct c3_isp_awb_stats); 22 u32 ae_dma_size = sizeof(struct c3_isp_ae_stats); 23 u32 awb_dma_addr = stats->buff->dma_addr; 24 u32 af_dma_addr; 25 u32 ae_dma_addr; 26 27 ae_dma_addr = awb_dma_addr + awb_dma_size; 28 af_dma_addr = ae_dma_addr + ae_dma_size; 29 30 c3_isp_update_bits(stats->isp, VIU_DMAWR_BADDR0, 31 VIU_DMAWR_BADDR0_AF_STATS_BASE_ADDR_MASK, 32 VIU_DMAWR_BADDR0_AF_STATS_BASE_ADDR(af_dma_addr)); 33 34 c3_isp_update_bits(stats->isp, VIU_DMAWR_BADDR1, 35 VIU_DMAWR_BADDR1_AWB_STATS_BASE_ADDR_MASK, 36 VIU_DMAWR_BADDR1_AWB_STATS_BASE_ADDR(awb_dma_addr)); 37 38 c3_isp_update_bits(stats->isp, VIU_DMAWR_BADDR2, 39 VIU_DMAWR_BADDR2_AE_STATS_BASE_ADDR_MASK, 40 VIU_DMAWR_BADDR2_AE_STATS_BASE_ADDR(ae_dma_addr)); 41 } 42 43 static void c3_isp_stats_cfg_buff(struct c3_isp_stats *stats) 44 { 45 stats->buff = 46 list_first_entry_or_null(&stats->pending, 47 struct c3_isp_stats_buffer, list); 48 if (stats->buff) { 49 c3_isp_stats_cfg_dmawr_addr(stats); 50 list_del(&stats->buff->list); 51 } 52 } 53 54 void c3_isp_stats_pre_cfg(struct c3_isp_device *isp) 55 { 56 struct c3_isp_stats *stats = &isp->stats; 57 u32 dma_size; 58 59 c3_isp_update_bits(stats->isp, ISP_AF_EN_CTRL, 60 ISP_AF_EN_CTRL_STAT_SEL_MASK, 61 ISP_AF_EN_CTRL_STAT_SEL_NEW); 62 c3_isp_update_bits(stats->isp, ISP_AE_CTRL, 63 ISP_AE_CTRL_LUMA_MODE_MASK, 64 ISP_AE_CTRL_LUMA_MODE_FILTER); 65 66 /* The unit of dma_size is 16 bytes */ 67 dma_size = sizeof(struct c3_isp_af_stats) / C3_ISP_DMA_SIZE_ALIGN_BYTES; 68 c3_isp_update_bits(stats->isp, VIU_DMAWR_SIZE0, 69 VIU_DMAWR_SIZE0_AF_STATS_SIZE_MASK, 70 VIU_DMAWR_SIZE0_AF_STATS_SIZE(dma_size)); 71 72 dma_size = sizeof(struct c3_isp_awb_stats) / 73 C3_ISP_DMA_SIZE_ALIGN_BYTES; 74 c3_isp_update_bits(stats->isp, VIU_DMAWR_SIZE0, 75 VIU_DMAWR_SIZE0_AWB_STATS_SIZE_MASK, 76 VIU_DMAWR_SIZE0_AWB_STATS_SIZE(dma_size)); 77 78 dma_size = sizeof(struct c3_isp_ae_stats) / C3_ISP_DMA_SIZE_ALIGN_BYTES; 79 c3_isp_update_bits(stats->isp, VIU_DMAWR_SIZE1, 80 VIU_DMAWR_SIZE1_AE_STATS_SIZE_MASK, 81 VIU_DMAWR_SIZE1_AE_STATS_SIZE(dma_size)); 82 83 guard(spinlock_irqsave)(&stats->buff_lock); 84 85 c3_isp_stats_cfg_buff(stats); 86 } 87 88 static int c3_isp_stats_querycap(struct file *file, void *fh, 89 struct v4l2_capability *cap) 90 { 91 strscpy(cap->driver, C3_ISP_DRIVER_NAME, sizeof(cap->driver)); 92 strscpy(cap->card, "AML C3 ISP", sizeof(cap->card)); 93 94 return 0; 95 } 96 97 static int c3_isp_stats_enum_fmt(struct file *file, void *fh, 98 struct v4l2_fmtdesc *f) 99 { 100 struct c3_isp_stats *stats = video_drvdata(file); 101 102 if (f->index > 0 || f->type != stats->vb2_q.type) 103 return -EINVAL; 104 105 f->pixelformat = V4L2_META_FMT_C3ISP_STATS; 106 107 return 0; 108 } 109 110 static int c3_isp_stats_g_fmt(struct file *file, void *fh, 111 struct v4l2_format *f) 112 { 113 struct c3_isp_stats *stats = video_drvdata(file); 114 115 f->fmt.meta = stats->vfmt.fmt.meta; 116 117 return 0; 118 } 119 120 static const struct v4l2_ioctl_ops isp_stats_v4l2_ioctl_ops = { 121 .vidioc_querycap = c3_isp_stats_querycap, 122 .vidioc_enum_fmt_meta_cap = c3_isp_stats_enum_fmt, 123 .vidioc_g_fmt_meta_cap = c3_isp_stats_g_fmt, 124 .vidioc_s_fmt_meta_cap = c3_isp_stats_g_fmt, 125 .vidioc_try_fmt_meta_cap = c3_isp_stats_g_fmt, 126 .vidioc_reqbufs = vb2_ioctl_reqbufs, 127 .vidioc_querybuf = vb2_ioctl_querybuf, 128 .vidioc_qbuf = vb2_ioctl_qbuf, 129 .vidioc_expbuf = vb2_ioctl_expbuf, 130 .vidioc_dqbuf = vb2_ioctl_dqbuf, 131 .vidioc_prepare_buf = vb2_ioctl_prepare_buf, 132 .vidioc_create_bufs = vb2_ioctl_create_bufs, 133 .vidioc_streamon = vb2_ioctl_streamon, 134 .vidioc_streamoff = vb2_ioctl_streamoff, 135 }; 136 137 static const struct v4l2_file_operations isp_stats_v4l2_fops = { 138 .open = v4l2_fh_open, 139 .release = vb2_fop_release, 140 .poll = vb2_fop_poll, 141 .unlocked_ioctl = video_ioctl2, 142 .mmap = vb2_fop_mmap, 143 }; 144 145 static int c3_isp_stats_vb2_queue_setup(struct vb2_queue *q, 146 unsigned int *num_buffers, 147 unsigned int *num_planes, 148 unsigned int sizes[], 149 struct device *alloc_devs[]) 150 { 151 if (*num_planes) { 152 if (*num_planes != 1) 153 return -EINVAL; 154 155 if (sizes[0] < sizeof(struct c3_isp_stats_info)) 156 return -EINVAL; 157 158 return 0; 159 } 160 161 *num_planes = 1; 162 sizes[0] = sizeof(struct c3_isp_stats_info); 163 164 return 0; 165 } 166 167 static void c3_isp_stats_vb2_buf_queue(struct vb2_buffer *vb) 168 { 169 struct vb2_v4l2_buffer *v4l2_buf = to_vb2_v4l2_buffer(vb); 170 struct c3_isp_stats_buffer *buf = 171 container_of(v4l2_buf, struct c3_isp_stats_buffer, vb); 172 struct c3_isp_stats *stats = vb2_get_drv_priv(vb->vb2_queue); 173 174 guard(spinlock_irqsave)(&stats->buff_lock); 175 176 list_add_tail(&buf->list, &stats->pending); 177 } 178 179 static int c3_isp_stats_vb2_buf_prepare(struct vb2_buffer *vb) 180 { 181 struct c3_isp_stats *stats = vb2_get_drv_priv(vb->vb2_queue); 182 unsigned int size = stats->vfmt.fmt.meta.buffersize; 183 184 if (vb2_plane_size(vb, 0) < size) { 185 dev_err(stats->isp->dev, 186 "User buffer too small (%ld < %u)\n", 187 vb2_plane_size(vb, 0), size); 188 return -EINVAL; 189 } 190 191 vb2_set_plane_payload(vb, 0, size); 192 193 return 0; 194 } 195 196 static int c3_isp_stats_vb2_buf_init(struct vb2_buffer *vb) 197 { 198 struct vb2_v4l2_buffer *v4l2_buf = to_vb2_v4l2_buffer(vb); 199 struct c3_isp_stats_buffer *buf = 200 container_of(v4l2_buf, struct c3_isp_stats_buffer, vb); 201 202 buf->dma_addr = vb2_dma_contig_plane_dma_addr(vb, 0); 203 204 return 0; 205 } 206 207 static void c3_isp_stats_vb2_stop_streaming(struct vb2_queue *q) 208 { 209 struct c3_isp_stats *stats = vb2_get_drv_priv(q); 210 211 guard(spinlock_irqsave)(&stats->buff_lock); 212 213 if (stats->buff) { 214 vb2_buffer_done(&stats->buff->vb.vb2_buf, VB2_BUF_STATE_ERROR); 215 stats->buff = NULL; 216 } 217 218 while (!list_empty(&stats->pending)) { 219 struct c3_isp_stats_buffer *buff; 220 221 buff = list_first_entry(&stats->pending, 222 struct c3_isp_stats_buffer, list); 223 list_del(&buff->list); 224 vb2_buffer_done(&buff->vb.vb2_buf, VB2_BUF_STATE_ERROR); 225 } 226 } 227 228 static const struct vb2_ops isp_stats_vb2_ops = { 229 .queue_setup = c3_isp_stats_vb2_queue_setup, 230 .buf_queue = c3_isp_stats_vb2_buf_queue, 231 .buf_prepare = c3_isp_stats_vb2_buf_prepare, 232 .buf_init = c3_isp_stats_vb2_buf_init, 233 .stop_streaming = c3_isp_stats_vb2_stop_streaming, 234 }; 235 236 int c3_isp_stats_register(struct c3_isp_device *isp) 237 { 238 struct c3_isp_stats *stats = &isp->stats; 239 struct video_device *vdev = &stats->vdev; 240 struct vb2_queue *vb2_q = &stats->vb2_q; 241 int ret; 242 243 memset(stats, 0, sizeof(*stats)); 244 stats->vfmt.fmt.meta.dataformat = V4L2_META_FMT_C3ISP_STATS; 245 stats->vfmt.fmt.meta.buffersize = sizeof(struct c3_isp_stats_info); 246 stats->isp = isp; 247 INIT_LIST_HEAD(&stats->pending); 248 spin_lock_init(&stats->buff_lock); 249 250 mutex_init(&stats->lock); 251 252 snprintf(vdev->name, sizeof(vdev->name), "c3-isp-stats"); 253 vdev->fops = &isp_stats_v4l2_fops; 254 vdev->ioctl_ops = &isp_stats_v4l2_ioctl_ops; 255 vdev->v4l2_dev = &isp->v4l2_dev; 256 vdev->lock = &stats->lock; 257 vdev->minor = -1; 258 vdev->queue = vb2_q; 259 vdev->release = video_device_release_empty; 260 vdev->device_caps = V4L2_CAP_META_CAPTURE | V4L2_CAP_STREAMING; 261 vdev->vfl_dir = VFL_DIR_RX; 262 video_set_drvdata(vdev, stats); 263 264 vb2_q->drv_priv = stats; 265 vb2_q->mem_ops = &vb2_dma_contig_memops; 266 vb2_q->ops = &isp_stats_vb2_ops; 267 vb2_q->type = V4L2_BUF_TYPE_META_CAPTURE; 268 vb2_q->io_modes = VB2_DMABUF | VB2_MMAP; 269 vb2_q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; 270 vb2_q->buf_struct_size = sizeof(struct c3_isp_stats_buffer); 271 vb2_q->dev = isp->dev; 272 vb2_q->lock = &stats->lock; 273 vb2_q->min_queued_buffers = 2; 274 275 ret = vb2_queue_init(vb2_q); 276 if (ret) 277 goto err_destroy; 278 279 stats->pad.flags = MEDIA_PAD_FL_SINK; 280 ret = media_entity_pads_init(&vdev->entity, 1, &stats->pad); 281 if (ret) 282 goto err_queue_release; 283 284 ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1); 285 if (ret) { 286 dev_err(isp->dev, 287 "Failed to register %s: %d\n", vdev->name, ret); 288 goto err_entity_cleanup; 289 } 290 291 return 0; 292 293 err_entity_cleanup: 294 media_entity_cleanup(&vdev->entity); 295 err_queue_release: 296 vb2_queue_release(vb2_q); 297 err_destroy: 298 mutex_destroy(&stats->lock); 299 return ret; 300 } 301 302 void c3_isp_stats_unregister(struct c3_isp_device *isp) 303 { 304 struct c3_isp_stats *stats = &isp->stats; 305 306 vb2_queue_release(&stats->vb2_q); 307 media_entity_cleanup(&stats->vdev.entity); 308 video_unregister_device(&stats->vdev); 309 mutex_destroy(&stats->lock); 310 } 311 312 void c3_isp_stats_isr(struct c3_isp_device *isp) 313 { 314 struct c3_isp_stats *stats = &isp->stats; 315 316 guard(spinlock_irqsave)(&stats->buff_lock); 317 318 if (stats->buff) { 319 stats->buff->vb.sequence = stats->isp->frm_sequence; 320 stats->buff->vb.vb2_buf.timestamp = ktime_get(); 321 stats->buff->vb.field = V4L2_FIELD_NONE; 322 vb2_buffer_done(&stats->buff->vb.vb2_buf, VB2_BUF_STATE_DONE); 323 } 324 325 c3_isp_stats_cfg_buff(stats); 326 } 327