^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Freescale VIU video driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Authors: Hongjun Chen <hong-jun.chen@freescale.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Porting to 2.6.35 by DENX Software Engineering,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Anatolij Gustschin <agust@denx.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/i2c.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/of_address.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/of_irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/of_platform.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <media/v4l2-common.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <media/v4l2-device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <media/v4l2-ioctl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <media/v4l2-ctrls.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <media/v4l2-fh.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <media/v4l2-event.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <media/videobuf-dma-contig.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define DRV_NAME "fsl_viu"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define VIU_VERSION "0.5.1"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) /* Allow building this driver with COMPILE_TEST */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #if !defined(CONFIG_PPC) && !defined(CONFIG_MICROBLAZE) && !defined(CONFIG_M68K)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define out_be32(v, a) iowrite32be(a, (void __iomem *)v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define in_be32(a) ioread32be((void __iomem *)a)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define BUFFER_TIMEOUT msecs_to_jiffies(500) /* 0.5 seconds */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define VIU_VID_MEM_LIMIT 4 /* Video memory limit, in Mb */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) /* I2C address of video decoder chip is 0x4A */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define VIU_VIDEO_DECODER_ADDR 0x25
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) static int info_level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define dprintk(level, fmt, arg...) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) if (level <= info_level) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) printk(KERN_DEBUG "viu: " fmt , ## arg); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) * Basic structures
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) struct viu_fmt {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) u32 fourcc; /* v4l2 format id */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) u32 pixelformat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) int depth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) static struct viu_fmt formats[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) .fourcc = V4L2_PIX_FMT_RGB565,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) .pixelformat = V4L2_PIX_FMT_RGB565,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) .depth = 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) .fourcc = V4L2_PIX_FMT_RGB32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) .pixelformat = V4L2_PIX_FMT_RGB32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) .depth = 32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) struct viu_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) struct viu_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) /* buffer for one video frame */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) struct viu_buf {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) /* common v4l buffer stuff -- must be first */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) struct videobuf_buffer vb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) struct viu_fmt *fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) struct viu_dmaqueue {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) struct viu_dev *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) struct list_head active;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) struct list_head queued;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) struct timer_list timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) struct viu_status {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) u32 field_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) u32 vsync_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) u32 hsync_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) u32 vstart_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) u32 dma_end_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) u32 error_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) struct viu_reg {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) u32 status_cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) u32 luminance;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) u32 chroma_r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) u32 chroma_g;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) u32 chroma_b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) u32 field_base_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) u32 dma_inc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) u32 picture_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) u32 req_alarm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) u32 alpha;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) } __attribute__ ((packed));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) struct viu_dev {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) struct v4l2_device v4l2_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) struct v4l2_ctrl_handler hdl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) struct mutex lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) spinlock_t slock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) int users;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) struct device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) /* various device info */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) struct video_device *vdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) struct viu_dmaqueue vidq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) enum v4l2_field capfield;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) int field;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) int first;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) int dma_done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) /* Hardware register area */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) struct viu_reg __iomem *vr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) /* Interrupt vector */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) int irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) struct viu_status irqs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) /* video overlay */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) struct v4l2_framebuffer ovbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) struct viu_fmt *ovfmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) unsigned int ovenable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) enum v4l2_field ovfield;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) /* crop */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) struct v4l2_rect crop_current;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) /* clock pointer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) struct clk *clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) /* decoder */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) struct v4l2_subdev *decoder;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) v4l2_std_id std;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) struct viu_fh {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) /* must remain the first field of this struct */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) struct v4l2_fh fh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) struct viu_dev *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) /* video capture */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) struct videobuf_queue vb_vidq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) spinlock_t vbq_lock; /* spinlock for the videobuf queue */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) /* video overlay */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) struct v4l2_window win;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) struct v4l2_clip clips[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) /* video capture */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) struct viu_fmt *fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) int width, height, sizeimage;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) enum v4l2_buf_type type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) static struct viu_reg reg_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) * Macro definitions of VIU registers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) /* STATUS_CONFIG register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) enum status_config {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) SOFT_RST = 1 << 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) ERR_MASK = 0x0f << 4, /* Error code mask */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) ERR_NO = 0x00, /* No error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) ERR_DMA_V = 0x01 << 4, /* DMA in vertical active */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) ERR_DMA_VB = 0x02 << 4, /* DMA in vertical blanking */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) ERR_LINE_TOO_LONG = 0x04 << 4, /* Line too long */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) ERR_TOO_MANG_LINES = 0x05 << 4, /* Too many lines in field */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) ERR_LINE_TOO_SHORT = 0x06 << 4, /* Line too short */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) ERR_NOT_ENOUGH_LINE = 0x07 << 4, /* Not enough lines in field */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) ERR_FIFO_OVERFLOW = 0x08 << 4, /* FIFO overflow */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) ERR_FIFO_UNDERFLOW = 0x09 << 4, /* FIFO underflow */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) ERR_1bit_ECC = 0x0a << 4, /* One bit ECC error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) ERR_MORE_ECC = 0x0b << 4, /* Two/more bits ECC error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) INT_FIELD_EN = 0x01 << 8, /* Enable field interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) INT_VSYNC_EN = 0x01 << 9, /* Enable vsync interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) INT_HSYNC_EN = 0x01 << 10, /* Enable hsync interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) INT_VSTART_EN = 0x01 << 11, /* Enable vstart interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) INT_DMA_END_EN = 0x01 << 12, /* Enable DMA end interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) INT_ERROR_EN = 0x01 << 13, /* Enable error interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) INT_ECC_EN = 0x01 << 14, /* Enable ECC interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) INT_FIELD_STATUS = 0x01 << 16, /* field interrupt status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) INT_VSYNC_STATUS = 0x01 << 17, /* vsync interrupt status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) INT_HSYNC_STATUS = 0x01 << 18, /* hsync interrupt status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) INT_VSTART_STATUS = 0x01 << 19, /* vstart interrupt status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) INT_DMA_END_STATUS = 0x01 << 20, /* DMA end interrupt status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) INT_ERROR_STATUS = 0x01 << 21, /* error interrupt status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) DMA_ACT = 0x01 << 27, /* Enable DMA transfer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) FIELD_NO = 0x01 << 28, /* Field number */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) DITHER_ON = 0x01 << 29, /* Dithering is on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) ROUND_ON = 0x01 << 30, /* Round is on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) MODE_32BIT = 1UL << 31, /* Data in RGBa888,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) * 0 in RGB565
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) #define norm_maxw() 720
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) #define norm_maxh() 576
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) #define INT_ALL_STATUS (INT_FIELD_STATUS | INT_VSYNC_STATUS | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) INT_HSYNC_STATUS | INT_VSTART_STATUS | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) INT_DMA_END_STATUS | INT_ERROR_STATUS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) #define NUM_FORMATS ARRAY_SIZE(formats)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) static irqreturn_t viu_intr(int irq, void *dev_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) static struct viu_fmt *format_by_fourcc(int fourcc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) for (i = 0; i < NUM_FORMATS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) if (formats[i].pixelformat == fourcc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) return formats + i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) dprintk(0, "unknown pixelformat:'%4.4s'\n", (char *)&fourcc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) static void viu_start_dma(struct viu_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) struct viu_reg __iomem *vr = dev->vr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) dev->field = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) /* Enable DMA operation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) out_be32(&vr->status_cfg, SOFT_RST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) out_be32(&vr->status_cfg, INT_FIELD_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) static void viu_stop_dma(struct viu_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) struct viu_reg __iomem *vr = dev->vr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) int cnt = 100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) u32 status_cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) out_be32(&vr->status_cfg, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) /* Clear pending interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) status_cfg = in_be32(&vr->status_cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) if (status_cfg & 0x3f0000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) out_be32(&vr->status_cfg, status_cfg & 0x3f0000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) if (status_cfg & DMA_ACT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) status_cfg = in_be32(&vr->status_cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) if (status_cfg & INT_DMA_END_STATUS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) } while (cnt--);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) if (cnt < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) /* timed out, issue soft reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) out_be32(&vr->status_cfg, SOFT_RST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) out_be32(&vr->status_cfg, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) /* clear DMA_END and other pending irqs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) out_be32(&vr->status_cfg, status_cfg & 0x3f0000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) dev->field = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) static int restart_video_queue(struct viu_dmaqueue *vidq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) struct viu_buf *buf, *prev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) dprintk(1, "%s vidq=%p\n", __func__, vidq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) if (!list_empty(&vidq->active)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) buf = list_entry(vidq->active.next, struct viu_buf, vb.queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) dprintk(2, "restart_queue [%p/%d]: restart dma\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) buf, buf->vb.i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) viu_stop_dma(vidq->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) /* cancel all outstanding capture requests */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) list_for_each_entry_safe(buf, prev, &vidq->active, vb.queue) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) list_del(&buf->vb.queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) buf->vb.state = VIDEOBUF_ERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) wake_up(&buf->vb.done);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) mod_timer(&vidq->timeout, jiffies+BUFFER_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) return 0;
^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) prev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) if (list_empty(&vidq->queued))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) buf = list_entry(vidq->queued.next, struct viu_buf, vb.queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) if (prev == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) list_move_tail(&buf->vb.queue, &vidq->active);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) dprintk(1, "Restarting video dma\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) viu_stop_dma(vidq->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) viu_start_dma(vidq->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) buf->vb.state = VIDEOBUF_ACTIVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) mod_timer(&vidq->timeout, jiffies+BUFFER_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) dprintk(2, "[%p/%d] restart_queue - first active\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) buf, buf->vb.i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) } else if (prev->vb.width == buf->vb.width &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) prev->vb.height == buf->vb.height &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) prev->fmt == buf->fmt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) list_move_tail(&buf->vb.queue, &vidq->active);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) buf->vb.state = VIDEOBUF_ACTIVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) dprintk(2, "[%p/%d] restart_queue - move to active\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) buf, buf->vb.i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) prev = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) static void viu_vid_timeout(struct timer_list *t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) struct viu_dev *dev = from_timer(dev, t, vidq.timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) struct viu_buf *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) struct viu_dmaqueue *vidq = &dev->vidq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) while (!list_empty(&vidq->active)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) buf = list_entry(vidq->active.next, struct viu_buf, vb.queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) list_del(&buf->vb.queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) buf->vb.state = VIDEOBUF_ERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) wake_up(&buf->vb.done);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) dprintk(1, "viu/0: [%p/%d] timeout\n", buf, buf->vb.i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) restart_video_queue(vidq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) * Videobuf operations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) static int buffer_setup(struct videobuf_queue *vq, unsigned int *count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) unsigned int *size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) struct viu_fh *fh = vq->priv_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) *size = fh->width * fh->height * fh->fmt->depth >> 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) if (*count == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) *count = 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) while (*size * *count > VIU_VID_MEM_LIMIT * 1024 * 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) (*count)--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) dprintk(1, "%s, count=%d, size=%d\n", __func__, *count, *size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) static void free_buffer(struct videobuf_queue *vq, struct viu_buf *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) struct videobuf_buffer *vb = &buf->vb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) void *vaddr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) BUG_ON(in_interrupt());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) videobuf_waiton(vq, &buf->vb, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) if (vq->int_ops && vq->int_ops->vaddr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) vaddr = vq->int_ops->vaddr(vb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) if (vaddr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) videobuf_dma_contig_free(vq, &buf->vb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) buf->vb.state = VIDEOBUF_NEEDS_INIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) inline int buffer_activate(struct viu_dev *dev, struct viu_buf *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) struct viu_reg __iomem *vr = dev->vr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) int bpp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) /* setup the DMA base address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) reg_val.field_base_addr = videobuf_to_dma_contig(&buf->vb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) dprintk(1, "buffer_activate [%p/%d]: dma addr 0x%lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) buf, buf->vb.i, (unsigned long)reg_val.field_base_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) /* interlace is on by default, set horizontal DMA increment */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) reg_val.status_cfg = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) bpp = buf->fmt->depth >> 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) switch (bpp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) reg_val.status_cfg &= ~MODE_32BIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) reg_val.dma_inc = buf->vb.width * 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) reg_val.status_cfg |= MODE_32BIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) reg_val.dma_inc = buf->vb.width * 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) dprintk(0, "doesn't support color depth(%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) bpp * 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) /* setup picture_count register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) reg_val.picture_count = (buf->vb.height / 2) << 16 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) buf->vb.width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) reg_val.status_cfg |= DMA_ACT | INT_DMA_END_EN | INT_FIELD_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) buf->vb.state = VIDEOBUF_ACTIVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) dev->capfield = buf->vb.field;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) /* reset dma increment if needed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) if (!V4L2_FIELD_HAS_BOTH(buf->vb.field))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) reg_val.dma_inc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) out_be32(&vr->dma_inc, reg_val.dma_inc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) out_be32(&vr->picture_count, reg_val.picture_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) out_be32(&vr->field_base_addr, reg_val.field_base_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) mod_timer(&dev->vidq.timeout, jiffies + BUFFER_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) return 0;
^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) static int buffer_prepare(struct videobuf_queue *vq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) struct videobuf_buffer *vb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) enum v4l2_field field)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) struct viu_fh *fh = vq->priv_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) struct viu_buf *buf = container_of(vb, struct viu_buf, vb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) BUG_ON(fh->fmt == NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) if (fh->width < 48 || fh->width > norm_maxw() ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) fh->height < 32 || fh->height > norm_maxh())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) buf->vb.size = (fh->width * fh->height * fh->fmt->depth) >> 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) if (buf->vb.baddr != 0 && buf->vb.bsize < buf->vb.size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) if (buf->fmt != fh->fmt ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) buf->vb.width != fh->width ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) buf->vb.height != fh->height ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) buf->vb.field != field) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) buf->fmt = fh->fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) buf->vb.width = fh->width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) buf->vb.height = fh->height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) buf->vb.field = field;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) if (buf->vb.state == VIDEOBUF_NEEDS_INIT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) rc = videobuf_iolock(vq, &buf->vb, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) if (rc != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) buf->vb.width = fh->width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) buf->vb.height = fh->height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) buf->vb.field = field;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) buf->fmt = fh->fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) buf->vb.state = VIDEOBUF_PREPARED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) free_buffer(vq, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) struct viu_buf *buf = container_of(vb, struct viu_buf, vb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) struct viu_fh *fh = vq->priv_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) struct viu_dev *dev = fh->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) struct viu_dmaqueue *vidq = &dev->vidq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) struct viu_buf *prev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) if (!list_empty(&vidq->queued)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) dprintk(1, "adding vb queue=%p\n", &buf->vb.queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) dprintk(1, "vidq pointer 0x%p, queued 0x%p\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) vidq, &vidq->queued);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) dprintk(1, "dev %p, queued: self %p, next %p, head %p\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) dev, &vidq->queued, vidq->queued.next,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) vidq->queued.prev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) list_add_tail(&buf->vb.queue, &vidq->queued);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) buf->vb.state = VIDEOBUF_QUEUED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) dprintk(2, "[%p/%d] buffer_queue - append to queued\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) buf, buf->vb.i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) } else if (list_empty(&vidq->active)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) dprintk(1, "adding vb active=%p\n", &buf->vb.queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) list_add_tail(&buf->vb.queue, &vidq->active);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) buf->vb.state = VIDEOBUF_ACTIVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) mod_timer(&vidq->timeout, jiffies+BUFFER_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) dprintk(2, "[%p/%d] buffer_queue - first active\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) buf, buf->vb.i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) buffer_activate(dev, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) dprintk(1, "adding vb queue2=%p\n", &buf->vb.queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) prev = list_entry(vidq->active.prev, struct viu_buf, vb.queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) if (prev->vb.width == buf->vb.width &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) prev->vb.height == buf->vb.height &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) prev->fmt == buf->fmt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) list_add_tail(&buf->vb.queue, &vidq->active);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) buf->vb.state = VIDEOBUF_ACTIVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) dprintk(2, "[%p/%d] buffer_queue - append to active\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) buf, buf->vb.i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) list_add_tail(&buf->vb.queue, &vidq->queued);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) buf->vb.state = VIDEOBUF_QUEUED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) dprintk(2, "[%p/%d] buffer_queue - first queued\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) buf, buf->vb.i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) }
^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) static void buffer_release(struct videobuf_queue *vq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) struct videobuf_buffer *vb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) struct viu_buf *buf = container_of(vb, struct viu_buf, vb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) struct viu_fh *fh = vq->priv_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) struct viu_dev *dev = (struct viu_dev *)fh->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) viu_stop_dma(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) free_buffer(vq, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) static const struct videobuf_queue_ops viu_video_qops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) .buf_setup = buffer_setup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) .buf_prepare = buffer_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) .buf_queue = buffer_queue,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) .buf_release = buffer_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) };
^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) * IOCTL vidioc handling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) static int vidioc_querycap(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) struct v4l2_capability *cap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) strscpy(cap->driver, "viu", sizeof(cap->driver));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) strscpy(cap->card, "viu", sizeof(cap->card));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) strscpy(cap->bus_info, "platform:viu", sizeof(cap->bus_info));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) static int vidioc_enum_fmt(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) struct v4l2_fmtdesc *f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) int index = f->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) if (f->index >= NUM_FORMATS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) f->pixelformat = formats[index].fourcc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) static int vidioc_g_fmt_cap(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) struct v4l2_format *f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) struct viu_fh *fh = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) f->fmt.pix.width = fh->width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) f->fmt.pix.height = fh->height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) f->fmt.pix.field = fh->vb_vidq.field;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) f->fmt.pix.pixelformat = fh->fmt->pixelformat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) f->fmt.pix.bytesperline =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) (f->fmt.pix.width * fh->fmt->depth) >> 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) f->fmt.pix.sizeimage = fh->sizeimage;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) static int vidioc_try_fmt_cap(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) struct v4l2_format *f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) struct viu_fmt *fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) unsigned int maxw, maxh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) fmt = format_by_fourcc(f->fmt.pix.pixelformat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) if (!fmt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) dprintk(1, "Fourcc format (0x%08x) invalid.",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) f->fmt.pix.pixelformat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) maxw = norm_maxw();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) maxh = norm_maxh();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) f->fmt.pix.field = V4L2_FIELD_INTERLACED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) if (f->fmt.pix.height < 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) f->fmt.pix.height = 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) if (f->fmt.pix.height > maxh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) f->fmt.pix.height = maxh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) if (f->fmt.pix.width < 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) f->fmt.pix.width = 48;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) if (f->fmt.pix.width > maxw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) f->fmt.pix.width = maxw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) f->fmt.pix.width &= ~0x03;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) f->fmt.pix.bytesperline =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) (f->fmt.pix.width * fmt->depth) >> 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) static int vidioc_s_fmt_cap(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) struct v4l2_format *f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) struct viu_fh *fh = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) ret = vidioc_try_fmt_cap(file, fh, f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) fh->width = f->fmt.pix.width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) fh->height = f->fmt.pix.height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) fh->sizeimage = f->fmt.pix.sizeimage;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) fh->vb_vidq.field = f->fmt.pix.field;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) fh->type = f->type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) static int vidioc_g_fmt_overlay(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) struct v4l2_format *f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) struct viu_fh *fh = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) f->fmt.win = fh->win;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) static int verify_preview(struct viu_dev *dev, struct v4l2_window *win)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) enum v4l2_field field;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) int maxw, maxh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) if (dev->ovbuf.base == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) if (dev->ovfmt == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) if (win->w.width < 48 || win->w.height < 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) field = win->field;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) maxw = dev->crop_current.width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) maxh = dev->crop_current.height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) if (field == V4L2_FIELD_ANY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) field = (win->w.height > maxh/2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) ? V4L2_FIELD_INTERLACED
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) : V4L2_FIELD_TOP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) switch (field) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) case V4L2_FIELD_TOP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) case V4L2_FIELD_BOTTOM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) maxh = maxh / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) case V4L2_FIELD_INTERLACED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) win->field = field;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) if (win->w.width > maxw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) win->w.width = maxw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) if (win->w.height > maxh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) win->w.height = maxh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) return 0;
^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) inline void viu_activate_overlay(struct viu_reg __iomem *vr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) out_be32(&vr->field_base_addr, reg_val.field_base_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) out_be32(&vr->dma_inc, reg_val.dma_inc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) out_be32(&vr->picture_count, reg_val.picture_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) static int viu_setup_preview(struct viu_dev *dev, struct viu_fh *fh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) int bpp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) dprintk(1, "%s %dx%d\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) fh->win.w.width, fh->win.w.height);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) reg_val.status_cfg = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) /* setup window */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) reg_val.picture_count = (fh->win.w.height / 2) << 16 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) fh->win.w.width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) /* setup color depth and dma increment */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) bpp = dev->ovfmt->depth / 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) switch (bpp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) reg_val.status_cfg &= ~MODE_32BIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) reg_val.dma_inc = fh->win.w.width * 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) reg_val.status_cfg |= MODE_32BIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) reg_val.dma_inc = fh->win.w.width * 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) dprintk(0, "device doesn't support color depth(%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) bpp * 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) dev->ovfield = fh->win.field;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) if (!V4L2_FIELD_HAS_BOTH(dev->ovfield))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) reg_val.dma_inc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) reg_val.status_cfg |= DMA_ACT | INT_DMA_END_EN | INT_FIELD_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) /* setup the base address of the overlay buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) reg_val.field_base_addr = (u32)(long)dev->ovbuf.base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) static int vidioc_s_fmt_overlay(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) struct v4l2_format *f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) struct viu_fh *fh = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) struct viu_dev *dev = (struct viu_dev *)fh->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) err = verify_preview(dev, &f->fmt.win);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) fh->win = f->fmt.win;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) spin_lock_irqsave(&dev->slock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) viu_setup_preview(dev, fh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) spin_unlock_irqrestore(&dev->slock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) static int vidioc_try_fmt_overlay(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) struct v4l2_format *f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) static int vidioc_overlay(struct file *file, void *priv, unsigned int on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) struct viu_fh *fh = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) struct viu_dev *dev = (struct viu_dev *)fh->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) if (on) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) spin_lock_irqsave(&dev->slock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) viu_activate_overlay(dev->vr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) dev->ovenable = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) /* start dma */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) viu_start_dma(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) spin_unlock_irqrestore(&dev->slock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) viu_stop_dma(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) dev->ovenable = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) static int vidioc_g_fbuf(struct file *file, void *priv, struct v4l2_framebuffer *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) struct viu_fh *fh = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) struct viu_dev *dev = fh->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) struct v4l2_framebuffer *fb = arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) *fb = dev->ovbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) static int vidioc_s_fbuf(struct file *file, void *priv, const struct v4l2_framebuffer *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) struct viu_fh *fh = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) struct viu_dev *dev = fh->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) const struct v4l2_framebuffer *fb = arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) struct viu_fmt *fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RAWIO))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) /* check args */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) fmt = format_by_fourcc(fb->fmt.pixelformat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) if (fmt == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) /* ok, accept it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) dev->ovbuf = *fb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) dev->ovfmt = fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) if (dev->ovbuf.fmt.bytesperline == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) dev->ovbuf.fmt.bytesperline =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) dev->ovbuf.fmt.width * fmt->depth / 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) static int vidioc_reqbufs(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) struct v4l2_requestbuffers *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) struct viu_fh *fh = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) return videobuf_reqbufs(&fh->vb_vidq, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) static int vidioc_querybuf(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) struct v4l2_buffer *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) struct viu_fh *fh = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) return videobuf_querybuf(&fh->vb_vidq, p);
^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) static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) struct viu_fh *fh = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) return videobuf_qbuf(&fh->vb_vidq, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) struct viu_fh *fh = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) return videobuf_dqbuf(&fh->vb_vidq, p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) file->f_flags & O_NONBLOCK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) struct viu_fh *fh = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) struct viu_dev *dev = fh->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) if (fh->type != i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) if (dev->ovenable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) dev->ovenable = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) viu_start_dma(fh->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) return videobuf_streamon(&fh->vb_vidq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) struct viu_fh *fh = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) if (fh->type != i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) viu_stop_dma(fh->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) return videobuf_streamoff(&fh->vb_vidq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) #define decoder_call(viu, o, f, args...) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) v4l2_subdev_call(viu->decoder, o, f, ##args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) static int vidioc_querystd(struct file *file, void *priv, v4l2_std_id *std_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) struct viu_fh *fh = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) decoder_call(fh->dev, video, querystd, std_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) return 0;
^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) static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) struct viu_fh *fh = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) fh->dev->std = id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) decoder_call(fh->dev, video, s_std, id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *std_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) struct viu_fh *fh = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) *std_id = fh->dev->std;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) return 0;
^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) /* only one input in this driver */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) static int vidioc_enum_input(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) struct v4l2_input *inp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) struct viu_fh *fh = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) if (inp->index != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) inp->type = V4L2_INPUT_TYPE_CAMERA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) inp->std = fh->dev->vdev->tvnorms;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) strscpy(inp->name, "Camera", sizeof(inp->name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) *i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) struct viu_fh *fh = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) if (i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) decoder_call(fh->dev, video, s_routing, i, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) inline void viu_activate_next_buf(struct viu_dev *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) struct viu_dmaqueue *viuq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) struct viu_dmaqueue *vidq = viuq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) struct viu_buf *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) /* launch another DMA operation for an active/queued buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) if (!list_empty(&vidq->active)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) buf = list_entry(vidq->active.next, struct viu_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) vb.queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) dprintk(1, "start another queued buffer: 0x%p\n", buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) buffer_activate(dev, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) } else if (!list_empty(&vidq->queued)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) buf = list_entry(vidq->queued.next, struct viu_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) vb.queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) list_del(&buf->vb.queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) dprintk(1, "start another queued buffer: 0x%p\n", buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) list_add_tail(&buf->vb.queue, &vidq->active);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) buf->vb.state = VIDEOBUF_ACTIVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) buffer_activate(dev, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) inline void viu_default_settings(struct viu_reg __iomem *vr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) out_be32(&vr->luminance, 0x9512A254);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) out_be32(&vr->chroma_r, 0x03310000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) out_be32(&vr->chroma_g, 0x06600F38);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) out_be32(&vr->chroma_b, 0x00000409);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) out_be32(&vr->alpha, 0x000000ff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) out_be32(&vr->req_alarm, 0x00000090);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) dprintk(1, "status reg: 0x%08x, field base: 0x%08x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) in_be32(&vr->status_cfg), in_be32(&vr->field_base_addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) static void viu_overlay_intr(struct viu_dev *dev, u32 status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) struct viu_reg __iomem *vr = dev->vr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) if (status & INT_DMA_END_STATUS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) dev->dma_done = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) if (status & INT_FIELD_STATUS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) if (dev->dma_done) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) u32 addr = reg_val.field_base_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) dev->dma_done = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) if (status & FIELD_NO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) addr += reg_val.dma_inc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) out_be32(&vr->field_base_addr, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) out_be32(&vr->dma_inc, reg_val.dma_inc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) out_be32(&vr->status_cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) (status & 0xffc0ffff) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) (status & INT_ALL_STATUS) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) reg_val.status_cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) } else if (status & INT_VSYNC_STATUS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) out_be32(&vr->status_cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) (status & 0xffc0ffff) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) (status & INT_ALL_STATUS) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) reg_val.status_cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) static void viu_capture_intr(struct viu_dev *dev, u32 status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) struct viu_dmaqueue *vidq = &dev->vidq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) struct viu_reg __iomem *vr = dev->vr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) struct viu_buf *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) int field_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) int need_two;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) int dma_done = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) field_num = status & FIELD_NO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) need_two = V4L2_FIELD_HAS_BOTH(dev->capfield);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) if (status & INT_DMA_END_STATUS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) dma_done = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) if (((field_num == 0) && (dev->field == 0)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) (field_num && (dev->field == 1)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) dev->field++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) if (status & INT_FIELD_STATUS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) dprintk(1, "irq: field %d, done %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) !!field_num, dma_done);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) if (unlikely(dev->first)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) if (field_num == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) dev->first = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) dprintk(1, "activate first buf\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) viu_activate_next_buf(dev, vidq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) dprintk(1, "wait field 0\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) /* setup buffer address for next dma operation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) if (!list_empty(&vidq->active)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) u32 addr = reg_val.field_base_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) if (field_num && need_two) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) addr += reg_val.dma_inc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) dprintk(1, "field 1, 0x%lx, dev field %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) (unsigned long)addr, dev->field);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) out_be32(&vr->field_base_addr, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) out_be32(&vr->dma_inc, reg_val.dma_inc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) out_be32(&vr->status_cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) (status & 0xffc0ffff) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) (status & INT_ALL_STATUS) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) reg_val.status_cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) }
^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) if (dma_done && field_num && (dev->field == 2)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) dev->field = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) buf = list_entry(vidq->active.next,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) struct viu_buf, vb.queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) dprintk(1, "viu/0: [%p/%d] 0x%lx/0x%lx: dma complete\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) buf, buf->vb.i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) (unsigned long)videobuf_to_dma_contig(&buf->vb),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) (unsigned long)in_be32(&vr->field_base_addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) if (waitqueue_active(&buf->vb.done)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) list_del(&buf->vb.queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) buf->vb.ts = ktime_get_ns();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) buf->vb.state = VIDEOBUF_DONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) buf->vb.field_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) wake_up(&buf->vb.done);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) /* activate next dma buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) viu_activate_next_buf(dev, vidq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) static irqreturn_t viu_intr(int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) struct viu_dev *dev = (struct viu_dev *)dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) struct viu_reg __iomem *vr = dev->vr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) u32 status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) u32 error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) status = in_be32(&vr->status_cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) if (status & INT_ERROR_STATUS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) dev->irqs.error_irq++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) error = status & ERR_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) dprintk(1, "Err: error(%d), times:%d!\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) error >> 4, dev->irqs.error_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) /* Clear interrupt error bit and error flags */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) out_be32(&vr->status_cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) (status & 0xffc0ffff) | INT_ERROR_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) if (status & INT_DMA_END_STATUS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) dev->irqs.dma_end_irq++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) dev->dma_done = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) dprintk(2, "VIU DMA end interrupt times: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) dev->irqs.dma_end_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) if (status & INT_HSYNC_STATUS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) dev->irqs.hsync_irq++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) if (status & INT_FIELD_STATUS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) dev->irqs.field_irq++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) dprintk(2, "VIU field interrupt times: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) dev->irqs.field_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) if (status & INT_VSTART_STATUS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) dev->irqs.vstart_irq++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) if (status & INT_VSYNC_STATUS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) dev->irqs.vsync_irq++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) dprintk(2, "VIU vsync interrupt times: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) dev->irqs.vsync_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) /* clear all pending irqs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) status = in_be32(&vr->status_cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) out_be32(&vr->status_cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) (status & 0xffc0ffff) | (status & INT_ALL_STATUS));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) if (dev->ovenable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) viu_overlay_intr(dev, status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) /* Capture mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) viu_capture_intr(dev, status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) * File operations for the device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) static int viu_open(struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) struct video_device *vdev = video_devdata(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) struct viu_dev *dev = video_get_drvdata(vdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) struct viu_fh *fh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) struct viu_reg __iomem *vr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) int minor = vdev->minor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) u32 status_cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) dprintk(1, "viu: open (minor=%d)\n", minor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) dev->users++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) if (dev->users > 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) dev->users--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) vr = dev->vr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) dprintk(1, "open minor=%d type=%s users=%d\n", minor,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) v4l2_type_names[V4L2_BUF_TYPE_VIDEO_CAPTURE], dev->users);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) if (mutex_lock_interruptible(&dev->lock)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) dev->users--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) return -ERESTARTSYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) /* allocate and initialize per filehandle data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) fh = kzalloc(sizeof(*fh), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) if (!fh) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) dev->users--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) mutex_unlock(&dev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) v4l2_fh_init(&fh->fh, vdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) file->private_data = fh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) fh->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) fh->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) fh->fmt = format_by_fourcc(V4L2_PIX_FMT_RGB32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) fh->width = norm_maxw();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) fh->height = norm_maxh();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) dev->crop_current.width = fh->width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) dev->crop_current.height = fh->height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) dprintk(1, "Open: fh=%p, dev=%p, dev->vidq=%p\n", fh, dev, &dev->vidq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) dprintk(1, "Open: list_empty queued=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) list_empty(&dev->vidq.queued));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) dprintk(1, "Open: list_empty active=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) list_empty(&dev->vidq.active));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) viu_default_settings(vr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) status_cfg = in_be32(&vr->status_cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) out_be32(&vr->status_cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) status_cfg & ~(INT_VSYNC_EN | INT_HSYNC_EN |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) INT_FIELD_EN | INT_VSTART_EN |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) INT_DMA_END_EN | INT_ERROR_EN | INT_ECC_EN));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) status_cfg = in_be32(&vr->status_cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) out_be32(&vr->status_cfg, status_cfg | INT_ALL_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) spin_lock_init(&fh->vbq_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) videobuf_queue_dma_contig_init(&fh->vb_vidq, &viu_video_qops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) dev->dev, &fh->vbq_lock,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) fh->type, V4L2_FIELD_INTERLACED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) sizeof(struct viu_buf), fh,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) &fh->dev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) v4l2_fh_add(&fh->fh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) mutex_unlock(&dev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) static ssize_t viu_read(struct file *file, char __user *data, size_t count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) loff_t *ppos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) struct viu_fh *fh = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) struct viu_dev *dev = fh->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) dprintk(2, "%s\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) if (dev->ovenable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) dev->ovenable = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) if (mutex_lock_interruptible(&dev->lock))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) return -ERESTARTSYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) viu_start_dma(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) ret = videobuf_read_stream(&fh->vb_vidq, data, count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) ppos, 0, file->f_flags & O_NONBLOCK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) mutex_unlock(&dev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) static __poll_t viu_poll(struct file *file, struct poll_table_struct *wait)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) struct viu_fh *fh = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) struct videobuf_queue *q = &fh->vb_vidq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) struct viu_dev *dev = fh->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) __poll_t req_events = poll_requested_events(wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) __poll_t res = v4l2_ctrl_poll(file, wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) return EPOLLERR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) if (!(req_events & (EPOLLIN | EPOLLRDNORM)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) mutex_lock(&dev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) res |= videobuf_poll_stream(file, q, wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) mutex_unlock(&dev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) static int viu_release(struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) struct viu_fh *fh = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) struct viu_dev *dev = fh->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) int minor = video_devdata(file)->minor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) mutex_lock(&dev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) viu_stop_dma(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) videobuf_stop(&fh->vb_vidq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) videobuf_mmap_free(&fh->vb_vidq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) v4l2_fh_del(&fh->fh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) v4l2_fh_exit(&fh->fh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) mutex_unlock(&dev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) kfree(fh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) dev->users--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) dprintk(1, "close (minor=%d, users=%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) minor, dev->users);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) static void viu_reset(struct viu_reg __iomem *reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) out_be32(®->status_cfg, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) out_be32(®->luminance, 0x9512a254);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) out_be32(®->chroma_r, 0x03310000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) out_be32(®->chroma_g, 0x06600f38);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) out_be32(®->chroma_b, 0x00000409);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) out_be32(®->field_base_addr, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) out_be32(®->dma_inc, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) out_be32(®->picture_count, 0x01e002d0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) out_be32(®->req_alarm, 0x00000090);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) out_be32(®->alpha, 0x000000ff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) static int viu_mmap(struct file *file, struct vm_area_struct *vma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) struct viu_fh *fh = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) struct viu_dev *dev = fh->dev;
^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) dprintk(1, "mmap called, vma=%p\n", vma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) if (mutex_lock_interruptible(&dev->lock))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) return -ERESTARTSYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) ret = videobuf_mmap_mapper(&fh->vb_vidq, vma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) mutex_unlock(&dev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) dprintk(1, "vma start=0x%08lx, size=%ld, ret=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) (unsigned long)vma->vm_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) (unsigned long)vma->vm_end-(unsigned long)vma->vm_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) static const struct v4l2_file_operations viu_fops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) .open = viu_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) .release = viu_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) .read = viu_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) .poll = viu_poll,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) .unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) .mmap = viu_mmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) static const struct v4l2_ioctl_ops viu_ioctl_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) .vidioc_querycap = vidioc_querycap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) .vidioc_g_fmt_vid_cap = vidioc_g_fmt_cap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) .vidioc_try_fmt_vid_cap = vidioc_try_fmt_cap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) .vidioc_s_fmt_vid_cap = vidioc_s_fmt_cap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) .vidioc_enum_fmt_vid_overlay = vidioc_enum_fmt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) .vidioc_g_fmt_vid_overlay = vidioc_g_fmt_overlay,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) .vidioc_try_fmt_vid_overlay = vidioc_try_fmt_overlay,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) .vidioc_s_fmt_vid_overlay = vidioc_s_fmt_overlay,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) .vidioc_overlay = vidioc_overlay,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) .vidioc_g_fbuf = vidioc_g_fbuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) .vidioc_s_fbuf = vidioc_s_fbuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) .vidioc_reqbufs = vidioc_reqbufs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) .vidioc_querybuf = vidioc_querybuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) .vidioc_qbuf = vidioc_qbuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) .vidioc_dqbuf = vidioc_dqbuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) .vidioc_g_std = vidioc_g_std,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) .vidioc_s_std = vidioc_s_std,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) .vidioc_querystd = vidioc_querystd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) .vidioc_enum_input = vidioc_enum_input,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) .vidioc_g_input = vidioc_g_input,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) .vidioc_s_input = vidioc_s_input,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) .vidioc_streamon = vidioc_streamon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) .vidioc_streamoff = vidioc_streamoff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) .vidioc_log_status = v4l2_ctrl_log_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) static const struct video_device viu_template = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) .name = "FSL viu",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) .fops = &viu_fops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) .minor = -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) .ioctl_ops = &viu_ioctl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) .release = video_device_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) .tvnorms = V4L2_STD_NTSC_M | V4L2_STD_PAL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) .device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) V4L2_CAP_VIDEO_OVERLAY | V4L2_CAP_READWRITE,
^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 viu_of_probe(struct platform_device *op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) struct viu_dev *viu_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) struct video_device *vdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) struct resource r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) struct viu_reg __iomem *viu_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) struct i2c_adapter *ad;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) int ret, viu_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) struct clk *clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) ret = of_address_to_resource(op->dev.of_node, 0, &r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) dev_err(&op->dev, "Can't parse device node resource\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) viu_irq = irq_of_parse_and_map(op->dev.of_node, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) if (!viu_irq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) dev_err(&op->dev, "Error while mapping the irq\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) /* request mem region */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) if (!devm_request_mem_region(&op->dev, r.start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) sizeof(struct viu_reg), DRV_NAME)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) dev_err(&op->dev, "Error while requesting mem region\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) ret = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) goto err_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) /* remap registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) viu_regs = devm_ioremap(&op->dev, r.start, sizeof(struct viu_reg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) if (!viu_regs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) dev_err(&op->dev, "Can't map register set\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) goto err_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) /* Prepare our private structure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) viu_dev = devm_kzalloc(&op->dev, sizeof(struct viu_dev), GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) if (!viu_dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) dev_err(&op->dev, "Can't allocate private structure\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) goto err_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) viu_dev->vr = viu_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) viu_dev->irq = viu_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) viu_dev->dev = &op->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) /* init video dma queues */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) INIT_LIST_HEAD(&viu_dev->vidq.active);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) INIT_LIST_HEAD(&viu_dev->vidq.queued);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) snprintf(viu_dev->v4l2_dev.name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) sizeof(viu_dev->v4l2_dev.name), "%s", "VIU");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) ret = v4l2_device_register(viu_dev->dev, &viu_dev->v4l2_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) dev_err(&op->dev, "v4l2_device_register() failed: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) goto err_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) ad = i2c_get_adapter(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) if (!ad) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) ret = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) dev_err(&op->dev, "couldn't get i2c adapter\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) goto err_v4l2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) v4l2_ctrl_handler_init(&viu_dev->hdl, 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) if (viu_dev->hdl.error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) ret = viu_dev->hdl.error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) dev_err(&op->dev, "couldn't register control\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) goto err_i2c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) /* This control handler will inherit the control(s) from the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) sub-device(s). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) viu_dev->v4l2_dev.ctrl_handler = &viu_dev->hdl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) viu_dev->decoder = v4l2_i2c_new_subdev(&viu_dev->v4l2_dev, ad,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) "saa7113", VIU_VIDEO_DECODER_ADDR, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) timer_setup(&viu_dev->vidq.timeout, viu_vid_timeout, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) viu_dev->std = V4L2_STD_NTSC_M;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) viu_dev->first = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) /* Allocate memory for video device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) vdev = video_device_alloc();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) if (vdev == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) goto err_hdl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) *vdev = viu_template;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) vdev->v4l2_dev = &viu_dev->v4l2_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) viu_dev->vdev = vdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) /* initialize locks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) mutex_init(&viu_dev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) viu_dev->vdev->lock = &viu_dev->lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) spin_lock_init(&viu_dev->slock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) video_set_drvdata(viu_dev->vdev, viu_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) mutex_lock(&viu_dev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) ret = video_register_device(viu_dev->vdev, VFL_TYPE_VIDEO, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) video_device_release(viu_dev->vdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) goto err_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) /* enable VIU clock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) clk = devm_clk_get(&op->dev, "ipg");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) if (IS_ERR(clk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) dev_err(&op->dev, "failed to lookup the clock!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) ret = PTR_ERR(clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) goto err_vdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) ret = clk_prepare_enable(clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) dev_err(&op->dev, "failed to enable the clock!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) goto err_vdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) viu_dev->clk = clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) /* reset VIU module */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) viu_reset(viu_dev->vr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) /* install interrupt handler */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) if (request_irq(viu_dev->irq, viu_intr, 0, "viu", (void *)viu_dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) dev_err(&op->dev, "Request VIU IRQ failed.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) goto err_clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) mutex_unlock(&viu_dev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) dev_info(&op->dev, "Freescale VIU Video Capture Board\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) err_clk:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) clk_disable_unprepare(viu_dev->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) err_vdev:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) video_unregister_device(viu_dev->vdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) err_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) mutex_unlock(&viu_dev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) err_hdl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) v4l2_ctrl_handler_free(&viu_dev->hdl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) err_i2c:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) i2c_put_adapter(ad);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) err_v4l2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) v4l2_device_unregister(&viu_dev->v4l2_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) err_irq:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) irq_dispose_mapping(viu_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) static int viu_of_remove(struct platform_device *op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) struct v4l2_device *v4l2_dev = dev_get_drvdata(&op->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) struct viu_dev *dev = container_of(v4l2_dev, struct viu_dev, v4l2_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) struct v4l2_subdev *sdev = list_entry(v4l2_dev->subdevs.next,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) struct v4l2_subdev, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) struct i2c_client *client = v4l2_get_subdevdata(sdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) free_irq(dev->irq, (void *)dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) irq_dispose_mapping(dev->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) clk_disable_unprepare(dev->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) v4l2_ctrl_handler_free(&dev->hdl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) video_unregister_device(dev->vdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) i2c_put_adapter(client->adapter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) v4l2_device_unregister(&dev->v4l2_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) #ifdef CONFIG_PM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) static int viu_suspend(struct platform_device *op, pm_message_t state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) struct v4l2_device *v4l2_dev = dev_get_drvdata(&op->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) struct viu_dev *dev = container_of(v4l2_dev, struct viu_dev, v4l2_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) clk_disable(dev->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) static int viu_resume(struct platform_device *op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) struct v4l2_device *v4l2_dev = dev_get_drvdata(&op->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) struct viu_dev *dev = container_of(v4l2_dev, struct viu_dev, v4l2_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) clk_enable(dev->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) * Initialization and module stuff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) static const struct of_device_id mpc512x_viu_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) .compatible = "fsl,mpc5121-viu",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) {},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) MODULE_DEVICE_TABLE(of, mpc512x_viu_of_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) static struct platform_driver viu_of_platform_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) .probe = viu_of_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) .remove = viu_of_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) #ifdef CONFIG_PM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) .suspend = viu_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) .resume = viu_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) .name = DRV_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) .of_match_table = mpc512x_viu_of_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) module_platform_driver(viu_of_platform_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) MODULE_DESCRIPTION("Freescale Video-In(VIU)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) MODULE_AUTHOR("Hongjun Chen");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) MODULE_VERSION(VIU_VERSION);