^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 (C) 2010-2013 Bluecherry, LLC <https://www.bluecherrydvr.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Original author:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Ben Collins <bcollins@ubuntu.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Additional work by:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * John Brooks <john.brooks@bluecherry.net>
^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/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/kthread.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/freezer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <media/v4l2-ioctl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <media/v4l2-common.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <media/v4l2-event.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <media/videobuf2-dma-sg.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include "solo6x10.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include "solo6x10-tw28.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include "solo6x10-jpeg.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define MIN_VID_BUFFERS 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define FRAME_BUF_SIZE (400 * 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define MP4_QS 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define DMA_ALIGN 4096
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) /* 6010 M4V */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) static u8 vop_6010_ntsc_d1[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x20,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) 0x02, 0x48, 0x1d, 0xc0, 0x00, 0x40, 0x00, 0x40,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) 0x00, 0x40, 0x00, 0x80, 0x00, 0x97, 0x53, 0x04,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) 0x1f, 0x4c, 0x58, 0x10, 0xf0, 0x71, 0x18, 0x3f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) static u8 vop_6010_ntsc_cif[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x20,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) 0x02, 0x48, 0x1d, 0xc0, 0x00, 0x40, 0x00, 0x40,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) 0x00, 0x40, 0x00, 0x80, 0x00, 0x97, 0x53, 0x04,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) 0x1f, 0x4c, 0x2c, 0x10, 0x78, 0x51, 0x18, 0x3f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) static u8 vop_6010_pal_d1[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x20,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) 0x02, 0x48, 0x15, 0xc0, 0x00, 0x40, 0x00, 0x40,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) 0x00, 0x40, 0x00, 0x80, 0x00, 0x97, 0x53, 0x04,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) 0x1f, 0x4c, 0x58, 0x11, 0x20, 0x71, 0x18, 0x3f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) static u8 vop_6010_pal_cif[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x20,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) 0x02, 0x48, 0x15, 0xc0, 0x00, 0x40, 0x00, 0x40,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) 0x00, 0x40, 0x00, 0x80, 0x00, 0x97, 0x53, 0x04,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) 0x1f, 0x4c, 0x2c, 0x10, 0x90, 0x51, 0x18, 0x3f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) /* 6110 h.264 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) static u8 vop_6110_ntsc_d1[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00, 0x1e,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) 0x9a, 0x74, 0x05, 0x81, 0xec, 0x80, 0x00, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) 0x00, 0x01, 0x68, 0xce, 0x32, 0x28, 0x00, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) static u8 vop_6110_ntsc_cif[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00, 0x1e,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) 0x9a, 0x74, 0x0b, 0x0f, 0xc8, 0x00, 0x00, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) 0x01, 0x68, 0xce, 0x32, 0x28, 0x00, 0x00, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) static u8 vop_6110_pal_d1[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00, 0x1e,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) 0x9a, 0x74, 0x05, 0x80, 0x93, 0x20, 0x00, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) 0x00, 0x01, 0x68, 0xce, 0x32, 0x28, 0x00, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) static u8 vop_6110_pal_cif[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00, 0x1e,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) 0x9a, 0x74, 0x0b, 0x04, 0xb2, 0x00, 0x00, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) 0x01, 0x68, 0xce, 0x32, 0x28, 0x00, 0x00, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) typedef __le32 vop_header[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) struct solo_enc_buf {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) enum solo_enc_types type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) const vop_header *vh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) int motion;
^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) static int solo_is_motion_on(struct solo_enc_dev *solo_enc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) struct solo_dev *solo_dev = solo_enc->solo_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) return (solo_dev->motion_mask >> solo_enc->ch) & 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) static int solo_motion_detected(struct solo_enc_dev *solo_enc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) struct solo_dev *solo_dev = solo_enc->solo_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) u32 ch_mask = 1 << solo_enc->ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) spin_lock_irqsave(&solo_enc->motion_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) if (solo_reg_read(solo_dev, SOLO_VI_MOT_STATUS) & ch_mask) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) solo_reg_write(solo_dev, SOLO_VI_MOT_CLEAR, ch_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) ret = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) spin_unlock_irqrestore(&solo_enc->motion_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) static void solo_motion_toggle(struct solo_enc_dev *solo_enc, int on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) struct solo_dev *solo_dev = solo_enc->solo_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) u32 mask = 1 << solo_enc->ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) spin_lock_irqsave(&solo_enc->motion_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) if (on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) solo_dev->motion_mask |= mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) solo_dev->motion_mask &= ~mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) solo_reg_write(solo_dev, SOLO_VI_MOT_CLEAR, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) solo_reg_write(solo_dev, SOLO_VI_MOT_ADR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) SOLO_VI_MOTION_EN(solo_dev->motion_mask) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) (SOLO_MOTION_EXT_ADDR(solo_dev) >> 16));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) spin_unlock_irqrestore(&solo_enc->motion_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) void solo_update_mode(struct solo_enc_dev *solo_enc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) struct solo_dev *solo_dev = solo_enc->solo_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) int vop_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) u8 *vop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) solo_enc->interlaced = (solo_enc->mode & 0x08) ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) solo_enc->bw_weight = max(solo_dev->fps / solo_enc->interval, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) if (solo_enc->mode == SOLO_ENC_MODE_CIF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) solo_enc->width = solo_dev->video_hsize >> 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) solo_enc->height = solo_dev->video_vsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) if (solo_dev->type == SOLO_DEV_6110) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) vop = vop_6110_ntsc_cif;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) vop_len = sizeof(vop_6110_ntsc_cif);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) vop = vop_6110_pal_cif;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) vop_len = sizeof(vop_6110_pal_cif);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) vop = vop_6010_ntsc_cif;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) vop_len = sizeof(vop_6010_ntsc_cif);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) vop = vop_6010_pal_cif;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) vop_len = sizeof(vop_6010_pal_cif);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) solo_enc->width = solo_dev->video_hsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) solo_enc->height = solo_dev->video_vsize << 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) solo_enc->bw_weight <<= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) if (solo_dev->type == SOLO_DEV_6110) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) vop = vop_6110_ntsc_d1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) vop_len = sizeof(vop_6110_ntsc_d1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) vop = vop_6110_pal_d1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) vop_len = sizeof(vop_6110_pal_d1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) vop = vop_6010_ntsc_d1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) vop_len = sizeof(vop_6010_ntsc_d1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) vop = vop_6010_pal_d1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) vop_len = sizeof(vop_6010_pal_d1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) memcpy(solo_enc->vop, vop, vop_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) /* Some fixups for 6010/M4V */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) if (solo_dev->type == SOLO_DEV_6010) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) u16 fps = solo_dev->fps * 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) u16 interval = solo_enc->interval * 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) vop = solo_enc->vop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) /* Frame rate and interval */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) vop[22] = fps >> 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) vop[23] = ((fps << 4) & 0xf0) | 0x0c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) | ((interval >> 13) & 0x3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) vop[24] = (interval >> 5) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) vop[25] = ((interval << 3) & 0xf8) | 0x04;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) solo_enc->vop_len = vop_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) /* Now handle the jpeg header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) vop = solo_enc->jpeg_header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) vop[SOF0_START + 5] = 0xff & (solo_enc->height >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) vop[SOF0_START + 6] = 0xff & solo_enc->height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) vop[SOF0_START + 7] = 0xff & (solo_enc->width >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) vop[SOF0_START + 8] = 0xff & solo_enc->width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) memcpy(vop + DQT_START,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) jpeg_dqt[solo_g_jpeg_qp(solo_dev, solo_enc->ch)], DQT_LEN);
^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) static int solo_enc_on(struct solo_enc_dev *solo_enc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) u8 ch = solo_enc->ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) struct solo_dev *solo_dev = solo_enc->solo_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) u8 interval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) solo_update_mode(solo_enc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) /* Make sure to do a bandwidth check */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) if (solo_enc->bw_weight > solo_dev->enc_bw_remain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) solo_enc->sequence = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) solo_dev->enc_bw_remain -= solo_enc->bw_weight;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) if (solo_enc->type == SOLO_ENC_TYPE_EXT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) solo_reg_write(solo_dev, SOLO_CAP_CH_COMP_ENA_E(ch), 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) /* Disable all encoding for this channel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) solo_reg_write(solo_dev, SOLO_CAP_CH_SCALE(ch), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) /* Common for both std and ext encoding */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) solo_reg_write(solo_dev, SOLO_VE_CH_INTL(ch),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) solo_enc->interlaced ? 1 : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) if (solo_enc->interlaced)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) interval = solo_enc->interval - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) interval = solo_enc->interval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) /* Standard encoding only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) solo_reg_write(solo_dev, SOLO_VE_CH_GOP(ch), solo_enc->gop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) solo_reg_write(solo_dev, SOLO_VE_CH_QP(ch), solo_enc->qp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) solo_reg_write(solo_dev, SOLO_CAP_CH_INTV(ch), interval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) /* Extended encoding only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) solo_reg_write(solo_dev, SOLO_VE_CH_GOP_E(ch), solo_enc->gop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) solo_reg_write(solo_dev, SOLO_VE_CH_QP_E(ch), solo_enc->qp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) solo_reg_write(solo_dev, SOLO_CAP_CH_INTV_E(ch), interval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) /* Enables the standard encoder */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) solo_reg_write(solo_dev, SOLO_CAP_CH_SCALE(ch), solo_enc->mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) static void solo_enc_off(struct solo_enc_dev *solo_enc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) struct solo_dev *solo_dev = solo_enc->solo_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) solo_dev->enc_bw_remain += solo_enc->bw_weight;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) solo_reg_write(solo_dev, SOLO_CAP_CH_SCALE(solo_enc->ch), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) solo_reg_write(solo_dev, SOLO_CAP_CH_COMP_ENA_E(solo_enc->ch), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) static int enc_get_mpeg_dma(struct solo_dev *solo_dev, dma_addr_t dma,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) unsigned int off, unsigned int size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) if (off > SOLO_MP4E_EXT_SIZE(solo_dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) /* Single shot */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) if (off + size <= SOLO_MP4E_EXT_SIZE(solo_dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) return solo_p2m_dma_t(solo_dev, 0, dma,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) SOLO_MP4E_EXT_ADDR(solo_dev) + off, size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) /* Buffer wrap */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) ret = solo_p2m_dma_t(solo_dev, 0, dma,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) SOLO_MP4E_EXT_ADDR(solo_dev) + off,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) SOLO_MP4E_EXT_SIZE(solo_dev) - off, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) if (!ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) ret = solo_p2m_dma_t(solo_dev, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) dma + SOLO_MP4E_EXT_SIZE(solo_dev) - off,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) SOLO_MP4E_EXT_ADDR(solo_dev),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) size + off - SOLO_MP4E_EXT_SIZE(solo_dev), 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) /* Build a descriptor queue out of an SG list and send it to the P2M for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) * processing. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) static int solo_send_desc(struct solo_enc_dev *solo_enc, int skip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) struct sg_table *vbuf, int off, int size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) unsigned int base, unsigned int base_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) struct solo_dev *solo_dev = solo_enc->solo_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) struct scatterlist *sg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) if (WARN_ON_ONCE(size > FRAME_BUF_SIZE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) solo_enc->desc_count = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) for_each_sg(vbuf->sgl, sg, vbuf->nents, i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) struct solo_p2m_desc *desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) dma_addr_t dma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) int left = base_size - off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) desc = &solo_enc->desc_items[solo_enc->desc_count++];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) dma = sg_dma_address(sg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) len = sg_dma_len(sg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) /* We assume this is smaller than the scatter size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) BUG_ON(skip >= len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) if (skip) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) len -= skip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) dma += skip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) size -= skip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) skip = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) len = min(len, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) if (len <= left) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) /* Single descriptor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) solo_p2m_fill_desc(desc, 0, dma, base + off,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) len, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) /* Buffer wrap */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) /* XXX: Do these as separate DMA requests, to avoid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) timeout errors triggered by awkwardly sized
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) descriptors. See
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) <https://github.com/bluecherrydvr/solo6x10/issues/8>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) ret = solo_p2m_dma_t(solo_dev, 0, dma, base + off,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) left, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) ret = solo_p2m_dma_t(solo_dev, 0, dma + left, base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) len - left, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) solo_enc->desc_count--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) size -= len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) if (size <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) off += len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) if (off >= base_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) off -= base_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) /* Because we may use two descriptors per loop */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) if (solo_enc->desc_count >= (solo_enc->desc_nelts - 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) ret = solo_p2m_dma_desc(solo_dev, solo_enc->desc_items,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) solo_enc->desc_dma,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) solo_enc->desc_count - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) solo_enc->desc_count = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) if (solo_enc->desc_count <= 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) return solo_p2m_dma_desc(solo_dev, solo_enc->desc_items,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) solo_enc->desc_dma, solo_enc->desc_count - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) /* Extract values from VOP header - VE_STATUSxx */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) static inline int vop_interlaced(const vop_header *vh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) return (__le32_to_cpu((*vh)[0]) >> 30) & 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) static inline u8 vop_channel(const vop_header *vh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) return (__le32_to_cpu((*vh)[0]) >> 24) & 0x1F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) static inline u8 vop_type(const vop_header *vh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) return (__le32_to_cpu((*vh)[0]) >> 22) & 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) static inline u32 vop_mpeg_size(const vop_header *vh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) return __le32_to_cpu((*vh)[0]) & 0xFFFFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) static inline u8 vop_hsize(const vop_header *vh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) return (__le32_to_cpu((*vh)[1]) >> 8) & 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) static inline u8 vop_vsize(const vop_header *vh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) return __le32_to_cpu((*vh)[1]) & 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) static inline u32 vop_mpeg_offset(const vop_header *vh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) return __le32_to_cpu((*vh)[2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) static inline u32 vop_jpeg_offset(const vop_header *vh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) return __le32_to_cpu((*vh)[3]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) static inline u32 vop_jpeg_size(const vop_header *vh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) return __le32_to_cpu((*vh)[4]) & 0xFFFFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) static inline u32 vop_sec(const vop_header *vh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) return __le32_to_cpu((*vh)[5]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) static inline u32 vop_usec(const vop_header *vh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) return __le32_to_cpu((*vh)[6]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) static int solo_fill_jpeg(struct solo_enc_dev *solo_enc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) struct vb2_buffer *vb, const vop_header *vh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) struct solo_dev *solo_dev = solo_enc->solo_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) int frame_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) vbuf->flags |= V4L2_BUF_FLAG_KEYFRAME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) if (vb2_plane_size(vb, 0) < vop_jpeg_size(vh) + solo_enc->jpeg_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) frame_size = ALIGN(vop_jpeg_size(vh) + solo_enc->jpeg_len, DMA_ALIGN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) vb2_set_plane_payload(vb, 0, vop_jpeg_size(vh) + solo_enc->jpeg_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) return solo_send_desc(solo_enc, solo_enc->jpeg_len, sgt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) vop_jpeg_offset(vh) - SOLO_JPEG_EXT_ADDR(solo_dev),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) frame_size, SOLO_JPEG_EXT_ADDR(solo_dev),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) SOLO_JPEG_EXT_SIZE(solo_dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) static int solo_fill_mpeg(struct solo_enc_dev *solo_enc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) struct vb2_buffer *vb, const vop_header *vh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) struct solo_dev *solo_dev = solo_enc->solo_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) int frame_off, frame_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) int skip = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) if (vb2_plane_size(vb, 0) < vop_mpeg_size(vh))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) /* If this is a key frame, add extra header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) vbuf->flags &= ~(V4L2_BUF_FLAG_KEYFRAME | V4L2_BUF_FLAG_PFRAME |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) V4L2_BUF_FLAG_BFRAME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) if (!vop_type(vh)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) skip = solo_enc->vop_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) vbuf->flags |= V4L2_BUF_FLAG_KEYFRAME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) vb2_set_plane_payload(vb, 0, vop_mpeg_size(vh) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) solo_enc->vop_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) vbuf->flags |= V4L2_BUF_FLAG_PFRAME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) vb2_set_plane_payload(vb, 0, vop_mpeg_size(vh));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) /* Now get the actual mpeg payload */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) frame_off = (vop_mpeg_offset(vh) - SOLO_MP4E_EXT_ADDR(solo_dev) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) sizeof(*vh)) % SOLO_MP4E_EXT_SIZE(solo_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) frame_size = ALIGN(vop_mpeg_size(vh) + skip, DMA_ALIGN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) return solo_send_desc(solo_enc, skip, sgt, frame_off, frame_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) SOLO_MP4E_EXT_ADDR(solo_dev),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) SOLO_MP4E_EXT_SIZE(solo_dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) static int solo_enc_fillbuf(struct solo_enc_dev *solo_enc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) struct vb2_buffer *vb, struct solo_enc_buf *enc_buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) const vop_header *vh = enc_buf->vh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) switch (solo_enc->fmt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) case V4L2_PIX_FMT_MPEG4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) case V4L2_PIX_FMT_H264:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) ret = solo_fill_mpeg(solo_enc, vb, vh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) default: /* V4L2_PIX_FMT_MJPEG */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) ret = solo_fill_jpeg(solo_enc, vb, vh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) if (!ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) vbuf->sequence = solo_enc->sequence++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) vb->timestamp = ktime_get_ns();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) /* Check for motion flags */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) if (solo_is_motion_on(solo_enc) && enc_buf->motion) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) struct v4l2_event ev = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) .type = V4L2_EVENT_MOTION_DET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) .u.motion_det = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) .flags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) = V4L2_EVENT_MD_FL_HAVE_FRAME_SEQ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) .frame_sequence = vbuf->sequence,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) .region_mask = enc_buf->motion ? 1 : 0,
^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) v4l2_event_queue(solo_enc->vfd, &ev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) vb2_buffer_done(vb, ret ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) static void solo_enc_handle_one(struct solo_enc_dev *solo_enc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) struct solo_enc_buf *enc_buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) struct solo_vb2_buf *vb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) mutex_lock(&solo_enc->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) if (solo_enc->type != enc_buf->type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) goto unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) spin_lock_irqsave(&solo_enc->av_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) if (list_empty(&solo_enc->vidq_active)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) spin_unlock_irqrestore(&solo_enc->av_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) goto unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) vb = list_first_entry(&solo_enc->vidq_active, struct solo_vb2_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) list_del(&vb->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) spin_unlock_irqrestore(&solo_enc->av_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) solo_enc_fillbuf(solo_enc, &vb->vb.vb2_buf, enc_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) mutex_unlock(&solo_enc->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) void solo_enc_v4l2_isr(struct solo_dev *solo_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) wake_up_interruptible_all(&solo_dev->ring_thread_wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) static void solo_handle_ring(struct solo_dev *solo_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) struct solo_enc_dev *solo_enc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) struct solo_enc_buf enc_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) u32 mpeg_current, off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) u8 ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) u8 cur_q;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) /* Check if the hardware has any new ones in the queue */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) cur_q = solo_reg_read(solo_dev, SOLO_VE_STATE(11)) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) if (cur_q == solo_dev->enc_idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) mpeg_current = solo_reg_read(solo_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) SOLO_VE_MPEG4_QUE(solo_dev->enc_idx));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) solo_dev->enc_idx = (solo_dev->enc_idx + 1) % MP4_QS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) ch = (mpeg_current >> 24) & 0x1f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) off = mpeg_current & 0x00ffffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) if (ch >= SOLO_MAX_CHANNELS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) ch -= SOLO_MAX_CHANNELS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) enc_buf.type = SOLO_ENC_TYPE_EXT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) enc_buf.type = SOLO_ENC_TYPE_STD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) solo_enc = solo_dev->v4l2_enc[ch];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) if (solo_enc == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) dev_err(&solo_dev->pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) "Got spurious packet for channel %d\n", ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) /* FAIL... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) if (enc_get_mpeg_dma(solo_dev, solo_dev->vh_dma, off,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) sizeof(vop_header)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) enc_buf.vh = solo_dev->vh_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) /* Sanity check */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) if (vop_mpeg_offset(enc_buf.vh) !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) SOLO_MP4E_EXT_ADDR(solo_dev) + off)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) if (solo_motion_detected(solo_enc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) enc_buf.motion = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) enc_buf.motion = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) solo_enc_handle_one(solo_enc, &enc_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) static int solo_ring_thread(void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) struct solo_dev *solo_dev = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) DECLARE_WAITQUEUE(wait, current);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) set_freezable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) add_wait_queue(&solo_dev->ring_thread_wait, &wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) long timeout = schedule_timeout_interruptible(HZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) if (timeout == -ERESTARTSYS || kthread_should_stop())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) solo_handle_ring(solo_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) try_to_freeze();
^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) remove_wait_queue(&solo_dev->ring_thread_wait, &wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) static int solo_enc_queue_setup(struct vb2_queue *q,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) unsigned int *num_buffers,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) unsigned int *num_planes, unsigned int sizes[],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) struct device *alloc_devs[])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) sizes[0] = FRAME_BUF_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) *num_planes = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) if (*num_buffers < MIN_VID_BUFFERS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) *num_buffers = MIN_VID_BUFFERS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) static void solo_enc_buf_queue(struct vb2_buffer *vb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) struct vb2_queue *vq = vb->vb2_queue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) struct solo_enc_dev *solo_enc = vb2_get_drv_priv(vq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) struct solo_vb2_buf *solo_vb =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) container_of(vbuf, struct solo_vb2_buf, vb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) spin_lock(&solo_enc->av_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) list_add_tail(&solo_vb->list, &solo_enc->vidq_active);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) spin_unlock(&solo_enc->av_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) static int solo_ring_start(struct solo_dev *solo_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) solo_dev->ring_thread = kthread_run(solo_ring_thread, solo_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) SOLO6X10_NAME "_ring");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) if (IS_ERR(solo_dev->ring_thread)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) int err = PTR_ERR(solo_dev->ring_thread);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) solo_dev->ring_thread = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) solo_irq_on(solo_dev, SOLO_IRQ_ENCODER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) static void solo_ring_stop(struct solo_dev *solo_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) if (solo_dev->ring_thread) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) kthread_stop(solo_dev->ring_thread);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) solo_dev->ring_thread = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) solo_irq_off(solo_dev, SOLO_IRQ_ENCODER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) static int solo_enc_start_streaming(struct vb2_queue *q, unsigned int count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) struct solo_enc_dev *solo_enc = vb2_get_drv_priv(q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) return solo_enc_on(solo_enc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) static void solo_enc_stop_streaming(struct vb2_queue *q)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) struct solo_enc_dev *solo_enc = vb2_get_drv_priv(q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) spin_lock_irqsave(&solo_enc->av_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) solo_enc_off(solo_enc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) while (!list_empty(&solo_enc->vidq_active)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) struct solo_vb2_buf *buf = list_entry(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) solo_enc->vidq_active.next,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) struct solo_vb2_buf, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) list_del(&buf->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) spin_unlock_irqrestore(&solo_enc->av_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) static void solo_enc_buf_finish(struct vb2_buffer *vb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) struct solo_enc_dev *solo_enc = vb2_get_drv_priv(vb->vb2_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) switch (solo_enc->fmt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) case V4L2_PIX_FMT_MPEG4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) case V4L2_PIX_FMT_H264:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) if (vbuf->flags & V4L2_BUF_FLAG_KEYFRAME)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) sg_copy_from_buffer(sgt->sgl, sgt->nents,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) solo_enc->vop, solo_enc->vop_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) default: /* V4L2_PIX_FMT_MJPEG */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) sg_copy_from_buffer(sgt->sgl, sgt->nents,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) solo_enc->jpeg_header, solo_enc->jpeg_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) static const struct vb2_ops solo_enc_video_qops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) .queue_setup = solo_enc_queue_setup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) .buf_queue = solo_enc_buf_queue,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) .buf_finish = solo_enc_buf_finish,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) .start_streaming = solo_enc_start_streaming,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) .stop_streaming = solo_enc_stop_streaming,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) .wait_prepare = vb2_ops_wait_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) .wait_finish = vb2_ops_wait_finish,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) static int solo_enc_querycap(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) struct v4l2_capability *cap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) struct solo_enc_dev *solo_enc = video_drvdata(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) struct solo_dev *solo_dev = solo_enc->solo_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) strscpy(cap->driver, SOLO6X10_NAME, sizeof(cap->driver));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) snprintf(cap->card, sizeof(cap->card), "Softlogic 6x10 Enc %d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) solo_enc->ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) pci_name(solo_dev->pdev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) static int solo_enc_enum_input(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) struct v4l2_input *input)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) struct solo_enc_dev *solo_enc = video_drvdata(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) struct solo_dev *solo_dev = solo_enc->solo_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) if (input->index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) snprintf(input->name, sizeof(input->name), "Encoder %d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) solo_enc->ch + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) input->type = V4L2_INPUT_TYPE_CAMERA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) input->std = solo_enc->vfd->tvnorms;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) if (!tw28_get_video_status(solo_dev, solo_enc->ch))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) input->status = V4L2_IN_ST_NO_SIGNAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) static int solo_enc_set_input(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) unsigned int index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) if (index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) static int solo_enc_get_input(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) unsigned int *index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) *index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) static int solo_enc_enum_fmt_cap(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) struct v4l2_fmtdesc *f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) struct solo_enc_dev *solo_enc = video_drvdata(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) int dev_type = solo_enc->solo_dev->type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) switch (f->index) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) switch (dev_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) case SOLO_DEV_6010:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) f->pixelformat = V4L2_PIX_FMT_MPEG4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) case SOLO_DEV_6110:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) f->pixelformat = V4L2_PIX_FMT_H264;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) f->pixelformat = V4L2_PIX_FMT_MJPEG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) return 0;
^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 inline int solo_valid_pixfmt(u32 pixfmt, int dev_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) return (pixfmt == V4L2_PIX_FMT_H264 && dev_type == SOLO_DEV_6110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) || (pixfmt == V4L2_PIX_FMT_MPEG4 && dev_type == SOLO_DEV_6010)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) || pixfmt == V4L2_PIX_FMT_MJPEG ? 0 : -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) static int solo_enc_try_fmt_cap(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) struct v4l2_format *f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) struct solo_enc_dev *solo_enc = video_drvdata(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) struct solo_dev *solo_dev = solo_enc->solo_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) struct v4l2_pix_format *pix = &f->fmt.pix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) if (solo_valid_pixfmt(pix->pixelformat, solo_dev->type))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) if (pix->width < solo_dev->video_hsize ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) pix->height < solo_dev->video_vsize << 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) /* Default to CIF 1/2 size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) pix->width = solo_dev->video_hsize >> 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) pix->height = solo_dev->video_vsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) /* Full frame */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) pix->width = solo_dev->video_hsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) pix->height = solo_dev->video_vsize << 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) switch (pix->field) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) case V4L2_FIELD_NONE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) case V4L2_FIELD_INTERLACED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) case V4L2_FIELD_ANY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) pix->field = V4L2_FIELD_INTERLACED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) /* Just set these */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) pix->colorspace = V4L2_COLORSPACE_SMPTE170M;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) pix->sizeimage = FRAME_BUF_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) pix->bytesperline = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) static int solo_enc_set_fmt_cap(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) struct v4l2_format *f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) struct solo_enc_dev *solo_enc = video_drvdata(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) struct solo_dev *solo_dev = solo_enc->solo_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) struct v4l2_pix_format *pix = &f->fmt.pix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) if (vb2_is_busy(&solo_enc->vidq))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) ret = solo_enc_try_fmt_cap(file, priv, f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) if (pix->width == solo_dev->video_hsize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) solo_enc->mode = SOLO_ENC_MODE_D1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) solo_enc->mode = SOLO_ENC_MODE_CIF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) /* This does not change the encoder at all */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) solo_enc->fmt = pix->pixelformat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) * More information is needed about these 'extended' types. As far
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) * as I can tell these are basically additional video streams with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) * different MPEG encoding attributes that can run in parallel with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) * the main stream. If so, then this should be implemented as a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) * second video node. Abusing priv like this is certainly not the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) * right approach.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) if (pix->priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) solo_enc->type = SOLO_ENC_TYPE_EXT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) solo_update_mode(solo_enc);
^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) static int solo_enc_get_fmt_cap(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) struct v4l2_format *f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) struct solo_enc_dev *solo_enc = video_drvdata(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) struct v4l2_pix_format *pix = &f->fmt.pix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) pix->width = solo_enc->width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) pix->height = solo_enc->height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) pix->pixelformat = solo_enc->fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) pix->field = solo_enc->interlaced ? V4L2_FIELD_INTERLACED :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) V4L2_FIELD_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) pix->sizeimage = FRAME_BUF_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) pix->colorspace = V4L2_COLORSPACE_SMPTE170M;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) static int solo_enc_g_std(struct file *file, void *priv, v4l2_std_id *i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) struct solo_enc_dev *solo_enc = video_drvdata(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) struct solo_dev *solo_dev = solo_enc->solo_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) *i = V4L2_STD_NTSC_M;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) *i = V4L2_STD_PAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) static int solo_enc_s_std(struct file *file, void *priv, v4l2_std_id std)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) struct solo_enc_dev *solo_enc = video_drvdata(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) return solo_set_video_type(solo_enc->solo_dev, std & V4L2_STD_625_50);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) static int solo_enum_framesizes(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) struct v4l2_frmsizeenum *fsize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) struct solo_enc_dev *solo_enc = video_drvdata(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) struct solo_dev *solo_dev = solo_enc->solo_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) if (solo_valid_pixfmt(fsize->pixel_format, solo_dev->type))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) switch (fsize->index) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) fsize->discrete.width = solo_dev->video_hsize >> 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) fsize->discrete.height = solo_dev->video_vsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) fsize->discrete.width = solo_dev->video_hsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) fsize->discrete.height = solo_dev->video_vsize << 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) static int solo_enum_frameintervals(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) struct v4l2_frmivalenum *fintv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) struct solo_enc_dev *solo_enc = video_drvdata(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) struct solo_dev *solo_dev = solo_enc->solo_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) if (solo_valid_pixfmt(fintv->pixel_format, solo_dev->type))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) if (fintv->index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) if ((fintv->width != solo_dev->video_hsize >> 1 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) fintv->height != solo_dev->video_vsize) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) (fintv->width != solo_dev->video_hsize ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) fintv->height != solo_dev->video_vsize << 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) fintv->type = V4L2_FRMIVAL_TYPE_STEPWISE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) fintv->stepwise.min.numerator = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) fintv->stepwise.min.denominator = solo_dev->fps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) fintv->stepwise.max.numerator = 15;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) fintv->stepwise.max.denominator = solo_dev->fps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) fintv->stepwise.step.numerator = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) fintv->stepwise.step.denominator = solo_dev->fps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) static int solo_g_parm(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) struct v4l2_streamparm *sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) struct solo_enc_dev *solo_enc = video_drvdata(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) struct v4l2_captureparm *cp = &sp->parm.capture;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) cp->capability = V4L2_CAP_TIMEPERFRAME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) cp->timeperframe.numerator = solo_enc->interval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) cp->timeperframe.denominator = solo_enc->solo_dev->fps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) cp->capturemode = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) /* XXX: Shouldn't we be able to get/set this from videobuf? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) cp->readbuffers = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) static inline int calc_interval(u8 fps, u32 n, u32 d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) if (!n || !d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) if (d == fps)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) return n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) n *= fps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) return min(15U, n / d + (n % d >= (fps >> 1)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) static int solo_s_parm(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) struct v4l2_streamparm *sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) struct solo_enc_dev *solo_enc = video_drvdata(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) struct v4l2_fract *t = &sp->parm.capture.timeperframe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) u8 fps = solo_enc->solo_dev->fps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) if (vb2_is_streaming(&solo_enc->vidq))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) solo_enc->interval = calc_interval(fps, t->numerator, t->denominator);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) solo_update_mode(solo_enc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) return solo_g_parm(file, priv, sp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) static int solo_s_ctrl(struct v4l2_ctrl *ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) struct solo_enc_dev *solo_enc =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) container_of(ctrl->handler, struct solo_enc_dev, hdl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) struct solo_dev *solo_dev = solo_enc->solo_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) switch (ctrl->id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) case V4L2_CID_BRIGHTNESS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) case V4L2_CID_CONTRAST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) case V4L2_CID_SATURATION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) case V4L2_CID_HUE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) case V4L2_CID_SHARPNESS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) return tw28_set_ctrl_val(solo_dev, ctrl->id, solo_enc->ch,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) solo_enc->gop = ctrl->val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) solo_reg_write(solo_dev, SOLO_VE_CH_GOP(solo_enc->ch), solo_enc->gop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) solo_reg_write(solo_dev, SOLO_VE_CH_GOP_E(solo_enc->ch), solo_enc->gop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) case V4L2_CID_MPEG_VIDEO_H264_MIN_QP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) solo_enc->qp = ctrl->val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) solo_reg_write(solo_dev, SOLO_VE_CH_QP(solo_enc->ch), solo_enc->qp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) solo_reg_write(solo_dev, SOLO_VE_CH_QP_E(solo_enc->ch), solo_enc->qp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) case V4L2_CID_DETECT_MD_GLOBAL_THRESHOLD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) solo_enc->motion_thresh = ctrl->val << 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) if (!solo_enc->motion_global || !solo_enc->motion_enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) return solo_set_motion_threshold(solo_dev, solo_enc->ch,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) solo_enc->motion_thresh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) case V4L2_CID_DETECT_MD_MODE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) solo_enc->motion_global = ctrl->val == V4L2_DETECT_MD_MODE_GLOBAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) solo_enc->motion_enabled = ctrl->val > V4L2_DETECT_MD_MODE_DISABLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) if (ctrl->val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) if (solo_enc->motion_global)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) err = solo_set_motion_threshold(solo_dev, solo_enc->ch,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) solo_enc->motion_thresh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) err = solo_set_motion_block(solo_dev, solo_enc->ch,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) solo_enc->md_thresholds->p_cur.p_u16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) solo_motion_toggle(solo_enc, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) case V4L2_CID_DETECT_MD_THRESHOLD_GRID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) if (solo_enc->motion_enabled && !solo_enc->motion_global)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) return solo_set_motion_block(solo_dev, solo_enc->ch,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) solo_enc->md_thresholds->p_new.p_u16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) case V4L2_CID_OSD_TEXT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) strscpy(solo_enc->osd_text, ctrl->p_new.p_char,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) sizeof(solo_enc->osd_text));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) return solo_osd_print(solo_enc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) static int solo_subscribe_event(struct v4l2_fh *fh,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) const struct v4l2_event_subscription *sub)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) switch (sub->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) case V4L2_EVENT_MOTION_DET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) /* Allow for up to 30 events (1 second for NTSC) to be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) * stored. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) return v4l2_event_subscribe(fh, sub, 30, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) return v4l2_ctrl_subscribe_event(fh, sub);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) static const struct v4l2_file_operations solo_enc_fops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) .open = v4l2_fh_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) .release = vb2_fop_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) .read = vb2_fop_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) .poll = vb2_fop_poll,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) .mmap = vb2_fop_mmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) .unlocked_ioctl = video_ioctl2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) static const struct v4l2_ioctl_ops solo_enc_ioctl_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) .vidioc_querycap = solo_enc_querycap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) .vidioc_s_std = solo_enc_s_std,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) .vidioc_g_std = solo_enc_g_std,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) /* Input callbacks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) .vidioc_enum_input = solo_enc_enum_input,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) .vidioc_s_input = solo_enc_set_input,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) .vidioc_g_input = solo_enc_get_input,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) /* Video capture format callbacks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) .vidioc_enum_fmt_vid_cap = solo_enc_enum_fmt_cap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) .vidioc_try_fmt_vid_cap = solo_enc_try_fmt_cap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) .vidioc_s_fmt_vid_cap = solo_enc_set_fmt_cap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) .vidioc_g_fmt_vid_cap = solo_enc_get_fmt_cap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) /* Streaming I/O */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) .vidioc_reqbufs = vb2_ioctl_reqbufs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) .vidioc_querybuf = vb2_ioctl_querybuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) .vidioc_qbuf = vb2_ioctl_qbuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) .vidioc_dqbuf = vb2_ioctl_dqbuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) .vidioc_streamon = vb2_ioctl_streamon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) .vidioc_streamoff = vb2_ioctl_streamoff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) /* Frame size and interval */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) .vidioc_enum_framesizes = solo_enum_framesizes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) .vidioc_enum_frameintervals = solo_enum_frameintervals,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) /* Video capture parameters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) .vidioc_s_parm = solo_s_parm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) .vidioc_g_parm = solo_g_parm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) /* Logging and events */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) .vidioc_log_status = v4l2_ctrl_log_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) .vidioc_subscribe_event = solo_subscribe_event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) static const struct video_device solo_enc_template = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) .name = SOLO6X10_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) .fops = &solo_enc_fops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) .ioctl_ops = &solo_enc_ioctl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) .minor = -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) .release = video_device_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) .tvnorms = V4L2_STD_NTSC_M | V4L2_STD_PAL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) .device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) V4L2_CAP_STREAMING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) static const struct v4l2_ctrl_ops solo_ctrl_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) .s_ctrl = solo_s_ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) static const struct v4l2_ctrl_config solo_osd_text_ctrl = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) .ops = &solo_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) .id = V4L2_CID_OSD_TEXT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) .name = "OSD Text",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) .type = V4L2_CTRL_TYPE_STRING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) .max = OSD_TEXT_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) .step = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) /* Motion Detection Threshold matrix */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) static const struct v4l2_ctrl_config solo_md_thresholds = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) .ops = &solo_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) .id = V4L2_CID_DETECT_MD_THRESHOLD_GRID,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) .dims = { SOLO_MOTION_SZ, SOLO_MOTION_SZ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) .def = SOLO_DEF_MOT_THRESH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) .max = 65535,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) .step = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) static struct solo_enc_dev *solo_enc_alloc(struct solo_dev *solo_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) u8 ch, unsigned nr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) struct solo_enc_dev *solo_enc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) struct v4l2_ctrl_handler *hdl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) solo_enc = kzalloc(sizeof(*solo_enc), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) if (!solo_enc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) hdl = &solo_enc->hdl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) v4l2_ctrl_handler_init(hdl, 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) V4L2_CID_CONTRAST, 0, 255, 1, 128);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) V4L2_CID_SATURATION, 0, 255, 1, 128);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) V4L2_CID_HUE, 0, 255, 1, 128);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) if (tw28_has_sharpness(solo_dev, ch))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) V4L2_CID_SHARPNESS, 0, 15, 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) V4L2_CID_MPEG_VIDEO_GOP_SIZE, 1, 255, 1, solo_dev->fps);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) V4L2_CID_MPEG_VIDEO_H264_MIN_QP, 0, 31, 1, SOLO_DEFAULT_QP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) v4l2_ctrl_new_std_menu(hdl, &solo_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) V4L2_CID_DETECT_MD_MODE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) V4L2_DETECT_MD_MODE_THRESHOLD_GRID, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) V4L2_DETECT_MD_MODE_DISABLED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) V4L2_CID_DETECT_MD_GLOBAL_THRESHOLD, 0, 0xff, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) SOLO_DEF_MOT_THRESH >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) v4l2_ctrl_new_custom(hdl, &solo_osd_text_ctrl, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) solo_enc->md_thresholds =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) v4l2_ctrl_new_custom(hdl, &solo_md_thresholds, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) if (hdl->error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) ret = hdl->error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) goto hdl_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) solo_enc->solo_dev = solo_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) solo_enc->ch = ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) mutex_init(&solo_enc->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) spin_lock_init(&solo_enc->av_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) INIT_LIST_HEAD(&solo_enc->vidq_active);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) solo_enc->fmt = (solo_dev->type == SOLO_DEV_6010) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) V4L2_PIX_FMT_MPEG4 : V4L2_PIX_FMT_H264;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) solo_enc->type = SOLO_ENC_TYPE_STD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) solo_enc->qp = SOLO_DEFAULT_QP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) solo_enc->gop = solo_dev->fps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) solo_enc->interval = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) solo_enc->mode = SOLO_ENC_MODE_CIF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) solo_enc->motion_global = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) solo_enc->motion_thresh = SOLO_DEF_MOT_THRESH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) solo_enc->vidq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) solo_enc->vidq.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) solo_enc->vidq.ops = &solo_enc_video_qops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) solo_enc->vidq.mem_ops = &vb2_dma_sg_memops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) solo_enc->vidq.drv_priv = solo_enc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) solo_enc->vidq.gfp_flags = __GFP_DMA32 | __GFP_KSWAPD_RECLAIM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) solo_enc->vidq.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) solo_enc->vidq.buf_struct_size = sizeof(struct solo_vb2_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) solo_enc->vidq.lock = &solo_enc->lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) solo_enc->vidq.dev = &solo_dev->pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) ret = vb2_queue_init(&solo_enc->vidq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) goto hdl_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) solo_update_mode(solo_enc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) spin_lock_init(&solo_enc->motion_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) /* Initialize this per encoder */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) solo_enc->jpeg_len = sizeof(jpeg_header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) memcpy(solo_enc->jpeg_header, jpeg_header, solo_enc->jpeg_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) solo_enc->desc_nelts = 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) solo_enc->desc_items = pci_alloc_consistent(solo_dev->pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) sizeof(struct solo_p2m_desc) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) solo_enc->desc_nelts,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) &solo_enc->desc_dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) if (solo_enc->desc_items == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) goto hdl_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) solo_enc->vfd = video_device_alloc();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) if (!solo_enc->vfd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) goto pci_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) *solo_enc->vfd = solo_enc_template;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) solo_enc->vfd->v4l2_dev = &solo_dev->v4l2_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) solo_enc->vfd->ctrl_handler = hdl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) solo_enc->vfd->queue = &solo_enc->vidq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) solo_enc->vfd->lock = &solo_enc->lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) video_set_drvdata(solo_enc->vfd, solo_enc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) ret = video_register_device(solo_enc->vfd, VFL_TYPE_VIDEO, nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) goto vdev_release;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) snprintf(solo_enc->vfd->name, sizeof(solo_enc->vfd->name),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) "%s-enc (%i/%i)", SOLO6X10_NAME, solo_dev->vfd->num,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) solo_enc->vfd->num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) return solo_enc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) vdev_release:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) video_device_release(solo_enc->vfd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) pci_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) pci_free_consistent(solo_enc->solo_dev->pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) sizeof(struct solo_p2m_desc) * solo_enc->desc_nelts,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) solo_enc->desc_items, solo_enc->desc_dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) hdl_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) v4l2_ctrl_handler_free(hdl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) kfree(solo_enc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) return ERR_PTR(ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) static void solo_enc_free(struct solo_enc_dev *solo_enc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) if (solo_enc == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) pci_free_consistent(solo_enc->solo_dev->pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) sizeof(struct solo_p2m_desc) * solo_enc->desc_nelts,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) solo_enc->desc_items, solo_enc->desc_dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) video_unregister_device(solo_enc->vfd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) v4l2_ctrl_handler_free(&solo_enc->hdl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) kfree(solo_enc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) int solo_enc_v4l2_init(struct solo_dev *solo_dev, unsigned nr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) init_waitqueue_head(&solo_dev->ring_thread_wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) solo_dev->vh_size = sizeof(vop_header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) solo_dev->vh_buf = pci_alloc_consistent(solo_dev->pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) solo_dev->vh_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) &solo_dev->vh_dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) if (solo_dev->vh_buf == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) for (i = 0; i < solo_dev->nr_chans; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) solo_dev->v4l2_enc[i] = solo_enc_alloc(solo_dev, i, nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) if (IS_ERR(solo_dev->v4l2_enc[i]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) if (i != solo_dev->nr_chans) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) int ret = PTR_ERR(solo_dev->v4l2_enc[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) while (i--)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) solo_enc_free(solo_dev->v4l2_enc[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) pci_free_consistent(solo_dev->pdev, solo_dev->vh_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) solo_dev->vh_buf, solo_dev->vh_dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) solo_dev->vh_buf = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) if (solo_dev->type == SOLO_DEV_6010)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) solo_dev->enc_bw_remain = solo_dev->fps * 4 * 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) solo_dev->enc_bw_remain = solo_dev->fps * 4 * 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) dev_info(&solo_dev->pdev->dev, "Encoders as /dev/video%d-%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) solo_dev->v4l2_enc[0]->vfd->num,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) solo_dev->v4l2_enc[solo_dev->nr_chans - 1]->vfd->num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) return solo_ring_start(solo_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) void solo_enc_v4l2_exit(struct solo_dev *solo_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) solo_ring_stop(solo_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) for (i = 0; i < solo_dev->nr_chans; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) solo_enc_free(solo_dev->v4l2_enc[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) if (solo_dev->vh_buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) pci_free_consistent(solo_dev->pdev, solo_dev->vh_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) solo_dev->vh_buf, solo_dev->vh_dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) }