1*501802e2SMichael Riesch // SPDX-License-Identifier: GPL-2.0 2*501802e2SMichael Riesch /* 3*501802e2SMichael Riesch * Rockchip Camera Interface (CIF) Driver 4*501802e2SMichael Riesch * 5*501802e2SMichael Riesch * Copyright (C) 2025 Michael Riesch <michael.riesch@wolfvision.net> 6*501802e2SMichael Riesch * Copyright (C) 2025 Collabora, Ltd. 7*501802e2SMichael Riesch */ 8*501802e2SMichael Riesch 9*501802e2SMichael Riesch #include <linux/pm_runtime.h> 10*501802e2SMichael Riesch 11*501802e2SMichael Riesch #include <media/v4l2-common.h> 12*501802e2SMichael Riesch #include <media/v4l2-fwnode.h> 13*501802e2SMichael Riesch #include <media/v4l2-ioctl.h> 14*501802e2SMichael Riesch #include <media/v4l2-mc.h> 15*501802e2SMichael Riesch #include <media/v4l2-subdev.h> 16*501802e2SMichael Riesch #include <media/videobuf2-dma-contig.h> 17*501802e2SMichael Riesch 18*501802e2SMichael Riesch #include "rkcif-common.h" 19*501802e2SMichael Riesch #include "rkcif-stream.h" 20*501802e2SMichael Riesch 21*501802e2SMichael Riesch #define CIF_REQ_BUFS_MIN 1 22*501802e2SMichael Riesch #define CIF_MIN_WIDTH 64 23*501802e2SMichael Riesch #define CIF_MIN_HEIGHT 64 24*501802e2SMichael Riesch #define CIF_MAX_WIDTH 8192 25*501802e2SMichael Riesch #define CIF_MAX_HEIGHT 8192 26*501802e2SMichael Riesch 27*501802e2SMichael Riesch static inline struct rkcif_buffer *to_rkcif_buffer(struct vb2_v4l2_buffer *vb) 28*501802e2SMichael Riesch { 29*501802e2SMichael Riesch return container_of(vb, struct rkcif_buffer, vb); 30*501802e2SMichael Riesch } 31*501802e2SMichael Riesch 32*501802e2SMichael Riesch static inline struct rkcif_stream *to_rkcif_stream(struct video_device *vdev) 33*501802e2SMichael Riesch { 34*501802e2SMichael Riesch return container_of(vdev, struct rkcif_stream, vdev); 35*501802e2SMichael Riesch } 36*501802e2SMichael Riesch 37*501802e2SMichael Riesch static struct rkcif_buffer *rkcif_stream_pop_buffer(struct rkcif_stream *stream) 38*501802e2SMichael Riesch { 39*501802e2SMichael Riesch struct rkcif_buffer *buffer; 40*501802e2SMichael Riesch 41*501802e2SMichael Riesch guard(spinlock_irqsave)(&stream->driver_queue_lock); 42*501802e2SMichael Riesch 43*501802e2SMichael Riesch if (list_empty(&stream->driver_queue)) 44*501802e2SMichael Riesch return NULL; 45*501802e2SMichael Riesch 46*501802e2SMichael Riesch buffer = list_first_entry(&stream->driver_queue, struct rkcif_buffer, 47*501802e2SMichael Riesch queue); 48*501802e2SMichael Riesch list_del(&buffer->queue); 49*501802e2SMichael Riesch 50*501802e2SMichael Riesch return buffer; 51*501802e2SMichael Riesch } 52*501802e2SMichael Riesch 53*501802e2SMichael Riesch static void rkcif_stream_push_buffer(struct rkcif_stream *stream, 54*501802e2SMichael Riesch struct rkcif_buffer *buffer) 55*501802e2SMichael Riesch { 56*501802e2SMichael Riesch guard(spinlock_irqsave)(&stream->driver_queue_lock); 57*501802e2SMichael Riesch 58*501802e2SMichael Riesch list_add_tail(&buffer->queue, &stream->driver_queue); 59*501802e2SMichael Riesch } 60*501802e2SMichael Riesch 61*501802e2SMichael Riesch static inline void rkcif_stream_return_buffer(struct rkcif_buffer *buffer, 62*501802e2SMichael Riesch enum vb2_buffer_state state) 63*501802e2SMichael Riesch { 64*501802e2SMichael Riesch struct vb2_v4l2_buffer *vb = &buffer->vb; 65*501802e2SMichael Riesch 66*501802e2SMichael Riesch vb2_buffer_done(&vb->vb2_buf, state); 67*501802e2SMichael Riesch } 68*501802e2SMichael Riesch 69*501802e2SMichael Riesch static void rkcif_stream_complete_buffer(struct rkcif_stream *stream, 70*501802e2SMichael Riesch struct rkcif_buffer *buffer) 71*501802e2SMichael Riesch { 72*501802e2SMichael Riesch struct vb2_v4l2_buffer *vb = &buffer->vb; 73*501802e2SMichael Riesch 74*501802e2SMichael Riesch vb->vb2_buf.timestamp = ktime_get_ns(); 75*501802e2SMichael Riesch vb->sequence = stream->frame_idx; 76*501802e2SMichael Riesch vb2_buffer_done(&vb->vb2_buf, VB2_BUF_STATE_DONE); 77*501802e2SMichael Riesch stream->frame_idx++; 78*501802e2SMichael Riesch } 79*501802e2SMichael Riesch 80*501802e2SMichael Riesch void rkcif_stream_pingpong(struct rkcif_stream *stream) 81*501802e2SMichael Riesch { 82*501802e2SMichael Riesch struct rkcif_buffer *buffer; 83*501802e2SMichael Riesch 84*501802e2SMichael Riesch buffer = stream->buffers[stream->frame_phase]; 85*501802e2SMichael Riesch if (!buffer->is_dummy) 86*501802e2SMichael Riesch rkcif_stream_complete_buffer(stream, buffer); 87*501802e2SMichael Riesch 88*501802e2SMichael Riesch buffer = rkcif_stream_pop_buffer(stream); 89*501802e2SMichael Riesch if (buffer) { 90*501802e2SMichael Riesch stream->buffers[stream->frame_phase] = buffer; 91*501802e2SMichael Riesch stream->buffers[stream->frame_phase]->is_dummy = false; 92*501802e2SMichael Riesch } else { 93*501802e2SMichael Riesch stream->buffers[stream->frame_phase] = &stream->dummy.buffer; 94*501802e2SMichael Riesch stream->buffers[stream->frame_phase]->is_dummy = true; 95*501802e2SMichael Riesch dev_dbg(stream->rkcif->dev, 96*501802e2SMichael Riesch "no buffer available, frame will be dropped\n"); 97*501802e2SMichael Riesch } 98*501802e2SMichael Riesch 99*501802e2SMichael Riesch if (stream->queue_buffer) 100*501802e2SMichael Riesch stream->queue_buffer(stream, stream->frame_phase); 101*501802e2SMichael Riesch 102*501802e2SMichael Riesch stream->frame_phase = 1 - stream->frame_phase; 103*501802e2SMichael Riesch } 104*501802e2SMichael Riesch 105*501802e2SMichael Riesch static int rkcif_stream_init_buffers(struct rkcif_stream *stream) 106*501802e2SMichael Riesch { 107*501802e2SMichael Riesch struct v4l2_pix_format_mplane *pix = &stream->pix; 108*501802e2SMichael Riesch 109*501802e2SMichael Riesch stream->buffers[0] = rkcif_stream_pop_buffer(stream); 110*501802e2SMichael Riesch if (!stream->buffers[0]) 111*501802e2SMichael Riesch goto err_buff_0; 112*501802e2SMichael Riesch 113*501802e2SMichael Riesch stream->buffers[1] = rkcif_stream_pop_buffer(stream); 114*501802e2SMichael Riesch if (!stream->buffers[1]) 115*501802e2SMichael Riesch goto err_buff_1; 116*501802e2SMichael Riesch 117*501802e2SMichael Riesch if (stream->queue_buffer) { 118*501802e2SMichael Riesch stream->queue_buffer(stream, 0); 119*501802e2SMichael Riesch stream->queue_buffer(stream, 1); 120*501802e2SMichael Riesch } 121*501802e2SMichael Riesch 122*501802e2SMichael Riesch stream->dummy.size = pix->num_planes * pix->plane_fmt[0].sizeimage; 123*501802e2SMichael Riesch stream->dummy.vaddr = 124*501802e2SMichael Riesch dma_alloc_attrs(stream->rkcif->dev, stream->dummy.size, 125*501802e2SMichael Riesch &stream->dummy.buffer.buff_addr[0], GFP_KERNEL, 126*501802e2SMichael Riesch DMA_ATTR_NO_KERNEL_MAPPING); 127*501802e2SMichael Riesch if (!stream->dummy.vaddr) 128*501802e2SMichael Riesch goto err_dummy; 129*501802e2SMichael Riesch 130*501802e2SMichael Riesch for (unsigned int i = 1; i < pix->num_planes; i++) 131*501802e2SMichael Riesch stream->dummy.buffer.buff_addr[i] = 132*501802e2SMichael Riesch stream->dummy.buffer.buff_addr[i - 1] + 133*501802e2SMichael Riesch pix->plane_fmt[i - 1].bytesperline * pix->height; 134*501802e2SMichael Riesch 135*501802e2SMichael Riesch return 0; 136*501802e2SMichael Riesch 137*501802e2SMichael Riesch err_dummy: 138*501802e2SMichael Riesch rkcif_stream_return_buffer(stream->buffers[1], VB2_BUF_STATE_QUEUED); 139*501802e2SMichael Riesch stream->buffers[1] = NULL; 140*501802e2SMichael Riesch 141*501802e2SMichael Riesch err_buff_1: 142*501802e2SMichael Riesch rkcif_stream_return_buffer(stream->buffers[0], VB2_BUF_STATE_QUEUED); 143*501802e2SMichael Riesch stream->buffers[0] = NULL; 144*501802e2SMichael Riesch err_buff_0: 145*501802e2SMichael Riesch return -EINVAL; 146*501802e2SMichael Riesch } 147*501802e2SMichael Riesch 148*501802e2SMichael Riesch static void rkcif_stream_return_all_buffers(struct rkcif_stream *stream, 149*501802e2SMichael Riesch enum vb2_buffer_state state) 150*501802e2SMichael Riesch { 151*501802e2SMichael Riesch struct rkcif_buffer *buffer; 152*501802e2SMichael Riesch 153*501802e2SMichael Riesch if (stream->buffers[0] && !stream->buffers[0]->is_dummy) { 154*501802e2SMichael Riesch rkcif_stream_return_buffer(stream->buffers[0], state); 155*501802e2SMichael Riesch stream->buffers[0] = NULL; 156*501802e2SMichael Riesch } 157*501802e2SMichael Riesch 158*501802e2SMichael Riesch if (stream->buffers[1] && !stream->buffers[1]->is_dummy) { 159*501802e2SMichael Riesch rkcif_stream_return_buffer(stream->buffers[1], state); 160*501802e2SMichael Riesch stream->buffers[1] = NULL; 161*501802e2SMichael Riesch } 162*501802e2SMichael Riesch 163*501802e2SMichael Riesch while ((buffer = rkcif_stream_pop_buffer(stream))) 164*501802e2SMichael Riesch rkcif_stream_return_buffer(buffer, state); 165*501802e2SMichael Riesch 166*501802e2SMichael Riesch if (stream->dummy.vaddr) { 167*501802e2SMichael Riesch dma_free_attrs(stream->rkcif->dev, stream->dummy.size, 168*501802e2SMichael Riesch stream->dummy.vaddr, 169*501802e2SMichael Riesch stream->dummy.buffer.buff_addr[0], 170*501802e2SMichael Riesch DMA_ATTR_NO_KERNEL_MAPPING); 171*501802e2SMichael Riesch stream->dummy.vaddr = NULL; 172*501802e2SMichael Riesch } 173*501802e2SMichael Riesch } 174*501802e2SMichael Riesch 175*501802e2SMichael Riesch static int rkcif_stream_setup_queue(struct vb2_queue *queue, 176*501802e2SMichael Riesch unsigned int *num_buffers, 177*501802e2SMichael Riesch unsigned int *num_planes, 178*501802e2SMichael Riesch unsigned int sizes[], 179*501802e2SMichael Riesch struct device *alloc_devs[]) 180*501802e2SMichael Riesch { 181*501802e2SMichael Riesch struct rkcif_stream *stream = queue->drv_priv; 182*501802e2SMichael Riesch struct v4l2_pix_format_mplane *pix = &stream->pix; 183*501802e2SMichael Riesch 184*501802e2SMichael Riesch if (*num_planes) { 185*501802e2SMichael Riesch if (*num_planes != pix->num_planes) 186*501802e2SMichael Riesch return -EINVAL; 187*501802e2SMichael Riesch 188*501802e2SMichael Riesch for (unsigned int i = 0; i < pix->num_planes; i++) 189*501802e2SMichael Riesch if (sizes[i] < pix->plane_fmt[i].sizeimage) 190*501802e2SMichael Riesch return -EINVAL; 191*501802e2SMichael Riesch } else { 192*501802e2SMichael Riesch *num_planes = pix->num_planes; 193*501802e2SMichael Riesch for (unsigned int i = 0; i < pix->num_planes; i++) 194*501802e2SMichael Riesch sizes[i] = pix->plane_fmt[i].sizeimage; 195*501802e2SMichael Riesch } 196*501802e2SMichael Riesch 197*501802e2SMichael Riesch return 0; 198*501802e2SMichael Riesch } 199*501802e2SMichael Riesch 200*501802e2SMichael Riesch static int rkcif_stream_prepare_buffer(struct vb2_buffer *vb) 201*501802e2SMichael Riesch { 202*501802e2SMichael Riesch struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 203*501802e2SMichael Riesch struct rkcif_buffer *buffer = to_rkcif_buffer(vbuf); 204*501802e2SMichael Riesch struct rkcif_stream *stream = vb->vb2_queue->drv_priv; 205*501802e2SMichael Riesch const struct rkcif_output_fmt *fmt; 206*501802e2SMichael Riesch struct v4l2_pix_format_mplane *pix = &stream->pix; 207*501802e2SMichael Riesch unsigned int i; 208*501802e2SMichael Riesch 209*501802e2SMichael Riesch memset(buffer->buff_addr, 0, sizeof(buffer->buff_addr)); 210*501802e2SMichael Riesch for (i = 0; i < pix->num_planes; i++) 211*501802e2SMichael Riesch buffer->buff_addr[i] = vb2_dma_contig_plane_dma_addr(vb, i); 212*501802e2SMichael Riesch 213*501802e2SMichael Riesch /* apply fallback for non-mplane formats, if required */ 214*501802e2SMichael Riesch if (pix->num_planes == 1) { 215*501802e2SMichael Riesch fmt = rkcif_stream_find_output_fmt(stream, true, 216*501802e2SMichael Riesch pix->pixelformat); 217*501802e2SMichael Riesch for (i = 1; i < fmt->cplanes; i++) 218*501802e2SMichael Riesch buffer->buff_addr[i] = 219*501802e2SMichael Riesch buffer->buff_addr[i - 1] + 220*501802e2SMichael Riesch pix->plane_fmt[i - 1].bytesperline * 221*501802e2SMichael Riesch pix->height; 222*501802e2SMichael Riesch } 223*501802e2SMichael Riesch 224*501802e2SMichael Riesch for (i = 0; i < pix->num_planes; i++) { 225*501802e2SMichael Riesch unsigned long size = pix->plane_fmt[i].sizeimage; 226*501802e2SMichael Riesch 227*501802e2SMichael Riesch if (vb2_plane_size(vb, i) < size) { 228*501802e2SMichael Riesch dev_err(stream->rkcif->dev, 229*501802e2SMichael Riesch "user buffer too small (%ld < %ld)\n", 230*501802e2SMichael Riesch vb2_plane_size(vb, i), size); 231*501802e2SMichael Riesch return -EINVAL; 232*501802e2SMichael Riesch } 233*501802e2SMichael Riesch 234*501802e2SMichael Riesch vb2_set_plane_payload(vb, i, size); 235*501802e2SMichael Riesch } 236*501802e2SMichael Riesch 237*501802e2SMichael Riesch vbuf->field = V4L2_FIELD_NONE; 238*501802e2SMichael Riesch 239*501802e2SMichael Riesch return 0; 240*501802e2SMichael Riesch } 241*501802e2SMichael Riesch 242*501802e2SMichael Riesch static void rkcif_stream_queue_buffer(struct vb2_buffer *vb) 243*501802e2SMichael Riesch { 244*501802e2SMichael Riesch struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 245*501802e2SMichael Riesch struct rkcif_buffer *buffer = to_rkcif_buffer(vbuf); 246*501802e2SMichael Riesch struct rkcif_stream *stream = vb->vb2_queue->drv_priv; 247*501802e2SMichael Riesch 248*501802e2SMichael Riesch rkcif_stream_push_buffer(stream, buffer); 249*501802e2SMichael Riesch } 250*501802e2SMichael Riesch 251*501802e2SMichael Riesch static int rkcif_stream_start_streaming(struct vb2_queue *queue, 252*501802e2SMichael Riesch unsigned int count) 253*501802e2SMichael Riesch { 254*501802e2SMichael Riesch struct rkcif_stream *stream = queue->drv_priv; 255*501802e2SMichael Riesch struct rkcif_device *rkcif = stream->rkcif; 256*501802e2SMichael Riesch u64 mask; 257*501802e2SMichael Riesch int ret; 258*501802e2SMichael Riesch 259*501802e2SMichael Riesch stream->frame_idx = 0; 260*501802e2SMichael Riesch stream->frame_phase = 0; 261*501802e2SMichael Riesch 262*501802e2SMichael Riesch ret = video_device_pipeline_start(&stream->vdev, &stream->pipeline); 263*501802e2SMichael Riesch if (ret) { 264*501802e2SMichael Riesch dev_err(rkcif->dev, "failed to start pipeline %d\n", ret); 265*501802e2SMichael Riesch goto err_out; 266*501802e2SMichael Riesch } 267*501802e2SMichael Riesch 268*501802e2SMichael Riesch ret = pm_runtime_resume_and_get(rkcif->dev); 269*501802e2SMichael Riesch if (ret < 0) { 270*501802e2SMichael Riesch dev_err(rkcif->dev, "failed to get runtime pm, %d\n", ret); 271*501802e2SMichael Riesch goto err_pipeline_stop; 272*501802e2SMichael Riesch } 273*501802e2SMichael Riesch 274*501802e2SMichael Riesch ret = rkcif_stream_init_buffers(stream); 275*501802e2SMichael Riesch if (ret) 276*501802e2SMichael Riesch goto err_runtime_put; 277*501802e2SMichael Riesch 278*501802e2SMichael Riesch if (stream->start_streaming) { 279*501802e2SMichael Riesch ret = stream->start_streaming(stream); 280*501802e2SMichael Riesch if (ret < 0) 281*501802e2SMichael Riesch goto err_runtime_put; 282*501802e2SMichael Riesch } 283*501802e2SMichael Riesch 284*501802e2SMichael Riesch mask = BIT_ULL(stream->id); 285*501802e2SMichael Riesch ret = v4l2_subdev_enable_streams(&stream->interface->sd, 286*501802e2SMichael Riesch RKCIF_IF_PAD_SRC, mask); 287*501802e2SMichael Riesch if (ret < 0) 288*501802e2SMichael Riesch goto err_stop_stream; 289*501802e2SMichael Riesch 290*501802e2SMichael Riesch return 0; 291*501802e2SMichael Riesch 292*501802e2SMichael Riesch err_stop_stream: 293*501802e2SMichael Riesch if (stream->stop_streaming) 294*501802e2SMichael Riesch stream->stop_streaming(stream); 295*501802e2SMichael Riesch err_runtime_put: 296*501802e2SMichael Riesch pm_runtime_put(rkcif->dev); 297*501802e2SMichael Riesch err_pipeline_stop: 298*501802e2SMichael Riesch video_device_pipeline_stop(&stream->vdev); 299*501802e2SMichael Riesch err_out: 300*501802e2SMichael Riesch rkcif_stream_return_all_buffers(stream, VB2_BUF_STATE_QUEUED); 301*501802e2SMichael Riesch return ret; 302*501802e2SMichael Riesch } 303*501802e2SMichael Riesch 304*501802e2SMichael Riesch static void rkcif_stream_stop_streaming(struct vb2_queue *queue) 305*501802e2SMichael Riesch { 306*501802e2SMichael Riesch struct rkcif_stream *stream = queue->drv_priv; 307*501802e2SMichael Riesch struct rkcif_device *rkcif = stream->rkcif; 308*501802e2SMichael Riesch u64 mask; 309*501802e2SMichael Riesch int ret; 310*501802e2SMichael Riesch 311*501802e2SMichael Riesch mask = BIT_ULL(stream->id); 312*501802e2SMichael Riesch v4l2_subdev_disable_streams(&stream->interface->sd, RKCIF_IF_PAD_SRC, 313*501802e2SMichael Riesch mask); 314*501802e2SMichael Riesch 315*501802e2SMichael Riesch stream->stopping = true; 316*501802e2SMichael Riesch ret = wait_event_timeout(stream->wq_stopped, !stream->stopping, 317*501802e2SMichael Riesch msecs_to_jiffies(1000)); 318*501802e2SMichael Riesch 319*501802e2SMichael Riesch if (!ret && stream->stop_streaming) 320*501802e2SMichael Riesch stream->stop_streaming(stream); 321*501802e2SMichael Riesch 322*501802e2SMichael Riesch pm_runtime_put(rkcif->dev); 323*501802e2SMichael Riesch 324*501802e2SMichael Riesch rkcif_stream_return_all_buffers(stream, VB2_BUF_STATE_ERROR); 325*501802e2SMichael Riesch 326*501802e2SMichael Riesch video_device_pipeline_stop(&stream->vdev); 327*501802e2SMichael Riesch } 328*501802e2SMichael Riesch 329*501802e2SMichael Riesch static const struct vb2_ops rkcif_stream_vb2_ops = { 330*501802e2SMichael Riesch .queue_setup = rkcif_stream_setup_queue, 331*501802e2SMichael Riesch .buf_prepare = rkcif_stream_prepare_buffer, 332*501802e2SMichael Riesch .buf_queue = rkcif_stream_queue_buffer, 333*501802e2SMichael Riesch .start_streaming = rkcif_stream_start_streaming, 334*501802e2SMichael Riesch .stop_streaming = rkcif_stream_stop_streaming, 335*501802e2SMichael Riesch }; 336*501802e2SMichael Riesch 337*501802e2SMichael Riesch static int rkcif_stream_fill_format(struct rkcif_stream *stream, 338*501802e2SMichael Riesch struct v4l2_pix_format_mplane *pix) 339*501802e2SMichael Riesch { 340*501802e2SMichael Riesch const struct rkcif_output_fmt *fmt; 341*501802e2SMichael Riesch u32 height, width; 342*501802e2SMichael Riesch int ret; 343*501802e2SMichael Riesch 344*501802e2SMichael Riesch fmt = rkcif_stream_find_output_fmt(stream, true, pix->pixelformat); 345*501802e2SMichael Riesch height = clamp_t(u32, pix->height, CIF_MIN_HEIGHT, CIF_MAX_HEIGHT); 346*501802e2SMichael Riesch width = clamp_t(u32, pix->width, CIF_MIN_WIDTH, CIF_MAX_WIDTH); 347*501802e2SMichael Riesch ret = v4l2_fill_pixfmt_mp(pix, fmt->fourcc, width, height); 348*501802e2SMichael Riesch if (ret) 349*501802e2SMichael Riesch return ret; 350*501802e2SMichael Riesch 351*501802e2SMichael Riesch pix->field = V4L2_FIELD_NONE; 352*501802e2SMichael Riesch 353*501802e2SMichael Riesch return 0; 354*501802e2SMichael Riesch } 355*501802e2SMichael Riesch 356*501802e2SMichael Riesch static int rkcif_stream_try_format(struct file *file, void *fh, 357*501802e2SMichael Riesch struct v4l2_format *f) 358*501802e2SMichael Riesch { 359*501802e2SMichael Riesch struct rkcif_stream *stream = video_drvdata(file); 360*501802e2SMichael Riesch struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp; 361*501802e2SMichael Riesch 362*501802e2SMichael Riesch return rkcif_stream_fill_format(stream, pix); 363*501802e2SMichael Riesch } 364*501802e2SMichael Riesch 365*501802e2SMichael Riesch static int rkcif_stream_set_format(struct file *file, void *priv, 366*501802e2SMichael Riesch struct v4l2_format *f) 367*501802e2SMichael Riesch { 368*501802e2SMichael Riesch struct rkcif_stream *stream = video_drvdata(file); 369*501802e2SMichael Riesch struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp; 370*501802e2SMichael Riesch int ret; 371*501802e2SMichael Riesch 372*501802e2SMichael Riesch if (vb2_is_busy(&stream->buf_queue)) 373*501802e2SMichael Riesch return -EBUSY; 374*501802e2SMichael Riesch 375*501802e2SMichael Riesch ret = rkcif_stream_try_format(file, priv, f); 376*501802e2SMichael Riesch if (ret) 377*501802e2SMichael Riesch return ret; 378*501802e2SMichael Riesch 379*501802e2SMichael Riesch stream->pix = *pix; 380*501802e2SMichael Riesch 381*501802e2SMichael Riesch return 0; 382*501802e2SMichael Riesch } 383*501802e2SMichael Riesch 384*501802e2SMichael Riesch static int rkcif_stream_get_format(struct file *file, void *fh, 385*501802e2SMichael Riesch struct v4l2_format *f) 386*501802e2SMichael Riesch { 387*501802e2SMichael Riesch struct rkcif_stream *stream = video_drvdata(file); 388*501802e2SMichael Riesch 389*501802e2SMichael Riesch f->fmt.pix_mp = stream->pix; 390*501802e2SMichael Riesch 391*501802e2SMichael Riesch return 0; 392*501802e2SMichael Riesch } 393*501802e2SMichael Riesch 394*501802e2SMichael Riesch static int rkcif_stream_enum_formats(struct file *file, void *priv, 395*501802e2SMichael Riesch struct v4l2_fmtdesc *f) 396*501802e2SMichael Riesch { 397*501802e2SMichael Riesch struct rkcif_stream *stream = video_drvdata(file); 398*501802e2SMichael Riesch 399*501802e2SMichael Riesch if (f->index >= stream->out_fmts_num) 400*501802e2SMichael Riesch return -EINVAL; 401*501802e2SMichael Riesch 402*501802e2SMichael Riesch f->pixelformat = stream->out_fmts[f->index].fourcc; 403*501802e2SMichael Riesch 404*501802e2SMichael Riesch return 0; 405*501802e2SMichael Riesch } 406*501802e2SMichael Riesch 407*501802e2SMichael Riesch static int rkcif_stream_enum_framesizes(struct file *file, void *fh, 408*501802e2SMichael Riesch struct v4l2_frmsizeenum *fsize) 409*501802e2SMichael Riesch { 410*501802e2SMichael Riesch struct rkcif_stream *stream = video_drvdata(file); 411*501802e2SMichael Riesch 412*501802e2SMichael Riesch if (fsize->index > 0) 413*501802e2SMichael Riesch return -EINVAL; 414*501802e2SMichael Riesch 415*501802e2SMichael Riesch if (!rkcif_stream_find_output_fmt(stream, false, fsize->pixel_format)) 416*501802e2SMichael Riesch return -EINVAL; 417*501802e2SMichael Riesch 418*501802e2SMichael Riesch fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE; 419*501802e2SMichael Riesch fsize->stepwise.min_width = CIF_MIN_WIDTH; 420*501802e2SMichael Riesch fsize->stepwise.max_width = CIF_MAX_WIDTH; 421*501802e2SMichael Riesch fsize->stepwise.step_width = 8; 422*501802e2SMichael Riesch fsize->stepwise.min_height = CIF_MIN_HEIGHT; 423*501802e2SMichael Riesch fsize->stepwise.max_height = CIF_MAX_HEIGHT; 424*501802e2SMichael Riesch fsize->stepwise.step_height = 8; 425*501802e2SMichael Riesch 426*501802e2SMichael Riesch return 0; 427*501802e2SMichael Riesch } 428*501802e2SMichael Riesch 429*501802e2SMichael Riesch static int rkcif_stream_querycap(struct file *file, void *priv, 430*501802e2SMichael Riesch struct v4l2_capability *cap) 431*501802e2SMichael Riesch { 432*501802e2SMichael Riesch struct rkcif_stream *stream = video_drvdata(file); 433*501802e2SMichael Riesch struct device *dev = stream->rkcif->dev; 434*501802e2SMichael Riesch 435*501802e2SMichael Riesch strscpy(cap->driver, dev->driver->name, sizeof(cap->driver)); 436*501802e2SMichael Riesch strscpy(cap->card, dev->driver->name, sizeof(cap->card)); 437*501802e2SMichael Riesch 438*501802e2SMichael Riesch return 0; 439*501802e2SMichael Riesch } 440*501802e2SMichael Riesch 441*501802e2SMichael Riesch static const struct v4l2_ioctl_ops rkcif_stream_ioctl_ops = { 442*501802e2SMichael Riesch .vidioc_reqbufs = vb2_ioctl_reqbufs, 443*501802e2SMichael Riesch .vidioc_querybuf = vb2_ioctl_querybuf, 444*501802e2SMichael Riesch .vidioc_create_bufs = vb2_ioctl_create_bufs, 445*501802e2SMichael Riesch .vidioc_qbuf = vb2_ioctl_qbuf, 446*501802e2SMichael Riesch .vidioc_expbuf = vb2_ioctl_expbuf, 447*501802e2SMichael Riesch .vidioc_dqbuf = vb2_ioctl_dqbuf, 448*501802e2SMichael Riesch .vidioc_prepare_buf = vb2_ioctl_prepare_buf, 449*501802e2SMichael Riesch .vidioc_streamon = vb2_ioctl_streamon, 450*501802e2SMichael Riesch .vidioc_streamoff = vb2_ioctl_streamoff, 451*501802e2SMichael Riesch .vidioc_try_fmt_vid_cap_mplane = rkcif_stream_try_format, 452*501802e2SMichael Riesch .vidioc_s_fmt_vid_cap_mplane = rkcif_stream_set_format, 453*501802e2SMichael Riesch .vidioc_g_fmt_vid_cap_mplane = rkcif_stream_get_format, 454*501802e2SMichael Riesch .vidioc_enum_fmt_vid_cap = rkcif_stream_enum_formats, 455*501802e2SMichael Riesch .vidioc_enum_framesizes = rkcif_stream_enum_framesizes, 456*501802e2SMichael Riesch .vidioc_querycap = rkcif_stream_querycap, 457*501802e2SMichael Riesch }; 458*501802e2SMichael Riesch 459*501802e2SMichael Riesch static int rkcif_stream_link_validate(struct media_link *link) 460*501802e2SMichael Riesch { 461*501802e2SMichael Riesch struct video_device *vdev = 462*501802e2SMichael Riesch media_entity_to_video_device(link->sink->entity); 463*501802e2SMichael Riesch struct v4l2_mbus_framefmt *source_fmt; 464*501802e2SMichael Riesch struct v4l2_subdev *sd; 465*501802e2SMichael Riesch struct v4l2_subdev_state *state; 466*501802e2SMichael Riesch struct rkcif_stream *stream = to_rkcif_stream(vdev); 467*501802e2SMichael Riesch int ret = -EINVAL; 468*501802e2SMichael Riesch 469*501802e2SMichael Riesch if (!media_entity_remote_source_pad_unique(link->sink->entity)) 470*501802e2SMichael Riesch return -ENOTCONN; 471*501802e2SMichael Riesch 472*501802e2SMichael Riesch sd = media_entity_to_v4l2_subdev(link->source->entity); 473*501802e2SMichael Riesch 474*501802e2SMichael Riesch state = v4l2_subdev_lock_and_get_active_state(sd); 475*501802e2SMichael Riesch 476*501802e2SMichael Riesch source_fmt = v4l2_subdev_state_get_format(state, link->source->index, 477*501802e2SMichael Riesch stream->id); 478*501802e2SMichael Riesch if (!source_fmt) 479*501802e2SMichael Riesch goto out; 480*501802e2SMichael Riesch 481*501802e2SMichael Riesch if (source_fmt->height != stream->pix.height || 482*501802e2SMichael Riesch source_fmt->width != stream->pix.width) { 483*501802e2SMichael Riesch dev_dbg(stream->rkcif->dev, 484*501802e2SMichael Riesch "link '%s':%u -> '%s':%u not valid: %ux%u != %ux%u\n", 485*501802e2SMichael Riesch link->source->entity->name, link->source->index, 486*501802e2SMichael Riesch link->sink->entity->name, link->sink->index, 487*501802e2SMichael Riesch source_fmt->width, source_fmt->height, 488*501802e2SMichael Riesch stream->pix.width, stream->pix.height); 489*501802e2SMichael Riesch goto out; 490*501802e2SMichael Riesch } 491*501802e2SMichael Riesch 492*501802e2SMichael Riesch ret = 0; 493*501802e2SMichael Riesch 494*501802e2SMichael Riesch out: 495*501802e2SMichael Riesch v4l2_subdev_unlock_state(state); 496*501802e2SMichael Riesch return ret; 497*501802e2SMichael Riesch } 498*501802e2SMichael Riesch 499*501802e2SMichael Riesch static const struct media_entity_operations rkcif_stream_media_ops = { 500*501802e2SMichael Riesch .link_validate = rkcif_stream_link_validate, 501*501802e2SMichael Riesch }; 502*501802e2SMichael Riesch 503*501802e2SMichael Riesch static const struct v4l2_file_operations rkcif_stream_file_ops = { 504*501802e2SMichael Riesch .open = v4l2_fh_open, 505*501802e2SMichael Riesch .release = vb2_fop_release, 506*501802e2SMichael Riesch .unlocked_ioctl = video_ioctl2, 507*501802e2SMichael Riesch .poll = vb2_fop_poll, 508*501802e2SMichael Riesch .mmap = vb2_fop_mmap, 509*501802e2SMichael Riesch }; 510*501802e2SMichael Riesch 511*501802e2SMichael Riesch static int rkcif_stream_init_vb2_queue(struct vb2_queue *q, 512*501802e2SMichael Riesch struct rkcif_stream *stream) 513*501802e2SMichael Riesch { 514*501802e2SMichael Riesch q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 515*501802e2SMichael Riesch q->io_modes = VB2_MMAP | VB2_DMABUF; 516*501802e2SMichael Riesch q->drv_priv = stream; 517*501802e2SMichael Riesch q->ops = &rkcif_stream_vb2_ops; 518*501802e2SMichael Riesch q->mem_ops = &vb2_dma_contig_memops; 519*501802e2SMichael Riesch q->buf_struct_size = sizeof(struct rkcif_buffer); 520*501802e2SMichael Riesch q->min_queued_buffers = CIF_REQ_BUFS_MIN; 521*501802e2SMichael Riesch q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; 522*501802e2SMichael Riesch q->lock = &stream->vlock; 523*501802e2SMichael Riesch q->dev = stream->rkcif->dev; 524*501802e2SMichael Riesch 525*501802e2SMichael Riesch return vb2_queue_init(q); 526*501802e2SMichael Riesch } 527*501802e2SMichael Riesch 528*501802e2SMichael Riesch int rkcif_stream_register(struct rkcif_device *rkcif, 529*501802e2SMichael Riesch struct rkcif_stream *stream) 530*501802e2SMichael Riesch { 531*501802e2SMichael Riesch struct rkcif_interface *interface = stream->interface; 532*501802e2SMichael Riesch struct v4l2_device *v4l2_dev = &rkcif->v4l2_dev; 533*501802e2SMichael Riesch struct video_device *vdev = &stream->vdev; 534*501802e2SMichael Riesch u32 link_flags = 0; 535*501802e2SMichael Riesch int ret; 536*501802e2SMichael Riesch 537*501802e2SMichael Riesch stream->rkcif = rkcif; 538*501802e2SMichael Riesch 539*501802e2SMichael Riesch INIT_LIST_HEAD(&stream->driver_queue); 540*501802e2SMichael Riesch spin_lock_init(&stream->driver_queue_lock); 541*501802e2SMichael Riesch 542*501802e2SMichael Riesch init_waitqueue_head(&stream->wq_stopped); 543*501802e2SMichael Riesch 544*501802e2SMichael Riesch mutex_init(&stream->vlock); 545*501802e2SMichael Riesch 546*501802e2SMichael Riesch vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_STREAMING | 547*501802e2SMichael Riesch V4L2_CAP_IO_MC; 548*501802e2SMichael Riesch vdev->entity.ops = &rkcif_stream_media_ops; 549*501802e2SMichael Riesch vdev->fops = &rkcif_stream_file_ops; 550*501802e2SMichael Riesch vdev->ioctl_ops = &rkcif_stream_ioctl_ops; 551*501802e2SMichael Riesch vdev->lock = &stream->vlock; 552*501802e2SMichael Riesch vdev->minor = -1; 553*501802e2SMichael Riesch vdev->release = video_device_release_empty; 554*501802e2SMichael Riesch vdev->v4l2_dev = v4l2_dev; 555*501802e2SMichael Riesch vdev->vfl_dir = VFL_DIR_RX; 556*501802e2SMichael Riesch video_set_drvdata(vdev, stream); 557*501802e2SMichael Riesch 558*501802e2SMichael Riesch stream->pad.flags = MEDIA_PAD_FL_SINK; 559*501802e2SMichael Riesch 560*501802e2SMichael Riesch stream->pix.height = CIF_MIN_HEIGHT; 561*501802e2SMichael Riesch stream->pix.width = CIF_MIN_WIDTH; 562*501802e2SMichael Riesch rkcif_stream_fill_format(stream, &stream->pix); 563*501802e2SMichael Riesch 564*501802e2SMichael Riesch rkcif_stream_init_vb2_queue(&stream->buf_queue, stream); 565*501802e2SMichael Riesch 566*501802e2SMichael Riesch vdev->queue = &stream->buf_queue; 567*501802e2SMichael Riesch if (interface->type == RKCIF_IF_DVP) 568*501802e2SMichael Riesch snprintf(vdev->name, sizeof(vdev->name), "rkcif-dvp0-id%d", 569*501802e2SMichael Riesch stream->id); 570*501802e2SMichael Riesch else if (interface->type == RKCIF_IF_MIPI) 571*501802e2SMichael Riesch snprintf(vdev->name, sizeof(vdev->name), "rkcif-mipi%d-id%d", 572*501802e2SMichael Riesch interface->index - RKCIF_MIPI_BASE, stream->id); 573*501802e2SMichael Riesch 574*501802e2SMichael Riesch ret = media_entity_pads_init(&vdev->entity, 1, &stream->pad); 575*501802e2SMichael Riesch if (ret < 0) { 576*501802e2SMichael Riesch dev_err(rkcif->dev, 577*501802e2SMichael Riesch "failed to initialize stream media pad: %d\n", ret); 578*501802e2SMichael Riesch return ret; 579*501802e2SMichael Riesch } 580*501802e2SMichael Riesch 581*501802e2SMichael Riesch ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1); 582*501802e2SMichael Riesch if (ret < 0) { 583*501802e2SMichael Riesch dev_err(rkcif->dev, "failed to register video device: %d\n", 584*501802e2SMichael Riesch ret); 585*501802e2SMichael Riesch goto err_media_entity_cleanup; 586*501802e2SMichael Riesch } 587*501802e2SMichael Riesch 588*501802e2SMichael Riesch /* enable only stream ID0 by default */ 589*501802e2SMichael Riesch if (stream->id == RKCIF_ID0) 590*501802e2SMichael Riesch link_flags |= MEDIA_LNK_FL_ENABLED; 591*501802e2SMichael Riesch 592*501802e2SMichael Riesch ret = media_create_pad_link(&interface->sd.entity, RKCIF_IF_PAD_SRC, 593*501802e2SMichael Riesch &stream->vdev.entity, 0, link_flags); 594*501802e2SMichael Riesch if (ret) { 595*501802e2SMichael Riesch dev_err(rkcif->dev, "failed to link stream media pad: %d\n", 596*501802e2SMichael Riesch ret); 597*501802e2SMichael Riesch goto err_video_unregister; 598*501802e2SMichael Riesch } 599*501802e2SMichael Riesch 600*501802e2SMichael Riesch v4l2_info(v4l2_dev, "registered %s as /dev/video%d\n", vdev->name, 601*501802e2SMichael Riesch vdev->num); 602*501802e2SMichael Riesch 603*501802e2SMichael Riesch return 0; 604*501802e2SMichael Riesch 605*501802e2SMichael Riesch err_video_unregister: 606*501802e2SMichael Riesch video_unregister_device(&stream->vdev); 607*501802e2SMichael Riesch err_media_entity_cleanup: 608*501802e2SMichael Riesch media_entity_cleanup(&stream->vdev.entity); 609*501802e2SMichael Riesch return ret; 610*501802e2SMichael Riesch } 611*501802e2SMichael Riesch 612*501802e2SMichael Riesch void rkcif_stream_unregister(struct rkcif_stream *stream) 613*501802e2SMichael Riesch { 614*501802e2SMichael Riesch video_unregister_device(&stream->vdev); 615*501802e2SMichael Riesch media_entity_cleanup(&stream->vdev.entity); 616*501802e2SMichael Riesch } 617*501802e2SMichael Riesch 618*501802e2SMichael Riesch const struct rkcif_output_fmt * 619*501802e2SMichael Riesch rkcif_stream_find_output_fmt(struct rkcif_stream *stream, bool ret_def, 620*501802e2SMichael Riesch u32 pixelfmt) 621*501802e2SMichael Riesch { 622*501802e2SMichael Riesch const struct rkcif_output_fmt *fmt; 623*501802e2SMichael Riesch 624*501802e2SMichael Riesch WARN_ON(stream->out_fmts_num == 0); 625*501802e2SMichael Riesch 626*501802e2SMichael Riesch for (unsigned int i = 0; i < stream->out_fmts_num; i++) { 627*501802e2SMichael Riesch fmt = &stream->out_fmts[i]; 628*501802e2SMichael Riesch if (fmt->fourcc == pixelfmt) 629*501802e2SMichael Riesch return fmt; 630*501802e2SMichael Riesch } 631*501802e2SMichael Riesch 632*501802e2SMichael Riesch if (ret_def) 633*501802e2SMichael Riesch return &stream->out_fmts[0]; 634*501802e2SMichael Riesch else 635*501802e2SMichael Riesch return NULL; 636*501802e2SMichael Riesch } 637