^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * V4L2 Driver for Renesas Capture Engine Unit (CEU) interface
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (C) 2017-2018 Jacopo Mondi <jacopo+renesas@jmondi.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Based on soc-camera driver "soc_camera/sh_mobile_ceu_camera.c"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (C) 2008 Magnus Damm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Based on V4L2 Driver for PXA camera host - "pxa_camera.c",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Copyright (C) 2006, Sascha Hauer, Pengutronix
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/dma-mapping.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/of_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/of_graph.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/pm_runtime.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/time.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/videodev2.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <media/v4l2-async.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <media/v4l2-common.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <media/v4l2-ctrls.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <media/v4l2-dev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <media/v4l2-device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include <media/v4l2-event.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #include <media/v4l2-fwnode.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #include <media/v4l2-image-sizes.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #include <media/v4l2-ioctl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #include <media/v4l2-mediabus.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #include <media/videobuf2-dma-contig.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #include <media/drv-intf/renesas-ceu.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define DRIVER_NAME "renesas-ceu"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) /* CEU registers offsets and masks. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define CEU_CAPSR 0x00 /* Capture start register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define CEU_CAPCR 0x04 /* Capture control register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define CEU_CAMCR 0x08 /* Capture interface control register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define CEU_CAMOR 0x10 /* Capture interface offset register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define CEU_CAPWR 0x14 /* Capture interface width register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define CEU_CAIFR 0x18 /* Capture interface input format register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define CEU_CRCNTR 0x28 /* CEU register control register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define CEU_CRCMPR 0x2c /* CEU register forcible control register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define CEU_CFLCR 0x30 /* Capture filter control register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define CEU_CFSZR 0x34 /* Capture filter size clip register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define CEU_CDWDR 0x38 /* Capture destination width register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define CEU_CDAYR 0x3c /* Capture data address Y register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define CEU_CDACR 0x40 /* Capture data address C register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define CEU_CFWCR 0x5c /* Firewall operation control register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define CEU_CDOCR 0x64 /* Capture data output control register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define CEU_CEIER 0x70 /* Capture event interrupt enable register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define CEU_CETCR 0x74 /* Capture event flag clear register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define CEU_CSTSR 0x7c /* Capture status register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define CEU_CSRTR 0x80 /* Capture software reset register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) /* Data synchronous fetch mode. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define CEU_CAMCR_JPEG BIT(4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) /* Input components ordering: CEU_CAMCR.DTARY field. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #define CEU_CAMCR_DTARY_8_UYVY (0x00 << 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #define CEU_CAMCR_DTARY_8_VYUY (0x01 << 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define CEU_CAMCR_DTARY_8_YUYV (0x02 << 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define CEU_CAMCR_DTARY_8_YVYU (0x03 << 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) /* TODO: input components ordering for 16 bits input. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) /* Bus transfer MTU. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #define CEU_CAPCR_BUS_WIDTH256 (0x3 << 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) /* Bus width configuration. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #define CEU_CAMCR_DTIF_16BITS BIT(12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) /* No downsampling to planar YUV420 in image fetch mode. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #define CEU_CDOCR_NO_DOWSAMPLE BIT(4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) /* Swap all input data in 8-bit, 16-bits and 32-bits units (Figure 46.45). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #define CEU_CDOCR_SWAP_ENDIANNESS (7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) /* Capture reset and enable bits. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) #define CEU_CAPSR_CPKIL BIT(16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #define CEU_CAPSR_CE BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) /* CEU operating flag bit. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) #define CEU_CAPCR_CTNCP BIT(16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) #define CEU_CSTRST_CPTON BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) /* Platform specific IRQ source flags. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) #define CEU_CETCR_ALL_IRQS_RZ 0x397f313
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) #define CEU_CETCR_ALL_IRQS_SH4 0x3d7f313
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) /* Prohibited register access interrupt bit. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) #define CEU_CETCR_IGRW BIT(4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) /* One-frame capture end interrupt. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) #define CEU_CEIER_CPE BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) /* VBP error. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) #define CEU_CEIER_VBP BIT(20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) #define CEU_CEIER_MASK (CEU_CEIER_CPE | CEU_CEIER_VBP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) #define CEU_MAX_WIDTH 2560
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) #define CEU_MAX_HEIGHT 1920
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) #define CEU_MAX_BPL 8188
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) #define CEU_W_MAX(w) ((w) < CEU_MAX_WIDTH ? (w) : CEU_MAX_WIDTH)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) #define CEU_H_MAX(h) ((h) < CEU_MAX_HEIGHT ? (h) : CEU_MAX_HEIGHT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) * ceu_bus_fmt - describe a 8-bits yuyv format the sensor can produce
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) * @mbus_code: bus format code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) * @fmt_order: CEU_CAMCR.DTARY ordering of input components (Y, Cb, Cr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) * @fmt_order_swap: swapped CEU_CAMCR.DTARY ordering of input components
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) * (Y, Cr, Cb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) * @swapped: does Cr appear before Cb?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) * @bps: number of bits sent over bus for each sample
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) * @bpp: number of bits per pixels unit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) struct ceu_mbus_fmt {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) u32 mbus_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) u32 fmt_order;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) u32 fmt_order_swap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) bool swapped;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) u8 bps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) u8 bpp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) * ceu_buffer - Link vb2 buffer to the list of available buffers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) struct ceu_buffer {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) struct vb2_v4l2_buffer vb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) struct list_head queue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) static inline struct ceu_buffer *vb2_to_ceu(struct vb2_v4l2_buffer *vbuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) return container_of(vbuf, struct ceu_buffer, vb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) * ceu_subdev - Wraps v4l2 sub-device and provides async subdevice.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) struct ceu_subdev {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) struct v4l2_subdev *v4l2_sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) struct v4l2_async_subdev asd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) /* per-subdevice mbus configuration options */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) unsigned int mbus_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) struct ceu_mbus_fmt mbus_fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) static struct ceu_subdev *to_ceu_subdev(struct v4l2_async_subdev *asd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) return container_of(asd, struct ceu_subdev, asd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) * ceu_device - CEU device instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) struct ceu_device {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) struct device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) struct video_device vdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) struct v4l2_device v4l2_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) /* subdevices descriptors */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) struct ceu_subdev *subdevs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) /* the subdevice currently in use */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) struct ceu_subdev *sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) unsigned int sd_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) unsigned int num_sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) /* platform specific mask with all IRQ sources flagged */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) u32 irq_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) /* currently configured field and pixel format */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) enum v4l2_field field;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) struct v4l2_pix_format_mplane v4l2_pix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) /* async subdev notification helpers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) struct v4l2_async_notifier notifier;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) /* vb2 queue, capture buffer list and active buffer pointer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) struct vb2_queue vb2_vq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) struct list_head capture;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) struct vb2_v4l2_buffer *active;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) unsigned int sequence;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) /* mlock - lock access to interface reset and vb2 queue */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) struct mutex mlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) /* lock - lock access to capture buffer queue and active buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) spinlock_t lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) /* base - CEU memory base address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) void __iomem *base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) static inline struct ceu_device *v4l2_to_ceu(struct v4l2_device *v4l2_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) return container_of(v4l2_dev, struct ceu_device, v4l2_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) /* --- CEU memory output formats --- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) * ceu_fmt - describe a memory output format supported by CEU interface.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) * @fourcc: memory layout fourcc format code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) * @bpp: number of bits for each pixel stored in memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) struct ceu_fmt {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) u32 fourcc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) u32 bpp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) * ceu_format_list - List of supported memory output formats
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) * If sensor provides any YUYV bus format, all the following planar memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) * formats are available thanks to CEU re-ordering and sub-sampling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) * capabilities.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) static const struct ceu_fmt ceu_fmt_list[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) .fourcc = V4L2_PIX_FMT_NV16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) .bpp = 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) .fourcc = V4L2_PIX_FMT_NV61,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) .bpp = 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) .fourcc = V4L2_PIX_FMT_NV12,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) .bpp = 12,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) .fourcc = V4L2_PIX_FMT_NV21,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) .bpp = 12,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) .fourcc = V4L2_PIX_FMT_YUYV,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) .bpp = 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) .fourcc = V4L2_PIX_FMT_UYVY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) .bpp = 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) .fourcc = V4L2_PIX_FMT_YVYU,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) .bpp = 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) .fourcc = V4L2_PIX_FMT_VYUY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) .bpp = 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) static const struct ceu_fmt *get_ceu_fmt_from_fourcc(unsigned int fourcc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) const struct ceu_fmt *fmt = &ceu_fmt_list[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) for (i = 0; i < ARRAY_SIZE(ceu_fmt_list); i++, fmt++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) if (fmt->fourcc == fourcc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) return fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) static bool ceu_fmt_mplane(struct v4l2_pix_format_mplane *pix)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) switch (pix->pixelformat) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) case V4L2_PIX_FMT_YUYV:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) case V4L2_PIX_FMT_UYVY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) case V4L2_PIX_FMT_YVYU:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) case V4L2_PIX_FMT_VYUY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) case V4L2_PIX_FMT_NV16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) case V4L2_PIX_FMT_NV61:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) case V4L2_PIX_FMT_NV12:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) case V4L2_PIX_FMT_NV21:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) /* --- CEU HW operations --- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) static void ceu_write(struct ceu_device *priv, unsigned int reg_offs, u32 data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) iowrite32(data, priv->base + reg_offs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) static u32 ceu_read(struct ceu_device *priv, unsigned int reg_offs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) return ioread32(priv->base + reg_offs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) * ceu_soft_reset() - Software reset the CEU interface.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) * @ceu_device: CEU device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) * Returns 0 for success, -EIO for error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) static int ceu_soft_reset(struct ceu_device *ceudev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) ceu_write(ceudev, CEU_CAPSR, CEU_CAPSR_CPKIL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) for (i = 0; i < 100; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) if (!(ceu_read(ceudev, CEU_CSTSR) & CEU_CSTRST_CPTON))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) if (i == 100) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) dev_err(ceudev->dev, "soft reset time out\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) for (i = 0; i < 100; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) if (!(ceu_read(ceudev, CEU_CAPSR) & CEU_CAPSR_CPKIL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) /* If we get here, CEU has not reset properly. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) /* --- CEU Capture Operations --- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) * ceu_hw_config() - Configure CEU interface registers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) static int ceu_hw_config(struct ceu_device *ceudev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) u32 camcr, cdocr, cfzsr, cdwdr, capwr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) struct v4l2_pix_format_mplane *pix = &ceudev->v4l2_pix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) struct ceu_subdev *ceu_sd = ceudev->sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) struct ceu_mbus_fmt *mbus_fmt = &ceu_sd->mbus_fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) unsigned int mbus_flags = ceu_sd->mbus_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) /* Start configuring CEU registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) ceu_write(ceudev, CEU_CAIFR, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) ceu_write(ceudev, CEU_CFWCR, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) ceu_write(ceudev, CEU_CRCNTR, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) ceu_write(ceudev, CEU_CRCMPR, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) /* Set the frame capture period for both image capture and data sync. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) capwr = (pix->height << 16) | pix->width * mbus_fmt->bpp / 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) * Swap input data endianness by default.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) * In data fetch mode bytes are received in chunks of 8 bytes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) * D0, D1, D2, D3, D4, D5, D6, D7 (D0 received first)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) * The data is however by default written to memory in reverse order:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) * D7, D6, D5, D4, D3, D2, D1, D0 (D7 written to lowest byte)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) * Use CEU_CDOCR[2:0] to swap data ordering.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) cdocr = CEU_CDOCR_SWAP_ENDIANNESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) * Configure CAMCR and CDOCR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) * match input components ordering with memory output format and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) * handle downsampling to YUV420.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) * If the memory output planar format is 'swapped' (Cr before Cb) and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) * input format is not, use the swapped version of CAMCR.DTARY.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) * If the memory output planar format is not 'swapped' (Cb before Cr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) * and input format is, use the swapped version of CAMCR.DTARY.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) * CEU by default downsample to planar YUV420 (CDCOR[4] = 0).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) * If output is planar YUV422 set CDOCR[4] = 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) * No downsample for data fetch sync mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) switch (pix->pixelformat) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) /* Data fetch sync mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) case V4L2_PIX_FMT_YUYV:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) case V4L2_PIX_FMT_YVYU:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) case V4L2_PIX_FMT_UYVY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) case V4L2_PIX_FMT_VYUY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) camcr = CEU_CAMCR_JPEG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) cdocr |= CEU_CDOCR_NO_DOWSAMPLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) cfzsr = (pix->height << 16) | pix->width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) cdwdr = pix->plane_fmt[0].bytesperline;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) /* Non-swapped planar image capture mode. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) case V4L2_PIX_FMT_NV16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) cdocr |= CEU_CDOCR_NO_DOWSAMPLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) case V4L2_PIX_FMT_NV12:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) if (mbus_fmt->swapped)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) camcr = mbus_fmt->fmt_order_swap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) camcr = mbus_fmt->fmt_order;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) cfzsr = (pix->height << 16) | pix->width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) cdwdr = pix->width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) /* Swapped planar image capture mode. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) case V4L2_PIX_FMT_NV61:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) cdocr |= CEU_CDOCR_NO_DOWSAMPLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) case V4L2_PIX_FMT_NV21:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) if (mbus_fmt->swapped)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) camcr = mbus_fmt->fmt_order;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) camcr = mbus_fmt->fmt_order_swap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) cfzsr = (pix->height << 16) | pix->width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) cdwdr = pix->width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) camcr |= mbus_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW ? 1 << 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) camcr |= mbus_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW ? 1 << 0 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) /* TODO: handle 16 bit bus width with DTIF bit in CAMCR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) ceu_write(ceudev, CEU_CAMCR, camcr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) ceu_write(ceudev, CEU_CDOCR, cdocr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) ceu_write(ceudev, CEU_CAPCR, CEU_CAPCR_BUS_WIDTH256);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) * TODO: make CAMOR offsets configurable.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) * CAMOR wants to know the number of blanks between a VS/HS signal
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) * and valid data. This value should actually come from the sensor...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) ceu_write(ceudev, CEU_CAMOR, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) /* TODO: 16 bit bus width require re-calculation of cdwdr and cfzsr */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) ceu_write(ceudev, CEU_CAPWR, capwr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) ceu_write(ceudev, CEU_CFSZR, cfzsr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) ceu_write(ceudev, CEU_CDWDR, cdwdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) * ceu_capture() - Trigger start of a capture sequence.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) * Program the CEU DMA registers with addresses where to transfer image data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) static int ceu_capture(struct ceu_device *ceudev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) struct v4l2_pix_format_mplane *pix = &ceudev->v4l2_pix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) dma_addr_t phys_addr_top;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) phys_addr_top =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) vb2_dma_contig_plane_dma_addr(&ceudev->active->vb2_buf, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) ceu_write(ceudev, CEU_CDAYR, phys_addr_top);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) /* Ignore CbCr plane for non multi-planar image formats. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) if (ceu_fmt_mplane(pix)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) phys_addr_top =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) vb2_dma_contig_plane_dma_addr(&ceudev->active->vb2_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) ceu_write(ceudev, CEU_CDACR, phys_addr_top);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) * Trigger new capture start: once for each frame, as we work in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) * one-frame capture mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) ceu_write(ceudev, CEU_CAPSR, CEU_CAPSR_CE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) static irqreturn_t ceu_irq(int irq, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) struct ceu_device *ceudev = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) struct vb2_v4l2_buffer *vbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) struct ceu_buffer *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) u32 status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) /* Clean interrupt status. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) status = ceu_read(ceudev, CEU_CETCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) ceu_write(ceudev, CEU_CETCR, ~ceudev->irq_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) /* Unexpected interrupt. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) if (!(status & CEU_CEIER_MASK))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) return IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) spin_lock(&ceudev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) /* Stale interrupt from a released buffer, ignore it. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) vbuf = ceudev->active;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) if (!vbuf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) spin_unlock(&ceudev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) * When a VBP interrupt occurs, no capture end interrupt will occur
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) * and the image of that frame is not captured correctly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) if (status & CEU_CEIER_VBP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) dev_err(ceudev->dev, "VBP interrupt: abort capture\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) goto error_irq_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) /* Prepare to return the 'previous' buffer. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) vbuf->vb2_buf.timestamp = ktime_get_ns();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) vbuf->sequence = ceudev->sequence++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) vbuf->field = ceudev->field;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) /* Prepare a new 'active' buffer and trigger a new capture. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) if (!list_empty(&ceudev->capture)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) buf = list_first_entry(&ceudev->capture, struct ceu_buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) list_del(&buf->queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) ceudev->active = &buf->vb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) ceu_capture(ceudev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) /* Return the 'previous' buffer. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) vb2_buffer_done(&vbuf->vb2_buf, VB2_BUF_STATE_DONE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) spin_unlock(&ceudev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) error_irq_out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) /* Return the 'previous' buffer and all queued ones. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) vb2_buffer_done(&vbuf->vb2_buf, VB2_BUF_STATE_ERROR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) list_for_each_entry(buf, &ceudev->capture, queue)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) spin_unlock(&ceudev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) /* --- CEU Videobuf2 operations --- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) static void ceu_update_plane_sizes(struct v4l2_plane_pix_format *plane,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) unsigned int bpl, unsigned int szimage)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) memset(plane, 0, sizeof(*plane));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) plane->sizeimage = szimage;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) if (plane->bytesperline < bpl || plane->bytesperline > CEU_MAX_BPL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) plane->bytesperline = bpl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) * ceu_calc_plane_sizes() - Fill per-plane 'struct v4l2_plane_pix_format'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) * information according to the currently configured
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) * pixel format.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) * @ceu_device: CEU device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) * @ceu_fmt: Active image format.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) * @pix: Pixel format information (store line width and image sizes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) static void ceu_calc_plane_sizes(struct ceu_device *ceudev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) const struct ceu_fmt *ceu_fmt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) struct v4l2_pix_format_mplane *pix)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) unsigned int bpl, szimage;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) switch (pix->pixelformat) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) case V4L2_PIX_FMT_YUYV:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) case V4L2_PIX_FMT_UYVY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) case V4L2_PIX_FMT_YVYU:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) case V4L2_PIX_FMT_VYUY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) pix->num_planes = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) bpl = pix->width * ceu_fmt->bpp / 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) szimage = pix->height * bpl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) ceu_update_plane_sizes(&pix->plane_fmt[0], bpl, szimage);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) case V4L2_PIX_FMT_NV12:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) case V4L2_PIX_FMT_NV21:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) pix->num_planes = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) bpl = pix->width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) szimage = pix->height * pix->width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) ceu_update_plane_sizes(&pix->plane_fmt[0], bpl, szimage);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) ceu_update_plane_sizes(&pix->plane_fmt[1], bpl, szimage / 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) case V4L2_PIX_FMT_NV16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) case V4L2_PIX_FMT_NV61:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) pix->num_planes = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) bpl = pix->width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) szimage = pix->height * pix->width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) ceu_update_plane_sizes(&pix->plane_fmt[0], bpl, szimage);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) ceu_update_plane_sizes(&pix->plane_fmt[1], bpl, szimage);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) * ceu_vb2_setup() - is called to check whether the driver can accept the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) * requested number of buffers and to fill in plane sizes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) * for the current frame format, if required.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) static int ceu_vb2_setup(struct vb2_queue *vq, unsigned int *count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) unsigned int *num_planes, unsigned int sizes[],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) struct device *alloc_devs[])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) struct ceu_device *ceudev = vb2_get_drv_priv(vq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) struct v4l2_pix_format_mplane *pix = &ceudev->v4l2_pix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) /* num_planes is set: just check plane sizes. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) if (*num_planes) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) for (i = 0; i < pix->num_planes; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) if (sizes[i] < pix->plane_fmt[i].sizeimage)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) /* num_planes not set: called from REQBUFS, just set plane sizes. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) *num_planes = pix->num_planes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) for (i = 0; i < pix->num_planes; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) sizes[i] = pix->plane_fmt[i].sizeimage;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) static void ceu_vb2_queue(struct vb2_buffer *vb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) struct ceu_device *ceudev = vb2_get_drv_priv(vb->vb2_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) struct ceu_buffer *buf = vb2_to_ceu(vbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) unsigned long irqflags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) spin_lock_irqsave(&ceudev->lock, irqflags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) list_add_tail(&buf->queue, &ceudev->capture);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) spin_unlock_irqrestore(&ceudev->lock, irqflags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) static int ceu_vb2_prepare(struct vb2_buffer *vb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) struct ceu_device *ceudev = vb2_get_drv_priv(vb->vb2_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) struct v4l2_pix_format_mplane *pix = &ceudev->v4l2_pix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) for (i = 0; i < pix->num_planes; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) if (vb2_plane_size(vb, i) < pix->plane_fmt[i].sizeimage) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) dev_err(ceudev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) "Plane size too small (%lu < %u)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) vb2_plane_size(vb, i),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) pix->plane_fmt[i].sizeimage);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) vb2_set_plane_payload(vb, i, pix->plane_fmt[i].sizeimage);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) static int ceu_start_streaming(struct vb2_queue *vq, unsigned int count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) struct ceu_device *ceudev = vb2_get_drv_priv(vq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) struct v4l2_subdev *v4l2_sd = ceudev->sd->v4l2_sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) struct ceu_buffer *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) unsigned long irqflags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) /* Program the CEU interface according to the CEU image format. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) ret = ceu_hw_config(ceudev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) goto error_return_bufs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) ret = v4l2_subdev_call(v4l2_sd, video, s_stream, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) if (ret && ret != -ENOIOCTLCMD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) dev_dbg(ceudev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) "Subdevice failed to start streaming: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) goto error_return_bufs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) spin_lock_irqsave(&ceudev->lock, irqflags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) ceudev->sequence = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) /* Grab the first available buffer and trigger the first capture. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) buf = list_first_entry(&ceudev->capture, struct ceu_buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) if (!buf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) spin_unlock_irqrestore(&ceudev->lock, irqflags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) dev_dbg(ceudev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) "No buffer available for capture.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) goto error_stop_sensor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) list_del(&buf->queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) ceudev->active = &buf->vb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) /* Clean and program interrupts for first capture. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) ceu_write(ceudev, CEU_CETCR, ~ceudev->irq_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) ceu_write(ceudev, CEU_CEIER, CEU_CEIER_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) ceu_capture(ceudev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) spin_unlock_irqrestore(&ceudev->lock, irqflags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) error_stop_sensor:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) v4l2_subdev_call(v4l2_sd, video, s_stream, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) error_return_bufs:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) spin_lock_irqsave(&ceudev->lock, irqflags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) list_for_each_entry(buf, &ceudev->capture, queue)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) vb2_buffer_done(&ceudev->active->vb2_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) VB2_BUF_STATE_QUEUED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) ceudev->active = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) spin_unlock_irqrestore(&ceudev->lock, irqflags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) static void ceu_stop_streaming(struct vb2_queue *vq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) struct ceu_device *ceudev = vb2_get_drv_priv(vq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) struct v4l2_subdev *v4l2_sd = ceudev->sd->v4l2_sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) struct ceu_buffer *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) unsigned long irqflags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) /* Clean and disable interrupt sources. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) ceu_write(ceudev, CEU_CETCR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) ceu_read(ceudev, CEU_CETCR) & ceudev->irq_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) ceu_write(ceudev, CEU_CEIER, CEU_CEIER_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) v4l2_subdev_call(v4l2_sd, video, s_stream, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) spin_lock_irqsave(&ceudev->lock, irqflags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) if (ceudev->active) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) vb2_buffer_done(&ceudev->active->vb2_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) VB2_BUF_STATE_ERROR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) ceudev->active = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) /* Release all queued buffers. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) list_for_each_entry(buf, &ceudev->capture, queue)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) INIT_LIST_HEAD(&ceudev->capture);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) spin_unlock_irqrestore(&ceudev->lock, irqflags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) ceu_soft_reset(ceudev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) static const struct vb2_ops ceu_vb2_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) .queue_setup = ceu_vb2_setup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) .buf_queue = ceu_vb2_queue,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) .buf_prepare = ceu_vb2_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) .wait_prepare = vb2_ops_wait_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) .wait_finish = vb2_ops_wait_finish,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) .start_streaming = ceu_start_streaming,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) .stop_streaming = ceu_stop_streaming,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) /* --- CEU image formats handling --- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) * __ceu_try_fmt() - test format on CEU and sensor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) * @ceudev: The CEU device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) * @v4l2_fmt: format to test.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) * @sd_mbus_code: the media bus code accepted by the subdevice; output param.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) * Returns 0 for success, < 0 for errors.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) static int __ceu_try_fmt(struct ceu_device *ceudev, struct v4l2_format *v4l2_fmt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) u32 *sd_mbus_code)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) struct ceu_subdev *ceu_sd = ceudev->sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) struct v4l2_pix_format_mplane *pix = &v4l2_fmt->fmt.pix_mp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) struct v4l2_subdev *v4l2_sd = ceu_sd->v4l2_sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) struct v4l2_subdev_pad_config pad_cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) const struct ceu_fmt *ceu_fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) u32 mbus_code_old;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) u32 mbus_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) * Set format on sensor sub device: bus format used to produce memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) * format is selected depending on YUV component ordering or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) * at initialization time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) struct v4l2_subdev_format sd_format = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) .which = V4L2_SUBDEV_FORMAT_TRY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) mbus_code_old = ceu_sd->mbus_fmt.mbus_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) switch (pix->pixelformat) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) case V4L2_PIX_FMT_YUYV:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) mbus_code = MEDIA_BUS_FMT_YUYV8_2X8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) case V4L2_PIX_FMT_UYVY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) mbus_code = MEDIA_BUS_FMT_UYVY8_2X8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) case V4L2_PIX_FMT_YVYU:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) mbus_code = MEDIA_BUS_FMT_YVYU8_2X8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) case V4L2_PIX_FMT_VYUY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) mbus_code = MEDIA_BUS_FMT_VYUY8_2X8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) case V4L2_PIX_FMT_NV16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) case V4L2_PIX_FMT_NV61:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) case V4L2_PIX_FMT_NV12:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) case V4L2_PIX_FMT_NV21:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) mbus_code = ceu_sd->mbus_fmt.mbus_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) pix->pixelformat = V4L2_PIX_FMT_NV16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) mbus_code = ceu_sd->mbus_fmt.mbus_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) ceu_fmt = get_ceu_fmt_from_fourcc(pix->pixelformat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) /* CFSZR requires height and width to be 4-pixel aligned. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) v4l_bound_align_image(&pix->width, 2, CEU_MAX_WIDTH, 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) &pix->height, 4, CEU_MAX_HEIGHT, 4, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) v4l2_fill_mbus_format_mplane(&sd_format.format, pix);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) * Try with the mbus_code matching YUYV components ordering first,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) * if that one fails, fallback to default selected at initialization
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) * time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) sd_format.format.code = mbus_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) ret = v4l2_subdev_call(v4l2_sd, pad, set_fmt, &pad_cfg, &sd_format);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) if (ret == -EINVAL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) /* fallback */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) sd_format.format.code = mbus_code_old;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) ret = v4l2_subdev_call(v4l2_sd, pad, set_fmt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) &pad_cfg, &sd_format);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) /* Apply size returned by sensor as the CEU can't scale. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) v4l2_fill_pix_format_mplane(pix, &sd_format.format);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) /* Calculate per-plane sizes based on image format. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) ceu_calc_plane_sizes(ceudev, ceu_fmt, pix);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) /* Report to caller the configured mbus format. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) *sd_mbus_code = sd_format.format.code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) * ceu_try_fmt() - Wrapper for __ceu_try_fmt; discard configured mbus_fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) static int ceu_try_fmt(struct ceu_device *ceudev, struct v4l2_format *v4l2_fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) u32 mbus_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) return __ceu_try_fmt(ceudev, v4l2_fmt, &mbus_code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) * ceu_set_fmt() - Apply the supplied format to both sensor and CEU
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) static int ceu_set_fmt(struct ceu_device *ceudev, struct v4l2_format *v4l2_fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) struct ceu_subdev *ceu_sd = ceudev->sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) struct v4l2_subdev *v4l2_sd = ceu_sd->v4l2_sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) u32 mbus_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) * Set format on sensor sub device: bus format used to produce memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) * format is selected at initialization time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) struct v4l2_subdev_format format = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) .which = V4L2_SUBDEV_FORMAT_ACTIVE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) ret = __ceu_try_fmt(ceudev, v4l2_fmt, &mbus_code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) format.format.code = mbus_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) v4l2_fill_mbus_format_mplane(&format.format, &v4l2_fmt->fmt.pix_mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) ret = v4l2_subdev_call(v4l2_sd, pad, set_fmt, NULL, &format);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) ceudev->v4l2_pix = v4l2_fmt->fmt.pix_mp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) ceudev->field = V4L2_FIELD_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) * ceu_set_default_fmt() - Apply default NV16 memory output format with VGA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) * sizes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) static int ceu_set_default_fmt(struct ceu_device *ceudev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) struct v4l2_format v4l2_fmt = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) .fmt.pix_mp = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) .width = VGA_WIDTH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) .height = VGA_HEIGHT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) .field = V4L2_FIELD_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) .pixelformat = V4L2_PIX_FMT_NV16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) .num_planes = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) .plane_fmt = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) [0] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) .sizeimage = VGA_WIDTH * VGA_HEIGHT * 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) .bytesperline = VGA_WIDTH * 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) [1] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) .sizeimage = VGA_WIDTH * VGA_HEIGHT * 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) .bytesperline = VGA_WIDTH * 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) ret = ceu_try_fmt(ceudev, &v4l2_fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) ceudev->v4l2_pix = v4l2_fmt.fmt.pix_mp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) ceudev->field = V4L2_FIELD_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) * ceu_init_mbus_fmt() - Query sensor for supported formats and initialize
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) * CEU media bus format used to produce memory formats.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) * Find out if sensor can produce a permutation of 8-bits YUYV bus format.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) * From a single 8-bits YUYV bus format the CEU can produce several memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) * output formats:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) * - NV[12|21|16|61] through image fetch mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) * - YUYV422 if sensor provides YUYV422
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) * TODO: Other YUYV422 permutations through data fetch sync mode and DTARY
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) * TODO: Binary data (eg. JPEG) and raw formats through data fetch sync mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) static int ceu_init_mbus_fmt(struct ceu_device *ceudev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) struct ceu_subdev *ceu_sd = ceudev->sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) struct ceu_mbus_fmt *mbus_fmt = &ceu_sd->mbus_fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) struct v4l2_subdev *v4l2_sd = ceu_sd->v4l2_sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) bool yuyv_bus_fmt = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) struct v4l2_subdev_mbus_code_enum sd_mbus_fmt = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) .which = V4L2_SUBDEV_FORMAT_ACTIVE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) .index = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) /* Find out if sensor can produce any permutation of 8-bits YUYV422. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) while (!yuyv_bus_fmt &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) !v4l2_subdev_call(v4l2_sd, pad, enum_mbus_code,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) NULL, &sd_mbus_fmt)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) switch (sd_mbus_fmt.code) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) case MEDIA_BUS_FMT_YUYV8_2X8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) case MEDIA_BUS_FMT_YVYU8_2X8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) case MEDIA_BUS_FMT_UYVY8_2X8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) case MEDIA_BUS_FMT_VYUY8_2X8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) yuyv_bus_fmt = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) * Only support 8-bits YUYV bus formats at the moment;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) * TODO: add support for binary formats (data sync
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) * fetch mode).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) sd_mbus_fmt.index++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) if (!yuyv_bus_fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) * Save the first encountered YUYV format as "mbus_fmt" and use it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) * to output all planar YUV422 and YUV420 (NV*) formats to memory as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) * well as for data synch fetch mode (YUYV - YVYU etc. ).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) mbus_fmt->mbus_code = sd_mbus_fmt.code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) mbus_fmt->bps = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) /* Annotate the selected bus format components ordering. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) switch (sd_mbus_fmt.code) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) case MEDIA_BUS_FMT_YUYV8_2X8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) mbus_fmt->fmt_order = CEU_CAMCR_DTARY_8_YUYV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) mbus_fmt->fmt_order_swap = CEU_CAMCR_DTARY_8_YVYU;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) mbus_fmt->swapped = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) mbus_fmt->bpp = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) case MEDIA_BUS_FMT_YVYU8_2X8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) mbus_fmt->fmt_order = CEU_CAMCR_DTARY_8_YVYU;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) mbus_fmt->fmt_order_swap = CEU_CAMCR_DTARY_8_YUYV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) mbus_fmt->swapped = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) mbus_fmt->bpp = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) case MEDIA_BUS_FMT_UYVY8_2X8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) mbus_fmt->fmt_order = CEU_CAMCR_DTARY_8_UYVY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) mbus_fmt->fmt_order_swap = CEU_CAMCR_DTARY_8_VYUY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) mbus_fmt->swapped = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) mbus_fmt->bpp = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) case MEDIA_BUS_FMT_VYUY8_2X8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) mbus_fmt->fmt_order = CEU_CAMCR_DTARY_8_VYUY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) mbus_fmt->fmt_order_swap = CEU_CAMCR_DTARY_8_UYVY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) mbus_fmt->swapped = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) mbus_fmt->bpp = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) /* --- Runtime PM Handlers --- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) * ceu_runtime_resume() - soft-reset the interface and turn sensor power on.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) static int __maybe_unused ceu_runtime_resume(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) struct ceu_device *ceudev = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) struct v4l2_subdev *v4l2_sd = ceudev->sd->v4l2_sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) v4l2_subdev_call(v4l2_sd, core, s_power, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) ceu_soft_reset(ceudev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) * ceu_runtime_suspend() - disable capture and interrupts and soft-reset.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) * Turn sensor power off.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) static int __maybe_unused ceu_runtime_suspend(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) struct ceu_device *ceudev = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) struct v4l2_subdev *v4l2_sd = ceudev->sd->v4l2_sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) v4l2_subdev_call(v4l2_sd, core, s_power, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) ceu_write(ceudev, CEU_CEIER, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) ceu_soft_reset(ceudev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) /* --- File Operations --- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) static int ceu_open(struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) struct ceu_device *ceudev = video_drvdata(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) ret = v4l2_fh_open(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) mutex_lock(&ceudev->mlock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) /* Causes soft-reset and sensor power on on first open */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) pm_runtime_get_sync(ceudev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) mutex_unlock(&ceudev->mlock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) static int ceu_release(struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) struct ceu_device *ceudev = video_drvdata(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) vb2_fop_release(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) mutex_lock(&ceudev->mlock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) /* Causes soft-reset and sensor power down on last close */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) pm_runtime_put(ceudev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) mutex_unlock(&ceudev->mlock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) static const struct v4l2_file_operations ceu_fops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) .open = ceu_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) .release = ceu_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) .unlocked_ioctl = video_ioctl2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) .mmap = vb2_fop_mmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) .poll = vb2_fop_poll,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) /* --- Video Device IOCTLs --- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) static int ceu_querycap(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) struct v4l2_capability *cap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) struct ceu_device *ceudev = video_drvdata(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) strscpy(cap->card, "Renesas CEU", sizeof(cap->card));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) strscpy(cap->driver, DRIVER_NAME, sizeof(cap->driver));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) snprintf(cap->bus_info, sizeof(cap->bus_info),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) "platform:renesas-ceu-%s", dev_name(ceudev->dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) static int ceu_enum_fmt_vid_cap(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) struct v4l2_fmtdesc *f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) const struct ceu_fmt *fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) if (f->index >= ARRAY_SIZE(ceu_fmt_list))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) fmt = &ceu_fmt_list[f->index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) f->pixelformat = fmt->fourcc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) static int ceu_try_fmt_vid_cap(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) struct v4l2_format *f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) struct ceu_device *ceudev = video_drvdata(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) return ceu_try_fmt(ceudev, f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) static int ceu_s_fmt_vid_cap(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) struct v4l2_format *f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) struct ceu_device *ceudev = video_drvdata(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) if (vb2_is_streaming(&ceudev->vb2_vq))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) return ceu_set_fmt(ceudev, f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) static int ceu_g_fmt_vid_cap(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) struct v4l2_format *f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) struct ceu_device *ceudev = video_drvdata(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) f->fmt.pix_mp = ceudev->v4l2_pix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) static int ceu_enum_input(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) struct v4l2_input *inp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) struct ceu_device *ceudev = video_drvdata(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) struct ceu_subdev *ceusd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) if (inp->index >= ceudev->num_sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) ceusd = &ceudev->subdevs[inp->index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) inp->type = V4L2_INPUT_TYPE_CAMERA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) inp->std = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) snprintf(inp->name, sizeof(inp->name), "Camera%u: %s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) inp->index, ceusd->v4l2_sd->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) static int ceu_g_input(struct file *file, void *priv, unsigned int *i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) struct ceu_device *ceudev = video_drvdata(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) *i = ceudev->sd_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) static int ceu_s_input(struct file *file, void *priv, unsigned int i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) struct ceu_device *ceudev = video_drvdata(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) struct ceu_subdev *ceu_sd_old;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) if (i >= ceudev->num_sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) if (vb2_is_streaming(&ceudev->vb2_vq))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) if (i == ceudev->sd_index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) ceu_sd_old = ceudev->sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) ceudev->sd = &ceudev->subdevs[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) * Make sure we can generate output image formats and apply
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) * default one.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) ret = ceu_init_mbus_fmt(ceudev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) ceudev->sd = ceu_sd_old;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) ret = ceu_set_default_fmt(ceudev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) ceudev->sd = ceu_sd_old;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) /* Now that we're sure we can use the sensor, power off the old one. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) v4l2_subdev_call(ceu_sd_old->v4l2_sd, core, s_power, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) v4l2_subdev_call(ceudev->sd->v4l2_sd, core, s_power, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) ceudev->sd_index = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) static int ceu_g_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) struct ceu_device *ceudev = video_drvdata(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) return v4l2_g_parm_cap(video_devdata(file), ceudev->sd->v4l2_sd, a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) static int ceu_s_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) struct ceu_device *ceudev = video_drvdata(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) return v4l2_s_parm_cap(video_devdata(file), ceudev->sd->v4l2_sd, a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) static int ceu_enum_framesizes(struct file *file, void *fh,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) struct v4l2_frmsizeenum *fsize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) struct ceu_device *ceudev = video_drvdata(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) struct ceu_subdev *ceu_sd = ceudev->sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) const struct ceu_fmt *ceu_fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) struct v4l2_subdev *v4l2_sd = ceu_sd->v4l2_sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) struct v4l2_subdev_frame_size_enum fse = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) .code = ceu_sd->mbus_fmt.mbus_code,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) .index = fsize->index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) .which = V4L2_SUBDEV_FORMAT_ACTIVE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) /* Just check if user supplied pixel format is supported. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) ceu_fmt = get_ceu_fmt_from_fourcc(fsize->pixel_format);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) if (!ceu_fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) ret = v4l2_subdev_call(v4l2_sd, pad, enum_frame_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) NULL, &fse);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) fsize->discrete.width = CEU_W_MAX(fse.max_width);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) fsize->discrete.height = CEU_H_MAX(fse.max_height);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) static int ceu_enum_frameintervals(struct file *file, void *fh,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) struct v4l2_frmivalenum *fival)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) struct ceu_device *ceudev = video_drvdata(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) struct ceu_subdev *ceu_sd = ceudev->sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) const struct ceu_fmt *ceu_fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) struct v4l2_subdev *v4l2_sd = ceu_sd->v4l2_sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) struct v4l2_subdev_frame_interval_enum fie = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) .code = ceu_sd->mbus_fmt.mbus_code,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) .index = fival->index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) .width = fival->width,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) .height = fival->height,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) .which = V4L2_SUBDEV_FORMAT_ACTIVE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) /* Just check if user supplied pixel format is supported. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) ceu_fmt = get_ceu_fmt_from_fourcc(fival->pixel_format);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) if (!ceu_fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) ret = v4l2_subdev_call(v4l2_sd, pad, enum_frame_interval, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) &fie);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) fival->discrete = fie.interval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) static const struct v4l2_ioctl_ops ceu_ioctl_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) .vidioc_querycap = ceu_querycap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) .vidioc_enum_fmt_vid_cap = ceu_enum_fmt_vid_cap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) .vidioc_try_fmt_vid_cap_mplane = ceu_try_fmt_vid_cap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) .vidioc_s_fmt_vid_cap_mplane = ceu_s_fmt_vid_cap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) .vidioc_g_fmt_vid_cap_mplane = ceu_g_fmt_vid_cap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) .vidioc_enum_input = ceu_enum_input,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) .vidioc_g_input = ceu_g_input,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) .vidioc_s_input = ceu_s_input,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) .vidioc_reqbufs = vb2_ioctl_reqbufs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) .vidioc_querybuf = vb2_ioctl_querybuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) .vidioc_qbuf = vb2_ioctl_qbuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) .vidioc_expbuf = vb2_ioctl_expbuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) .vidioc_dqbuf = vb2_ioctl_dqbuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) .vidioc_create_bufs = vb2_ioctl_create_bufs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) .vidioc_streamon = vb2_ioctl_streamon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) .vidioc_streamoff = vb2_ioctl_streamoff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) .vidioc_g_parm = ceu_g_parm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) .vidioc_s_parm = ceu_s_parm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) .vidioc_enum_framesizes = ceu_enum_framesizes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) .vidioc_enum_frameintervals = ceu_enum_frameintervals,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) .vidioc_log_status = v4l2_ctrl_log_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) * ceu_vdev_release() - release CEU video device memory when last reference
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) * to this driver is closed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) static void ceu_vdev_release(struct video_device *vdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) struct ceu_device *ceudev = video_get_drvdata(vdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) kfree(ceudev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) static int ceu_notify_bound(struct v4l2_async_notifier *notifier,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) struct v4l2_subdev *v4l2_sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) struct v4l2_async_subdev *asd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) struct v4l2_device *v4l2_dev = notifier->v4l2_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) struct ceu_device *ceudev = v4l2_to_ceu(v4l2_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) struct ceu_subdev *ceu_sd = to_ceu_subdev(asd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) ceu_sd->v4l2_sd = v4l2_sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) ceudev->num_sd++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) static int ceu_notify_complete(struct v4l2_async_notifier *notifier)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) struct v4l2_device *v4l2_dev = notifier->v4l2_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) struct ceu_device *ceudev = v4l2_to_ceu(v4l2_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) struct video_device *vdev = &ceudev->vdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) struct vb2_queue *q = &ceudev->vb2_vq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) struct v4l2_subdev *v4l2_sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) /* Initialize vb2 queue. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) q->io_modes = VB2_MMAP | VB2_DMABUF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) q->drv_priv = ceudev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) q->ops = &ceu_vb2_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) q->mem_ops = &vb2_dma_contig_memops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) q->buf_struct_size = sizeof(struct ceu_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) q->min_buffers_needed = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) q->lock = &ceudev->mlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) q->dev = ceudev->v4l2_dev.dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) ret = vb2_queue_init(q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) * Make sure at least one sensor is primary and use it to initialize
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) * ceu formats.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) if (!ceudev->sd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) ceudev->sd = &ceudev->subdevs[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) ceudev->sd_index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) v4l2_sd = ceudev->sd->v4l2_sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) ret = ceu_init_mbus_fmt(ceudev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) ret = ceu_set_default_fmt(ceudev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) /* Register the video device. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) strscpy(vdev->name, DRIVER_NAME, sizeof(vdev->name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) vdev->v4l2_dev = v4l2_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) vdev->lock = &ceudev->mlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) vdev->queue = &ceudev->vb2_vq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) vdev->ctrl_handler = v4l2_sd->ctrl_handler;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) vdev->fops = &ceu_fops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) vdev->ioctl_ops = &ceu_ioctl_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) vdev->release = ceu_vdev_release;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE_MPLANE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) V4L2_CAP_STREAMING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) video_set_drvdata(vdev, ceudev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) v4l2_err(vdev->v4l2_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) "video_register_device failed: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) static const struct v4l2_async_notifier_operations ceu_notify_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) .bound = ceu_notify_bound,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) .complete = ceu_notify_complete,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) * ceu_init_async_subdevs() - Initialize CEU subdevices and async_subdevs in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) * ceu device. Both DT and platform data parsing use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) * this routine.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) * Returns 0 for success, -ENOMEM for failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) static int ceu_init_async_subdevs(struct ceu_device *ceudev, unsigned int n_sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) /* Reserve memory for 'n_sd' ceu_subdev descriptors. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) ceudev->subdevs = devm_kcalloc(ceudev->dev, n_sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) sizeof(*ceudev->subdevs), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) if (!ceudev->subdevs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) ceudev->sd = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) ceudev->sd_index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) ceudev->num_sd = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) * ceu_parse_platform_data() - Initialize async_subdevices using platform
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) * device provided data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) static int ceu_parse_platform_data(struct ceu_device *ceudev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) const struct ceu_platform_data *pdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) const struct ceu_async_subdev *async_sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) struct ceu_subdev *ceu_sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) if (pdata->num_subdevs == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) ret = ceu_init_async_subdevs(ceudev, pdata->num_subdevs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) for (i = 0; i < pdata->num_subdevs; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) /* Setup the ceu subdevice and the async subdevice. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) async_sd = &pdata->subdevs[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) ceu_sd = &ceudev->subdevs[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) INIT_LIST_HEAD(&ceu_sd->asd.list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) ceu_sd->mbus_flags = async_sd->flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) ceu_sd->asd.match_type = V4L2_ASYNC_MATCH_I2C;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) ceu_sd->asd.match.i2c.adapter_id = async_sd->i2c_adapter_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) ceu_sd->asd.match.i2c.address = async_sd->i2c_address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) ret = v4l2_async_notifier_add_subdev(&ceudev->notifier,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) &ceu_sd->asd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) v4l2_async_notifier_cleanup(&ceudev->notifier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) return pdata->num_subdevs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) * ceu_parse_dt() - Initialize async_subdevs parsing device tree graph.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) static int ceu_parse_dt(struct ceu_device *ceudev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) struct device_node *of = ceudev->dev->of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) struct device_node *ep, *remote;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) struct ceu_subdev *ceu_sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) int num_ep;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) num_ep = of_graph_get_endpoint_count(of);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) if (!num_ep)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) ret = ceu_init_async_subdevs(ceudev, num_ep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) for (i = 0; i < num_ep; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) struct v4l2_fwnode_endpoint fw_ep = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) .bus_type = V4L2_MBUS_PARALLEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) .bus = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) .parallel = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) .flags = V4L2_MBUS_HSYNC_ACTIVE_HIGH |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) V4L2_MBUS_VSYNC_ACTIVE_HIGH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) .bus_width = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) ep = of_graph_get_endpoint_by_regs(of, 0, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) if (!ep) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) dev_err(ceudev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) "No subdevice connected on endpoint %u.\n", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) goto error_cleanup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep), &fw_ep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) dev_err(ceudev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) "Unable to parse endpoint #%u: %d.\n", i, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) goto error_cleanup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) /* Setup the ceu subdevice and the async subdevice. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) ceu_sd = &ceudev->subdevs[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) INIT_LIST_HEAD(&ceu_sd->asd.list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) remote = of_graph_get_remote_port_parent(ep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) ceu_sd->mbus_flags = fw_ep.bus.parallel.flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) ceu_sd->asd.match_type = V4L2_ASYNC_MATCH_FWNODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) ceu_sd->asd.match.fwnode = of_fwnode_handle(remote);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) ret = v4l2_async_notifier_add_subdev(&ceudev->notifier,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) &ceu_sd->asd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) of_node_put(remote);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) goto error_cleanup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) of_node_put(ep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) return num_ep;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) error_cleanup:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) v4l2_async_notifier_cleanup(&ceudev->notifier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) of_node_put(ep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) * struct ceu_data - Platform specific CEU data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) * @irq_mask: CETCR mask with all interrupt sources enabled. The mask differs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) * between SH4 and RZ platforms.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) struct ceu_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) u32 irq_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) static const struct ceu_data ceu_data_rz = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) .irq_mask = CEU_CETCR_ALL_IRQS_RZ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) static const struct ceu_data ceu_data_sh4 = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) .irq_mask = CEU_CETCR_ALL_IRQS_SH4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) #if IS_ENABLED(CONFIG_OF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) static const struct of_device_id ceu_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) { .compatible = "renesas,r7s72100-ceu", .data = &ceu_data_rz },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) { .compatible = "renesas,r8a7740-ceu", .data = &ceu_data_rz },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) MODULE_DEVICE_TABLE(of, ceu_of_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) static int ceu_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) const struct ceu_data *ceu_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) struct ceu_device *ceudev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) struct resource *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) unsigned int irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) int num_subdevs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) ceudev = kzalloc(sizeof(*ceudev), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) if (!ceudev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) platform_set_drvdata(pdev, ceudev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) ceudev->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) INIT_LIST_HEAD(&ceudev->capture);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) spin_lock_init(&ceudev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) mutex_init(&ceudev->mlock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) ceudev->base = devm_ioremap_resource(dev, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) if (IS_ERR(ceudev->base)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) ret = PTR_ERR(ceudev->base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) goto error_free_ceudev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) ret = platform_get_irq(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) goto error_free_ceudev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) irq = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) ret = devm_request_irq(dev, irq, ceu_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) 0, dev_name(dev), ceudev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) dev_err(&pdev->dev, "Unable to request CEU interrupt.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) goto error_free_ceudev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) pm_runtime_enable(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) ret = v4l2_device_register(dev, &ceudev->v4l2_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) goto error_pm_disable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) v4l2_async_notifier_init(&ceudev->notifier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) if (IS_ENABLED(CONFIG_OF) && dev->of_node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) ceu_data = of_match_device(ceu_of_match, dev)->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) num_subdevs = ceu_parse_dt(ceudev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) } else if (dev->platform_data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) /* Assume SH4 if booting with platform data. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) ceu_data = &ceu_data_sh4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) num_subdevs = ceu_parse_platform_data(ceudev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) dev->platform_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) num_subdevs = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) if (num_subdevs < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) ret = num_subdevs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) goto error_v4l2_unregister;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) ceudev->irq_mask = ceu_data->irq_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) ceudev->notifier.v4l2_dev = &ceudev->v4l2_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) ceudev->notifier.ops = &ceu_notify_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) ret = v4l2_async_notifier_register(&ceudev->v4l2_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) &ceudev->notifier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) goto error_cleanup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) dev_info(dev, "Renesas Capture Engine Unit %s\n", dev_name(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) error_cleanup:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) v4l2_async_notifier_cleanup(&ceudev->notifier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) error_v4l2_unregister:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) v4l2_device_unregister(&ceudev->v4l2_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) error_pm_disable:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) pm_runtime_disable(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) error_free_ceudev:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) kfree(ceudev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) static int ceu_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) struct ceu_device *ceudev = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) pm_runtime_disable(ceudev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) v4l2_async_notifier_unregister(&ceudev->notifier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) v4l2_async_notifier_cleanup(&ceudev->notifier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) v4l2_device_unregister(&ceudev->v4l2_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) video_unregister_device(&ceudev->vdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) static const struct dev_pm_ops ceu_pm_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) SET_RUNTIME_PM_OPS(ceu_runtime_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) ceu_runtime_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) static struct platform_driver ceu_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) .name = DRIVER_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) .pm = &ceu_pm_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) .of_match_table = of_match_ptr(ceu_of_match),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) .probe = ceu_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) .remove = ceu_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) module_platform_driver(ceu_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) MODULE_DESCRIPTION("Renesas CEU camera driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) MODULE_AUTHOR("Jacopo Mondi <jacopo+renesas@jmondi.org>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) MODULE_LICENSE("GPL v2");