Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'br-v5.18r' of git://linuxtv.org/hverkuil/media_tree into media_stage

Tag branch

* tag 'br-v5.18r' of git://linuxtv.org/hverkuil/media_tree:
media: amphion: add amphion vpu entry in Kconfig and Makefile
MAINTAINERS: add AMPHION VPU CODEC V4L2 driver entry
media: amphion: implement malone decoder rpc interface
media: amphion: implement windsor encoder rpc interface
media: amphion: add v4l2 m2m vpu decoder stateful driver
media: amphion: add v4l2 m2m vpu encoder stateful driver
media: amphion: add vpu v4l2 m2m support
media: amphion: implement vpu core communication based on mailbox
media: amphion: add vpu core driver
media: amphion: add amphion vpu device driver
media: add nv12m_8l128 and nv12m_10be_8l128 video format.
dt-bindings: media: amphion: add amphion video codec bindings

Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>

+11967 -3
+180
Documentation/devicetree/bindings/media/amphion,vpu.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) 2 + 3 + %YAML 1.2 4 + --- 5 + $id: http://devicetree.org/schemas/media/amphion,vpu.yaml# 6 + $schema: http://devicetree.org/meta-schemas/core.yaml# 7 + 8 + title: Amphion VPU codec IP 9 + 10 + maintainers: 11 + - Ming Qian <ming.qian@nxp.com> 12 + - Shijie Qin <shijie.qin@nxp.com> 13 + 14 + description: |- 15 + The Amphion MXC video encoder(Windsor) and decoder(Malone) accelerators present 16 + on NXP i.MX8Q SoCs. 17 + 18 + properties: 19 + $nodename: 20 + pattern: "^vpu@[0-9a-f]+$" 21 + 22 + compatible: 23 + items: 24 + - enum: 25 + - nxp,imx8qm-vpu 26 + - nxp,imx8qxp-vpu 27 + 28 + reg: 29 + maxItems: 1 30 + 31 + power-domains: 32 + maxItems: 1 33 + 34 + "#address-cells": 35 + const: 1 36 + 37 + "#size-cells": 38 + const: 1 39 + 40 + ranges: true 41 + 42 + patternProperties: 43 + "^mailbox@[0-9a-f]+$": 44 + description: 45 + Each vpu encoder or decoder correspond a MU, which used for communication 46 + between driver and firmware. Implement via mailbox on driver. 47 + $ref: ../mailbox/fsl,mu.yaml# 48 + 49 + 50 + "^vpu_core@[0-9a-f]+$": 51 + description: 52 + Each core correspond a decoder or encoder, need to configure them 53 + separately. NXP i.MX8QM SoC has one decoder and two encoder, i.MX8QXP SoC 54 + has one decoder and one encoder. 55 + type: object 56 + 57 + properties: 58 + compatible: 59 + items: 60 + - enum: 61 + - nxp,imx8q-vpu-decoder 62 + - nxp,imx8q-vpu-encoder 63 + 64 + reg: 65 + maxItems: 1 66 + 67 + power-domains: 68 + maxItems: 1 69 + 70 + mbox-names: 71 + items: 72 + - const: tx0 73 + - const: tx1 74 + - const: rx 75 + 76 + mboxes: 77 + description: 78 + List of phandle of 2 MU channels for tx, 1 MU channel for rx. 79 + maxItems: 3 80 + 81 + memory-region: 82 + description: 83 + Phandle to the reserved memory nodes to be associated with the 84 + remoteproc device. The reserved memory nodes should be carveout nodes, 85 + and should be defined as per the bindings in 86 + Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt 87 + items: 88 + - description: region reserved for firmware image sections. 89 + - description: region used for RPC shared memory between firmware and 90 + driver. 91 + 92 + required: 93 + - compatible 94 + - reg 95 + - power-domains 96 + - mbox-names 97 + - mboxes 98 + - memory-region 99 + 100 + additionalProperties: false 101 + 102 + required: 103 + - compatible 104 + - reg 105 + - power-domains 106 + 107 + additionalProperties: false 108 + 109 + examples: 110 + # Device node example for i.MX8QM platform: 111 + - | 112 + #include <dt-bindings/firmware/imx/rsrc.h> 113 + 114 + vpu: vpu@2c000000 { 115 + compatible = "nxp,imx8qm-vpu"; 116 + ranges = <0x2c000000 0x2c000000 0x2000000>; 117 + reg = <0x2c000000 0x1000000>; 118 + #address-cells = <1>; 119 + #size-cells = <1>; 120 + power-domains = <&pd IMX_SC_R_VPU>; 121 + 122 + mu_m0: mailbox@2d000000 { 123 + compatible = "fsl,imx6sx-mu"; 124 + reg = <0x2d000000 0x20000>; 125 + interrupts = <0 472 4>; 126 + #mbox-cells = <2>; 127 + power-domains = <&pd IMX_SC_R_VPU_MU_0>; 128 + }; 129 + 130 + mu1_m0: mailbox@2d020000 { 131 + compatible = "fsl,imx6sx-mu"; 132 + reg = <0x2d020000 0x20000>; 133 + interrupts = <0 473 4>; 134 + #mbox-cells = <2>; 135 + power-domains = <&pd IMX_SC_R_VPU_MU_1>; 136 + }; 137 + 138 + mu2_m0: mailbox@2d040000 { 139 + compatible = "fsl,imx6sx-mu"; 140 + reg = <0x2d040000 0x20000>; 141 + interrupts = <0 474 4>; 142 + #mbox-cells = <2>; 143 + power-domains = <&pd IMX_SC_R_VPU_MU_2>; 144 + }; 145 + 146 + vpu_core0: vpu_core@2d080000 { 147 + compatible = "nxp,imx8q-vpu-decoder"; 148 + reg = <0x2d080000 0x10000>; 149 + power-domains = <&pd IMX_SC_R_VPU_DEC_0>; 150 + mbox-names = "tx0", "tx1", "rx"; 151 + mboxes = <&mu_m0 0 0>, 152 + <&mu_m0 0 1>, 153 + <&mu_m0 1 0>; 154 + memory-region = <&decoder_boot>, <&decoder_rpc>; 155 + }; 156 + 157 + vpu_core1: vpu_core@2d090000 { 158 + compatible = "nxp,imx8q-vpu-encoder"; 159 + reg = <0x2d090000 0x10000>; 160 + power-domains = <&pd IMX_SC_R_VPU_ENC_0>; 161 + mbox-names = "tx0", "tx1", "rx"; 162 + mboxes = <&mu1_m0 0 0>, 163 + <&mu1_m0 0 1>, 164 + <&mu1_m0 1 0>; 165 + memory-region = <&encoder1_boot>, <&encoder1_rpc>; 166 + }; 167 + 168 + vpu_core2: vpu_core@2d0a0000 { 169 + reg = <0x2d0a0000 0x10000>; 170 + compatible = "nxp,imx8q-vpu-encoder"; 171 + power-domains = <&pd IMX_SC_R_VPU_ENC_1>; 172 + mbox-names = "tx0", "tx1", "rx"; 173 + mboxes = <&mu2_m0 0 0>, 174 + <&mu2_m0 0 1>, 175 + <&mu2_m0 1 0>; 176 + memory-region = <&encoder2_boot>, <&encoder2_rpc>; 177 + }; 178 + }; 179 + 180 + ...
+25 -3
Documentation/userspace-api/media/v4l/pixfmt-yuv-planar.rst
··· 257 257 .. _V4L2-PIX-FMT-NV12-4L4: 258 258 .. _V4L2-PIX-FMT-NV12-16L16: 259 259 .. _V4L2-PIX-FMT-NV12-32L32: 260 + .. _V4L2_PIX_FMT_NV12M_8L128: 261 + .. _V4L2_PIX_FMT_NV12M_10BE_8L128: 260 262 261 263 Tiled NV12 262 264 ---------- ··· 283 281 tiles is stored in linear order. The layouts of the luma and chroma 284 282 planes are identical. 285 283 286 - ``V4L2_PIX_FMT_NV12_4L4`` stores pixel in 4x4 tiles, and stores 284 + ``V4L2_PIX_FMT_NV12_4L4`` stores pixels in 4x4 tiles, and stores 287 285 tiles linearly in memory. The line stride and image height must be 288 286 aligned to a multiple of 4. The layouts of the luma and chroma planes are 289 287 identical. 290 288 291 - ``V4L2_PIX_FMT_NV12_16L16`` stores pixel in 16x16 tiles, and stores 289 + ``V4L2_PIX_FMT_NV12_16L16`` stores pixels in 16x16 tiles, and stores 292 290 tiles linearly in memory. The line stride and image height must be 293 291 aligned to a multiple of 16. The layouts of the luma and chroma planes are 294 292 identical. 295 293 296 - ``V4L2_PIX_FMT_NV12_32L32`` stores pixel in 32x32 tiles, and stores 294 + ``V4L2_PIX_FMT_NV12_32L32`` stores pixels in 32x32 tiles, and stores 297 295 tiles linearly in memory. The line stride and image height must be 298 296 aligned to a multiple of 32. The layouts of the luma and chroma planes are 299 297 identical. 298 + 299 + ``V4L2_PIX_FMT_NV12M_8L128`` is similar to ``V4L2_PIX_FMT_NV12M`` but stores 300 + pixels in 2D 8x128 tiles, and stores tiles linearly in memory. 301 + The image height must be aligned to a multiple of 128. 302 + The layouts of the luma and chroma planes are identical. 303 + 304 + ``V4L2_PIX_FMT_NV12M_10BE_8L128`` is similar to ``V4L2_PIX_FMT_NV12M`` but stores 305 + 10 bits pixels in 2D 8x128 tiles, and stores tiles linearly in memory. 306 + the data is arranged in big endian order. 307 + The image height must be aligned to a multiple of 128. 308 + The layouts of the luma and chroma planes are identical. 309 + Note the tile size is 8bytes multiplied by 128 bytes, 310 + it means that the low bits and high bits of one pixel may be in different tiles. 311 + The 10 bit pixels are packed, so 5 bytes contain 4 10-bit pixels layout like 312 + this (for luma): 313 + byte 0: Y0(bits 9-2) 314 + byte 1: Y0(bits 1-0) Y1(bits 9-4) 315 + byte 2: Y1(bits 3-0) Y2(bits 9-6) 316 + byte 3: Y2(bits 5-0) Y3(bits 9-8) 317 + byte 4: Y3(bits 7-0) 300 318 301 319 ``V4L2_PIX_FMT_MM21`` store luma pixel in 16x32 tiles, and chroma pixels 302 320 in 16x16 tiles. The line stride must be aligned to a multiple of 16 and the
+9
MAINTAINERS
··· 1030 1030 F: Documentation/hid/amd-sfh* 1031 1031 F: drivers/hid/amd-sfh-hid/ 1032 1032 1033 + AMPHION VPU CODEC V4L2 DRIVER 1034 + M: Ming Qian <ming.qian@nxp.com> 1035 + M: Shijie Qin <shijie.qin@nxp.com> 1036 + M: Zhou Peng <eagle.zhou@nxp.com> 1037 + L: linux-media@vger.kernel.org 1038 + S: Maintained 1039 + F: Documentation/devicetree/bindings/media/amphion,vpu.yaml 1040 + F: drivers/media/platform/amphion/ 1041 + 1033 1042 AMS AS73211 DRIVER 1034 1043 M: Christian Eggers <ceggers@arri.de> 1035 1044 L: linux-iio@vger.kernel.org
+19
drivers/media/platform/Kconfig
··· 648 648 Support for the NVIDIA Tegra video decoder unit. 649 649 To compile this driver as a module choose m here. 650 650 651 + config VIDEO_AMPHION_VPU 652 + tristate "Amphion VPU (Video Processing Unit) Codec IP" 653 + depends on ARCH_MXC || COMPILE_TEST 654 + depends on MEDIA_SUPPORT 655 + depends on VIDEO_DEV 656 + depends on VIDEO_V4L2 657 + select MEDIA_CONTROLLER 658 + select V4L2_MEM2MEM_DEV 659 + select VIDEOBUF2_DMA_CONTIG 660 + select VIDEOBUF2_VMALLOC 661 + help 662 + Amphion VPU Codec IP contains two parts: Windsor and Malone. 663 + Windsor is encoder that supports H.264, and Malone is decoder 664 + that supports H.264, HEVC, and other video formats. 665 + This is a V4L2 driver for NXP MXC 8Q video accelerator hardware. 666 + It accelerates encoding and decoding operations on 667 + various NXP SoCs. 668 + To compile this driver as a module choose m here. 669 + 651 670 endif # V4L_MEM2MEM_DRIVERS 652 671 653 672 # TI VIDEO PORT Helper Modules
+2
drivers/media/platform/Makefile
··· 92 92 obj-$(CONFIG_VIDEO_MESON_GE2D) += meson/ge2d/ 93 93 94 94 obj-$(CONFIG_VIDEO_TEGRA_VDE) += tegra/vde/ 95 + 96 + obj-$(CONFIG_VIDEO_AMPHION_VPU) += amphion/
+20
drivers/media/platform/amphion/Makefile
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + # Makefile for NXP VPU driver 3 + 4 + amphion-vpu-objs += vpu_drv.o \ 5 + vpu_core.o \ 6 + vpu_mbox.o \ 7 + vpu_v4l2.o \ 8 + vpu_helpers.o \ 9 + vpu_cmds.o \ 10 + vpu_msgs.o \ 11 + vpu_rpc.o \ 12 + vpu_imx8q.o \ 13 + vpu_windsor.o \ 14 + vpu_malone.o \ 15 + vpu_color.o \ 16 + vdec.o \ 17 + venc.o \ 18 + vpu_dbg.o 19 + 20 + obj-$(CONFIG_VIDEO_AMPHION_VPU) += amphion-vpu.o
+1691
drivers/media/platform/amphion/vdec.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright 2020-2021 NXP 4 + */ 5 + 6 + #include <linux/init.h> 7 + #include <linux/interconnect.h> 8 + #include <linux/ioctl.h> 9 + #include <linux/list.h> 10 + #include <linux/kernel.h> 11 + #include <linux/module.h> 12 + #include <linux/vmalloc.h> 13 + #include <linux/videodev2.h> 14 + #include <media/v4l2-device.h> 15 + #include <media/v4l2-event.h> 16 + #include <media/v4l2-mem2mem.h> 17 + #include <media/v4l2-ioctl.h> 18 + #include <media/videobuf2-v4l2.h> 19 + #include <media/videobuf2-dma-contig.h> 20 + #include <media/videobuf2-vmalloc.h> 21 + #include "vpu.h" 22 + #include "vpu_defs.h" 23 + #include "vpu_core.h" 24 + #include "vpu_helpers.h" 25 + #include "vpu_v4l2.h" 26 + #include "vpu_cmds.h" 27 + #include "vpu_rpc.h" 28 + 29 + #define VDEC_FRAME_DEPTH 256 30 + #define VDEC_MIN_BUFFER_CAP 8 31 + 32 + struct vdec_fs_info { 33 + char name[8]; 34 + u32 type; 35 + u32 max_count; 36 + u32 req_count; 37 + u32 count; 38 + u32 index; 39 + u32 size; 40 + struct vpu_buffer buffer[32]; 41 + u32 tag; 42 + }; 43 + 44 + struct vdec_t { 45 + u32 seq_hdr_found; 46 + struct vpu_buffer udata; 47 + struct vpu_decode_params params; 48 + struct vpu_dec_codec_info codec_info; 49 + enum vpu_codec_state state; 50 + 51 + struct vpu_vb2_buffer *slots[VB2_MAX_FRAME]; 52 + u32 req_frame_count; 53 + struct vdec_fs_info mbi; 54 + struct vdec_fs_info dcp; 55 + u32 seq_tag; 56 + 57 + bool reset_codec; 58 + bool fixed_fmt; 59 + u32 decoded_frame_count; 60 + u32 display_frame_count; 61 + u32 sequence; 62 + u32 eos_received; 63 + bool is_source_changed; 64 + u32 source_change; 65 + u32 drain; 66 + u32 ts_pre_count; 67 + u32 frame_depth; 68 + s64 ts_start; 69 + s64 ts_input; 70 + s64 timestamp; 71 + }; 72 + 73 + static const struct vpu_format vdec_formats[] = { 74 + { 75 + .pixfmt = V4L2_PIX_FMT_NV12M_8L128, 76 + .num_planes = 2, 77 + .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, 78 + }, 79 + { 80 + .pixfmt = V4L2_PIX_FMT_NV12M_10BE_8L128, 81 + .num_planes = 2, 82 + .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, 83 + }, 84 + { 85 + .pixfmt = V4L2_PIX_FMT_H264, 86 + .num_planes = 1, 87 + .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, 88 + .flags = V4L2_FMT_FLAG_DYN_RESOLUTION 89 + }, 90 + { 91 + .pixfmt = V4L2_PIX_FMT_H264_MVC, 92 + .num_planes = 1, 93 + .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, 94 + .flags = V4L2_FMT_FLAG_DYN_RESOLUTION 95 + }, 96 + { 97 + .pixfmt = V4L2_PIX_FMT_HEVC, 98 + .num_planes = 1, 99 + .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, 100 + .flags = V4L2_FMT_FLAG_DYN_RESOLUTION 101 + }, 102 + { 103 + .pixfmt = V4L2_PIX_FMT_VC1_ANNEX_G, 104 + .num_planes = 1, 105 + .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, 106 + .flags = V4L2_FMT_FLAG_DYN_RESOLUTION 107 + }, 108 + { 109 + .pixfmt = V4L2_PIX_FMT_VC1_ANNEX_L, 110 + .num_planes = 1, 111 + .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, 112 + .flags = V4L2_FMT_FLAG_DYN_RESOLUTION 113 + }, 114 + { 115 + .pixfmt = V4L2_PIX_FMT_MPEG2, 116 + .num_planes = 1, 117 + .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, 118 + .flags = V4L2_FMT_FLAG_DYN_RESOLUTION 119 + }, 120 + { 121 + .pixfmt = V4L2_PIX_FMT_MPEG4, 122 + .num_planes = 1, 123 + .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, 124 + .flags = V4L2_FMT_FLAG_DYN_RESOLUTION 125 + }, 126 + { 127 + .pixfmt = V4L2_PIX_FMT_XVID, 128 + .num_planes = 1, 129 + .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, 130 + .flags = V4L2_FMT_FLAG_DYN_RESOLUTION 131 + }, 132 + { 133 + .pixfmt = V4L2_PIX_FMT_VP8, 134 + .num_planes = 1, 135 + .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, 136 + .flags = V4L2_FMT_FLAG_DYN_RESOLUTION 137 + }, 138 + { 139 + .pixfmt = V4L2_PIX_FMT_H263, 140 + .num_planes = 1, 141 + .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, 142 + .flags = V4L2_FMT_FLAG_DYN_RESOLUTION 143 + }, 144 + {0, 0, 0, 0}, 145 + }; 146 + 147 + static const struct v4l2_ctrl_ops vdec_ctrl_ops = { 148 + .g_volatile_ctrl = vpu_helper_g_volatile_ctrl, 149 + }; 150 + 151 + static int vdec_ctrl_init(struct vpu_inst *inst) 152 + { 153 + struct v4l2_ctrl *ctrl; 154 + int ret; 155 + 156 + ret = v4l2_ctrl_handler_init(&inst->ctrl_handler, 20); 157 + if (ret) 158 + return ret; 159 + 160 + ctrl = v4l2_ctrl_new_std(&inst->ctrl_handler, &vdec_ctrl_ops, 161 + V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, 1, 32, 1, 2); 162 + if (ctrl) 163 + ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE; 164 + 165 + ctrl = v4l2_ctrl_new_std(&inst->ctrl_handler, &vdec_ctrl_ops, 166 + V4L2_CID_MIN_BUFFERS_FOR_OUTPUT, 1, 32, 1, 2); 167 + if (ctrl) 168 + ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE; 169 + 170 + ret = v4l2_ctrl_handler_setup(&inst->ctrl_handler); 171 + if (ret) { 172 + dev_err(inst->dev, "[%d] setup ctrls fail, ret = %d\n", inst->id, ret); 173 + v4l2_ctrl_handler_free(&inst->ctrl_handler); 174 + return ret; 175 + } 176 + 177 + return 0; 178 + } 179 + 180 + static void vdec_set_last_buffer_dequeued(struct vpu_inst *inst) 181 + { 182 + struct vdec_t *vdec = inst->priv; 183 + 184 + if (vdec->eos_received) { 185 + if (!vpu_set_last_buffer_dequeued(inst)) 186 + vdec->eos_received--; 187 + } 188 + } 189 + 190 + static void vdec_handle_resolution_change(struct vpu_inst *inst) 191 + { 192 + struct vdec_t *vdec = inst->priv; 193 + struct vb2_queue *q; 194 + 195 + if (!inst->fh.m2m_ctx) 196 + return; 197 + 198 + if (inst->state != VPU_CODEC_STATE_DYAMIC_RESOLUTION_CHANGE) 199 + return; 200 + if (!vdec->source_change) 201 + return; 202 + 203 + q = v4l2_m2m_get_dst_vq(inst->fh.m2m_ctx); 204 + if (!list_empty(&q->done_list)) 205 + return; 206 + 207 + vdec->source_change--; 208 + vpu_notify_source_change(inst); 209 + } 210 + 211 + static int vdec_update_state(struct vpu_inst *inst, enum vpu_codec_state state, u32 force) 212 + { 213 + struct vdec_t *vdec = inst->priv; 214 + enum vpu_codec_state pre_state = inst->state; 215 + 216 + if (state == VPU_CODEC_STATE_SEEK) { 217 + if (inst->state == VPU_CODEC_STATE_DYAMIC_RESOLUTION_CHANGE) 218 + vdec->state = inst->state; 219 + else 220 + vdec->state = VPU_CODEC_STATE_ACTIVE; 221 + } 222 + if (inst->state != VPU_CODEC_STATE_SEEK || force) 223 + inst->state = state; 224 + else if (state == VPU_CODEC_STATE_DYAMIC_RESOLUTION_CHANGE) 225 + vdec->state = VPU_CODEC_STATE_DYAMIC_RESOLUTION_CHANGE; 226 + 227 + if (inst->state != pre_state) 228 + vpu_trace(inst->dev, "[%d] %d -> %d\n", inst->id, pre_state, inst->state); 229 + 230 + if (inst->state == VPU_CODEC_STATE_DYAMIC_RESOLUTION_CHANGE) 231 + vdec_handle_resolution_change(inst); 232 + 233 + return 0; 234 + } 235 + 236 + static int vdec_querycap(struct file *file, void *fh, struct v4l2_capability *cap) 237 + { 238 + strscpy(cap->driver, "amphion-vpu", sizeof(cap->driver)); 239 + strscpy(cap->card, "amphion vpu decoder", sizeof(cap->card)); 240 + strscpy(cap->bus_info, "platform: amphion-vpu", sizeof(cap->bus_info)); 241 + 242 + return 0; 243 + } 244 + 245 + static int vdec_enum_fmt(struct file *file, void *fh, struct v4l2_fmtdesc *f) 246 + { 247 + struct vpu_inst *inst = to_inst(file); 248 + struct vdec_t *vdec = inst->priv; 249 + const struct vpu_format *fmt; 250 + int ret = -EINVAL; 251 + 252 + vpu_inst_lock(inst); 253 + if (!V4L2_TYPE_IS_OUTPUT(f->type) && vdec->fixed_fmt) { 254 + if (f->index == 0) { 255 + f->pixelformat = inst->cap_format.pixfmt; 256 + f->flags = inst->cap_format.flags; 257 + ret = 0; 258 + } 259 + } else { 260 + fmt = vpu_helper_enum_format(inst, f->type, f->index); 261 + memset(f->reserved, 0, sizeof(f->reserved)); 262 + if (!fmt) 263 + goto exit; 264 + 265 + f->pixelformat = fmt->pixfmt; 266 + f->flags = fmt->flags; 267 + ret = 0; 268 + } 269 + 270 + exit: 271 + vpu_inst_unlock(inst); 272 + return ret; 273 + } 274 + 275 + static int vdec_g_fmt(struct file *file, void *fh, struct v4l2_format *f) 276 + { 277 + struct vpu_inst *inst = to_inst(file); 278 + struct vdec_t *vdec = inst->priv; 279 + struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp; 280 + struct vpu_format *cur_fmt; 281 + int i; 282 + 283 + cur_fmt = vpu_get_format(inst, f->type); 284 + 285 + pixmp->pixelformat = cur_fmt->pixfmt; 286 + pixmp->num_planes = cur_fmt->num_planes; 287 + pixmp->width = cur_fmt->width; 288 + pixmp->height = cur_fmt->height; 289 + pixmp->field = cur_fmt->field; 290 + pixmp->flags = cur_fmt->flags; 291 + for (i = 0; i < pixmp->num_planes; i++) { 292 + pixmp->plane_fmt[i].bytesperline = cur_fmt->bytesperline[i]; 293 + pixmp->plane_fmt[i].sizeimage = cur_fmt->sizeimage[i]; 294 + } 295 + 296 + f->fmt.pix_mp.colorspace = vdec->codec_info.color_primaries; 297 + f->fmt.pix_mp.xfer_func = vdec->codec_info.transfer_chars; 298 + f->fmt.pix_mp.ycbcr_enc = vdec->codec_info.matrix_coeffs; 299 + f->fmt.pix_mp.quantization = vdec->codec_info.full_range; 300 + 301 + return 0; 302 + } 303 + 304 + static int vdec_try_fmt(struct file *file, void *fh, struct v4l2_format *f) 305 + { 306 + struct vpu_inst *inst = to_inst(file); 307 + struct vdec_t *vdec = inst->priv; 308 + 309 + vpu_try_fmt_common(inst, f); 310 + 311 + vpu_inst_lock(inst); 312 + if (vdec->fixed_fmt) { 313 + f->fmt.pix_mp.colorspace = vdec->codec_info.color_primaries; 314 + f->fmt.pix_mp.xfer_func = vdec->codec_info.transfer_chars; 315 + f->fmt.pix_mp.ycbcr_enc = vdec->codec_info.matrix_coeffs; 316 + f->fmt.pix_mp.quantization = vdec->codec_info.full_range; 317 + } else { 318 + f->fmt.pix_mp.colorspace = V4L2_COLORSPACE_DEFAULT; 319 + f->fmt.pix_mp.xfer_func = V4L2_XFER_FUNC_DEFAULT; 320 + f->fmt.pix_mp.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; 321 + f->fmt.pix_mp.quantization = V4L2_QUANTIZATION_DEFAULT; 322 + } 323 + vpu_inst_unlock(inst); 324 + 325 + return 0; 326 + } 327 + 328 + static int vdec_s_fmt_common(struct vpu_inst *inst, struct v4l2_format *f) 329 + { 330 + struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp; 331 + const struct vpu_format *fmt; 332 + struct vpu_format *cur_fmt; 333 + struct vb2_queue *q; 334 + struct vdec_t *vdec = inst->priv; 335 + int i; 336 + 337 + if (!inst->fh.m2m_ctx) 338 + return -EINVAL; 339 + 340 + q = v4l2_m2m_get_vq(inst->fh.m2m_ctx, f->type); 341 + if (!q) 342 + return -EINVAL; 343 + if (vb2_is_busy(q)) 344 + return -EBUSY; 345 + 346 + fmt = vpu_try_fmt_common(inst, f); 347 + if (!fmt) 348 + return -EINVAL; 349 + 350 + cur_fmt = vpu_get_format(inst, f->type); 351 + if (V4L2_TYPE_IS_OUTPUT(f->type) && inst->state != VPU_CODEC_STATE_DEINIT) { 352 + if (cur_fmt->pixfmt != fmt->pixfmt) { 353 + vdec->reset_codec = true; 354 + vdec->fixed_fmt = false; 355 + } 356 + } 357 + cur_fmt->pixfmt = fmt->pixfmt; 358 + if (V4L2_TYPE_IS_OUTPUT(f->type) || !vdec->fixed_fmt) { 359 + cur_fmt->num_planes = fmt->num_planes; 360 + cur_fmt->flags = fmt->flags; 361 + cur_fmt->width = pixmp->width; 362 + cur_fmt->height = pixmp->height; 363 + for (i = 0; i < fmt->num_planes; i++) { 364 + cur_fmt->sizeimage[i] = pixmp->plane_fmt[i].sizeimage; 365 + cur_fmt->bytesperline[i] = pixmp->plane_fmt[i].bytesperline; 366 + } 367 + if (pixmp->field != V4L2_FIELD_ANY) 368 + cur_fmt->field = pixmp->field; 369 + } else { 370 + pixmp->num_planes = cur_fmt->num_planes; 371 + pixmp->width = cur_fmt->width; 372 + pixmp->height = cur_fmt->height; 373 + for (i = 0; i < pixmp->num_planes; i++) { 374 + pixmp->plane_fmt[i].bytesperline = cur_fmt->bytesperline[i]; 375 + pixmp->plane_fmt[i].sizeimage = cur_fmt->sizeimage[i]; 376 + } 377 + pixmp->field = cur_fmt->field; 378 + } 379 + 380 + if (!vdec->fixed_fmt) { 381 + if (V4L2_TYPE_IS_OUTPUT(f->type)) { 382 + vdec->params.codec_format = cur_fmt->pixfmt; 383 + vdec->codec_info.color_primaries = f->fmt.pix_mp.colorspace; 384 + vdec->codec_info.transfer_chars = f->fmt.pix_mp.xfer_func; 385 + vdec->codec_info.matrix_coeffs = f->fmt.pix_mp.ycbcr_enc; 386 + vdec->codec_info.full_range = f->fmt.pix_mp.quantization; 387 + } else { 388 + vdec->params.output_format = cur_fmt->pixfmt; 389 + inst->crop.left = 0; 390 + inst->crop.top = 0; 391 + inst->crop.width = cur_fmt->width; 392 + inst->crop.height = cur_fmt->height; 393 + } 394 + } 395 + 396 + vpu_trace(inst->dev, "[%d] %c%c%c%c %dx%d\n", inst->id, 397 + f->fmt.pix_mp.pixelformat, 398 + f->fmt.pix_mp.pixelformat >> 8, 399 + f->fmt.pix_mp.pixelformat >> 16, 400 + f->fmt.pix_mp.pixelformat >> 24, 401 + f->fmt.pix_mp.width, 402 + f->fmt.pix_mp.height); 403 + 404 + return 0; 405 + } 406 + 407 + static int vdec_s_fmt(struct file *file, void *fh, struct v4l2_format *f) 408 + { 409 + struct vpu_inst *inst = to_inst(file); 410 + struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp; 411 + struct vdec_t *vdec = inst->priv; 412 + int ret = 0; 413 + 414 + vpu_inst_lock(inst); 415 + ret = vdec_s_fmt_common(inst, f); 416 + if (ret) 417 + goto exit; 418 + 419 + if (V4L2_TYPE_IS_OUTPUT(f->type) && !vdec->fixed_fmt) { 420 + struct v4l2_format fc; 421 + 422 + memset(&fc, 0, sizeof(fc)); 423 + fc.type = inst->cap_format.type; 424 + fc.fmt.pix_mp.pixelformat = inst->cap_format.pixfmt; 425 + fc.fmt.pix_mp.width = pixmp->width; 426 + fc.fmt.pix_mp.height = pixmp->height; 427 + vdec_s_fmt_common(inst, &fc); 428 + } 429 + 430 + f->fmt.pix_mp.colorspace = vdec->codec_info.color_primaries; 431 + f->fmt.pix_mp.xfer_func = vdec->codec_info.transfer_chars; 432 + f->fmt.pix_mp.ycbcr_enc = vdec->codec_info.matrix_coeffs; 433 + f->fmt.pix_mp.quantization = vdec->codec_info.full_range; 434 + 435 + exit: 436 + vpu_inst_unlock(inst); 437 + return ret; 438 + } 439 + 440 + static int vdec_g_selection(struct file *file, void *fh, struct v4l2_selection *s) 441 + { 442 + struct vpu_inst *inst = to_inst(file); 443 + 444 + if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) 445 + return -EINVAL; 446 + 447 + switch (s->target) { 448 + case V4L2_SEL_TGT_COMPOSE: 449 + case V4L2_SEL_TGT_COMPOSE_DEFAULT: 450 + case V4L2_SEL_TGT_COMPOSE_PADDED: 451 + s->r = inst->crop; 452 + break; 453 + case V4L2_SEL_TGT_COMPOSE_BOUNDS: 454 + s->r.left = 0; 455 + s->r.top = 0; 456 + s->r.width = inst->cap_format.width; 457 + s->r.height = inst->cap_format.height; 458 + break; 459 + default: 460 + return -EINVAL; 461 + } 462 + 463 + return 0; 464 + } 465 + 466 + static int vdec_drain(struct vpu_inst *inst) 467 + { 468 + struct vdec_t *vdec = inst->priv; 469 + 470 + if (!inst->fh.m2m_ctx) 471 + return 0; 472 + 473 + if (!vdec->drain) 474 + return 0; 475 + 476 + if (v4l2_m2m_num_src_bufs_ready(inst->fh.m2m_ctx)) 477 + return 0; 478 + 479 + if (!vdec->params.frame_count) { 480 + vpu_set_last_buffer_dequeued(inst); 481 + return 0; 482 + } 483 + 484 + vpu_iface_add_scode(inst, SCODE_PADDING_EOS); 485 + vdec->params.end_flag = 1; 486 + vpu_iface_set_decode_params(inst, &vdec->params, 1); 487 + vdec->drain = 0; 488 + vpu_trace(inst->dev, "[%d] frame_count = %d\n", inst->id, vdec->params.frame_count); 489 + 490 + return 0; 491 + } 492 + 493 + static int vdec_cmd_start(struct vpu_inst *inst) 494 + { 495 + switch (inst->state) { 496 + case VPU_CODEC_STATE_STARTED: 497 + case VPU_CODEC_STATE_DRAIN: 498 + case VPU_CODEC_STATE_DYAMIC_RESOLUTION_CHANGE: 499 + vdec_update_state(inst, VPU_CODEC_STATE_ACTIVE, 0); 500 + break; 501 + default: 502 + break; 503 + } 504 + vpu_process_capture_buffer(inst); 505 + return 0; 506 + } 507 + 508 + static int vdec_cmd_stop(struct vpu_inst *inst) 509 + { 510 + struct vdec_t *vdec = inst->priv; 511 + 512 + vpu_trace(inst->dev, "[%d]\n", inst->id); 513 + 514 + if (inst->state == VPU_CODEC_STATE_DEINIT) { 515 + vpu_set_last_buffer_dequeued(inst); 516 + } else { 517 + vdec->drain = 1; 518 + vdec_drain(inst); 519 + } 520 + 521 + return 0; 522 + } 523 + 524 + static int vdec_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *cmd) 525 + { 526 + struct vpu_inst *inst = to_inst(file); 527 + int ret; 528 + 529 + ret = v4l2_m2m_ioctl_try_decoder_cmd(file, fh, cmd); 530 + if (ret) 531 + return ret; 532 + 533 + vpu_inst_lock(inst); 534 + switch (cmd->cmd) { 535 + case V4L2_DEC_CMD_START: 536 + vdec_cmd_start(inst); 537 + break; 538 + case V4L2_DEC_CMD_STOP: 539 + vdec_cmd_stop(inst); 540 + break; 541 + default: 542 + break; 543 + } 544 + vpu_inst_unlock(inst); 545 + 546 + return 0; 547 + } 548 + 549 + static int vdec_subscribe_event(struct v4l2_fh *fh, const struct v4l2_event_subscription *sub) 550 + { 551 + switch (sub->type) { 552 + case V4L2_EVENT_EOS: 553 + return v4l2_event_subscribe(fh, sub, 0, NULL); 554 + case V4L2_EVENT_SOURCE_CHANGE: 555 + return v4l2_src_change_event_subscribe(fh, sub); 556 + case V4L2_EVENT_CTRL: 557 + return v4l2_ctrl_subscribe_event(fh, sub); 558 + default: 559 + return -EINVAL; 560 + } 561 + 562 + return 0; 563 + } 564 + 565 + static const struct v4l2_ioctl_ops vdec_ioctl_ops = { 566 + .vidioc_querycap = vdec_querycap, 567 + .vidioc_enum_fmt_vid_cap = vdec_enum_fmt, 568 + .vidioc_enum_fmt_vid_out = vdec_enum_fmt, 569 + .vidioc_g_fmt_vid_cap_mplane = vdec_g_fmt, 570 + .vidioc_g_fmt_vid_out_mplane = vdec_g_fmt, 571 + .vidioc_try_fmt_vid_cap_mplane = vdec_try_fmt, 572 + .vidioc_try_fmt_vid_out_mplane = vdec_try_fmt, 573 + .vidioc_s_fmt_vid_cap_mplane = vdec_s_fmt, 574 + .vidioc_s_fmt_vid_out_mplane = vdec_s_fmt, 575 + .vidioc_g_selection = vdec_g_selection, 576 + .vidioc_try_decoder_cmd = v4l2_m2m_ioctl_try_decoder_cmd, 577 + .vidioc_decoder_cmd = vdec_decoder_cmd, 578 + .vidioc_subscribe_event = vdec_subscribe_event, 579 + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, 580 + .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs, 581 + .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs, 582 + .vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf, 583 + .vidioc_querybuf = v4l2_m2m_ioctl_querybuf, 584 + .vidioc_qbuf = v4l2_m2m_ioctl_qbuf, 585 + .vidioc_expbuf = v4l2_m2m_ioctl_expbuf, 586 + .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf, 587 + .vidioc_streamon = v4l2_m2m_ioctl_streamon, 588 + .vidioc_streamoff = v4l2_m2m_ioctl_streamoff, 589 + }; 590 + 591 + static bool vdec_check_ready(struct vpu_inst *inst, unsigned int type) 592 + { 593 + struct vdec_t *vdec = inst->priv; 594 + 595 + if (V4L2_TYPE_IS_OUTPUT(type)) { 596 + if (vdec->ts_pre_count >= vdec->frame_depth) 597 + return false; 598 + return true; 599 + } 600 + 601 + if (vdec->req_frame_count) 602 + return true; 603 + 604 + return false; 605 + } 606 + 607 + static int vdec_frame_decoded(struct vpu_inst *inst, void *arg) 608 + { 609 + struct vdec_t *vdec = inst->priv; 610 + struct vpu_dec_pic_info *info = arg; 611 + struct vpu_vb2_buffer *vpu_buf; 612 + struct vb2_v4l2_buffer *vbuf; 613 + int ret = 0; 614 + 615 + if (!info || info->id >= ARRAY_SIZE(vdec->slots)) 616 + return -EINVAL; 617 + 618 + vpu_inst_lock(inst); 619 + vpu_buf = vdec->slots[info->id]; 620 + if (!vpu_buf) { 621 + dev_err(inst->dev, "[%d] decoded invalid frame[%d]\n", inst->id, info->id); 622 + ret = -EINVAL; 623 + goto exit; 624 + } 625 + vbuf = &vpu_buf->m2m_buf.vb; 626 + if (vpu_get_buffer_state(vbuf) == VPU_BUF_STATE_DECODED) 627 + dev_info(inst->dev, "[%d] buf[%d] has been decoded\n", inst->id, info->id); 628 + vpu_set_buffer_state(vbuf, VPU_BUF_STATE_DECODED); 629 + vdec->decoded_frame_count++; 630 + if (vdec->ts_pre_count >= info->consumed_count) 631 + vdec->ts_pre_count -= info->consumed_count; 632 + else 633 + vdec->ts_pre_count = 0; 634 + exit: 635 + vpu_inst_unlock(inst); 636 + 637 + return ret; 638 + } 639 + 640 + static struct vpu_vb2_buffer *vdec_find_buffer(struct vpu_inst *inst, u32 luma) 641 + { 642 + struct vdec_t *vdec = inst->priv; 643 + int i; 644 + 645 + for (i = 0; i < ARRAY_SIZE(vdec->slots); i++) { 646 + if (!vdec->slots[i]) 647 + continue; 648 + if (luma == vdec->slots[i]->luma) 649 + return vdec->slots[i]; 650 + } 651 + 652 + return NULL; 653 + } 654 + 655 + static void vdec_buf_done(struct vpu_inst *inst, struct vpu_frame_info *frame) 656 + { 657 + struct vdec_t *vdec = inst->priv; 658 + struct vpu_vb2_buffer *vpu_buf; 659 + struct vb2_v4l2_buffer *vbuf; 660 + u32 sequence; 661 + 662 + if (!frame) 663 + return; 664 + 665 + vpu_inst_lock(inst); 666 + sequence = vdec->sequence++; 667 + vpu_buf = vdec_find_buffer(inst, frame->luma); 668 + vpu_inst_unlock(inst); 669 + if (!vpu_buf) { 670 + dev_err(inst->dev, "[%d] can't find buffer, id = %d, addr = 0x%x\n", 671 + inst->id, frame->id, frame->luma); 672 + return; 673 + } 674 + if (frame->skipped) { 675 + dev_dbg(inst->dev, "[%d] frame skip\n", inst->id); 676 + return; 677 + } 678 + 679 + vbuf = &vpu_buf->m2m_buf.vb; 680 + if (vbuf->vb2_buf.index != frame->id) 681 + dev_err(inst->dev, "[%d] buffer id(%d, %d) dismatch\n", 682 + inst->id, vbuf->vb2_buf.index, frame->id); 683 + 684 + if (vpu_get_buffer_state(vbuf) != VPU_BUF_STATE_DECODED) 685 + dev_err(inst->dev, "[%d] buffer(%d) ready without decoded\n", inst->id, frame->id); 686 + vpu_set_buffer_state(vbuf, VPU_BUF_STATE_READY); 687 + vb2_set_plane_payload(&vbuf->vb2_buf, 0, inst->cap_format.sizeimage[0]); 688 + vb2_set_plane_payload(&vbuf->vb2_buf, 1, inst->cap_format.sizeimage[1]); 689 + vbuf->vb2_buf.timestamp = frame->timestamp; 690 + vbuf->field = inst->cap_format.field; 691 + vbuf->sequence = sequence; 692 + dev_dbg(inst->dev, "[%d][OUTPUT TS]%32lld\n", inst->id, frame->timestamp); 693 + 694 + v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_DONE); 695 + vpu_inst_lock(inst); 696 + vdec->timestamp = frame->timestamp; 697 + vdec->display_frame_count++; 698 + vpu_inst_unlock(inst); 699 + dev_dbg(inst->dev, "[%d] decoded : %d, display : %d, sequence : %d\n", 700 + inst->id, vdec->decoded_frame_count, vdec->display_frame_count, vdec->sequence); 701 + } 702 + 703 + static void vdec_stop_done(struct vpu_inst *inst) 704 + { 705 + struct vdec_t *vdec = inst->priv; 706 + 707 + vpu_inst_lock(inst); 708 + vdec_update_state(inst, VPU_CODEC_STATE_DEINIT, 0); 709 + vdec->seq_hdr_found = 0; 710 + vdec->req_frame_count = 0; 711 + vdec->reset_codec = false; 712 + vdec->fixed_fmt = false; 713 + vdec->params.end_flag = 0; 714 + vdec->drain = 0; 715 + vdec->ts_pre_count = 0; 716 + vdec->timestamp = VPU_INVALID_TIMESTAMP; 717 + vdec->ts_start = VPU_INVALID_TIMESTAMP; 718 + vdec->ts_input = VPU_INVALID_TIMESTAMP; 719 + vdec->params.frame_count = 0; 720 + vdec->decoded_frame_count = 0; 721 + vdec->display_frame_count = 0; 722 + vdec->sequence = 0; 723 + vdec->eos_received = 0; 724 + vdec->is_source_changed = false; 725 + vdec->source_change = 0; 726 + vpu_inst_unlock(inst); 727 + } 728 + 729 + static bool vdec_check_source_change(struct vpu_inst *inst) 730 + { 731 + struct vdec_t *vdec = inst->priv; 732 + const struct vpu_format *fmt; 733 + int i; 734 + 735 + if (!inst->fh.m2m_ctx) 736 + return false; 737 + 738 + if (!vb2_is_streaming(v4l2_m2m_get_dst_vq(inst->fh.m2m_ctx))) 739 + return true; 740 + fmt = vpu_helper_find_format(inst, inst->cap_format.type, vdec->codec_info.pixfmt); 741 + if (inst->cap_format.pixfmt != vdec->codec_info.pixfmt) 742 + return true; 743 + if (inst->cap_format.width != vdec->codec_info.decoded_width) 744 + return true; 745 + if (inst->cap_format.height != vdec->codec_info.decoded_height) 746 + return true; 747 + if (vpu_get_num_buffers(inst, inst->cap_format.type) < inst->min_buffer_cap) 748 + return true; 749 + if (inst->crop.left != vdec->codec_info.offset_x) 750 + return true; 751 + if (inst->crop.top != vdec->codec_info.offset_y) 752 + return true; 753 + if (inst->crop.width != vdec->codec_info.width) 754 + return true; 755 + if (inst->crop.height != vdec->codec_info.height) 756 + return true; 757 + if (fmt && inst->cap_format.num_planes != fmt->num_planes) 758 + return true; 759 + for (i = 0; i < inst->cap_format.num_planes; i++) { 760 + if (inst->cap_format.bytesperline[i] != vdec->codec_info.bytesperline[i]) 761 + return true; 762 + if (inst->cap_format.sizeimage[i] != vdec->codec_info.sizeimage[i]) 763 + return true; 764 + } 765 + 766 + return false; 767 + } 768 + 769 + static void vdec_init_fmt(struct vpu_inst *inst) 770 + { 771 + struct vdec_t *vdec = inst->priv; 772 + const struct vpu_format *fmt; 773 + int i; 774 + 775 + fmt = vpu_helper_find_format(inst, inst->cap_format.type, vdec->codec_info.pixfmt); 776 + inst->out_format.width = vdec->codec_info.width; 777 + inst->out_format.height = vdec->codec_info.height; 778 + inst->cap_format.width = vdec->codec_info.decoded_width; 779 + inst->cap_format.height = vdec->codec_info.decoded_height; 780 + inst->cap_format.pixfmt = vdec->codec_info.pixfmt; 781 + if (fmt) { 782 + inst->cap_format.num_planes = fmt->num_planes; 783 + inst->cap_format.flags = fmt->flags; 784 + } 785 + for (i = 0; i < inst->cap_format.num_planes; i++) { 786 + inst->cap_format.bytesperline[i] = vdec->codec_info.bytesperline[i]; 787 + inst->cap_format.sizeimage[i] = vdec->codec_info.sizeimage[i]; 788 + } 789 + if (vdec->codec_info.progressive) 790 + inst->cap_format.field = V4L2_FIELD_NONE; 791 + else 792 + inst->cap_format.field = V4L2_FIELD_SEQ_BT; 793 + if (vdec->codec_info.color_primaries == V4L2_COLORSPACE_DEFAULT) 794 + vdec->codec_info.color_primaries = V4L2_COLORSPACE_REC709; 795 + if (vdec->codec_info.transfer_chars == V4L2_XFER_FUNC_DEFAULT) 796 + vdec->codec_info.transfer_chars = V4L2_XFER_FUNC_709; 797 + if (vdec->codec_info.matrix_coeffs == V4L2_YCBCR_ENC_DEFAULT) 798 + vdec->codec_info.matrix_coeffs = V4L2_YCBCR_ENC_709; 799 + if (vdec->codec_info.full_range == V4L2_QUANTIZATION_DEFAULT) 800 + vdec->codec_info.full_range = V4L2_QUANTIZATION_LIM_RANGE; 801 + } 802 + 803 + static void vdec_init_crop(struct vpu_inst *inst) 804 + { 805 + struct vdec_t *vdec = inst->priv; 806 + 807 + inst->crop.left = vdec->codec_info.offset_x; 808 + inst->crop.top = vdec->codec_info.offset_y; 809 + inst->crop.width = vdec->codec_info.width; 810 + inst->crop.height = vdec->codec_info.height; 811 + } 812 + 813 + static void vdec_init_mbi(struct vpu_inst *inst) 814 + { 815 + struct vdec_t *vdec = inst->priv; 816 + 817 + vdec->mbi.size = vdec->codec_info.mbi_size; 818 + vdec->mbi.max_count = ARRAY_SIZE(vdec->mbi.buffer); 819 + scnprintf(vdec->mbi.name, sizeof(vdec->mbi.name), "mbi"); 820 + vdec->mbi.type = MEM_RES_MBI; 821 + vdec->mbi.tag = vdec->seq_tag; 822 + } 823 + 824 + static void vdec_init_dcp(struct vpu_inst *inst) 825 + { 826 + struct vdec_t *vdec = inst->priv; 827 + 828 + vdec->dcp.size = vdec->codec_info.dcp_size; 829 + vdec->dcp.max_count = ARRAY_SIZE(vdec->dcp.buffer); 830 + scnprintf(vdec->dcp.name, sizeof(vdec->dcp.name), "dcp"); 831 + vdec->dcp.type = MEM_RES_DCP; 832 + vdec->dcp.tag = vdec->seq_tag; 833 + } 834 + 835 + static void vdec_request_one_fs(struct vdec_fs_info *fs) 836 + { 837 + fs->req_count++; 838 + if (fs->req_count > fs->max_count) 839 + fs->req_count = fs->max_count; 840 + } 841 + 842 + static int vdec_alloc_fs_buffer(struct vpu_inst *inst, struct vdec_fs_info *fs) 843 + { 844 + struct vpu_buffer *buffer; 845 + 846 + if (!fs->size) 847 + return -EINVAL; 848 + 849 + if (fs->count >= fs->req_count) 850 + return -EINVAL; 851 + 852 + buffer = &fs->buffer[fs->count]; 853 + if (buffer->virt && buffer->length >= fs->size) 854 + return 0; 855 + 856 + vpu_free_dma(buffer); 857 + buffer->length = fs->size; 858 + return vpu_alloc_dma(inst->core, buffer); 859 + } 860 + 861 + static void vdec_alloc_fs(struct vpu_inst *inst, struct vdec_fs_info *fs) 862 + { 863 + int ret; 864 + 865 + while (fs->count < fs->req_count) { 866 + ret = vdec_alloc_fs_buffer(inst, fs); 867 + if (ret) 868 + break; 869 + fs->count++; 870 + } 871 + } 872 + 873 + static void vdec_clear_fs(struct vdec_fs_info *fs) 874 + { 875 + u32 i; 876 + 877 + if (!fs) 878 + return; 879 + 880 + for (i = 0; i < ARRAY_SIZE(fs->buffer); i++) 881 + vpu_free_dma(&fs->buffer[i]); 882 + memset(fs, 0, sizeof(*fs)); 883 + } 884 + 885 + static int vdec_response_fs(struct vpu_inst *inst, struct vdec_fs_info *fs) 886 + { 887 + struct vpu_fs_info info; 888 + int ret; 889 + 890 + if (fs->index >= fs->count) 891 + return 0; 892 + 893 + memset(&info, 0, sizeof(info)); 894 + info.id = fs->index; 895 + info.type = fs->type; 896 + info.tag = fs->tag; 897 + info.luma_addr = fs->buffer[fs->index].phys; 898 + info.luma_size = fs->buffer[fs->index].length; 899 + ret = vpu_session_alloc_fs(inst, &info); 900 + if (ret) 901 + return ret; 902 + 903 + fs->index++; 904 + return 0; 905 + } 906 + 907 + static int vdec_response_frame_abnormal(struct vpu_inst *inst) 908 + { 909 + struct vdec_t *vdec = inst->priv; 910 + struct vpu_fs_info info; 911 + 912 + if (!vdec->req_frame_count) 913 + return 0; 914 + 915 + memset(&info, 0, sizeof(info)); 916 + info.type = MEM_RES_FRAME; 917 + info.tag = vdec->seq_tag + 0xf0; 918 + vpu_session_alloc_fs(inst, &info); 919 + vdec->req_frame_count--; 920 + 921 + return 0; 922 + } 923 + 924 + static int vdec_response_frame(struct vpu_inst *inst, struct vb2_v4l2_buffer *vbuf) 925 + { 926 + struct vdec_t *vdec = inst->priv; 927 + struct vpu_vb2_buffer *vpu_buf; 928 + struct vpu_fs_info info; 929 + int ret; 930 + 931 + if (inst->state != VPU_CODEC_STATE_ACTIVE) 932 + return -EINVAL; 933 + 934 + if (!vdec->req_frame_count) 935 + return -EINVAL; 936 + 937 + if (!vbuf) 938 + return -EINVAL; 939 + 940 + if (vdec->slots[vbuf->vb2_buf.index]) { 941 + dev_err(inst->dev, "[%d] repeat alloc fs %d\n", 942 + inst->id, vbuf->vb2_buf.index); 943 + return -EINVAL; 944 + } 945 + 946 + dev_dbg(inst->dev, "[%d] state = %d, alloc fs %d, tag = 0x%x\n", 947 + inst->id, inst->state, vbuf->vb2_buf.index, vdec->seq_tag); 948 + vpu_buf = to_vpu_vb2_buffer(vbuf); 949 + 950 + memset(&info, 0, sizeof(info)); 951 + info.id = vbuf->vb2_buf.index; 952 + info.type = MEM_RES_FRAME; 953 + info.tag = vdec->seq_tag; 954 + info.luma_addr = vpu_get_vb_phy_addr(&vbuf->vb2_buf, 0); 955 + info.luma_size = inst->cap_format.sizeimage[0]; 956 + info.chroma_addr = vpu_get_vb_phy_addr(&vbuf->vb2_buf, 1); 957 + info.chromau_size = inst->cap_format.sizeimage[1]; 958 + info.bytesperline = inst->cap_format.bytesperline[0]; 959 + ret = vpu_session_alloc_fs(inst, &info); 960 + if (ret) 961 + return ret; 962 + 963 + vpu_buf->tag = info.tag; 964 + vpu_buf->luma = info.luma_addr; 965 + vpu_buf->chroma_u = info.chromau_size; 966 + vpu_buf->chroma_v = 0; 967 + vpu_set_buffer_state(vbuf, VPU_BUF_STATE_INUSE); 968 + vdec->slots[info.id] = vpu_buf; 969 + vdec->req_frame_count--; 970 + 971 + return 0; 972 + } 973 + 974 + static void vdec_response_fs_request(struct vpu_inst *inst, bool force) 975 + { 976 + struct vdec_t *vdec = inst->priv; 977 + int i; 978 + int ret; 979 + 980 + if (force) { 981 + for (i = vdec->req_frame_count; i > 0; i--) 982 + vdec_response_frame_abnormal(inst); 983 + return; 984 + } 985 + 986 + for (i = vdec->req_frame_count; i > 0; i--) { 987 + ret = vpu_process_capture_buffer(inst); 988 + if (ret) 989 + break; 990 + if (vdec->eos_received) 991 + break; 992 + } 993 + 994 + for (i = vdec->mbi.index; i < vdec->mbi.count; i++) { 995 + if (vdec_response_fs(inst, &vdec->mbi)) 996 + break; 997 + if (vdec->eos_received) 998 + break; 999 + } 1000 + for (i = vdec->dcp.index; i < vdec->dcp.count; i++) { 1001 + if (vdec_response_fs(inst, &vdec->dcp)) 1002 + break; 1003 + if (vdec->eos_received) 1004 + break; 1005 + } 1006 + } 1007 + 1008 + static void vdec_response_fs_release(struct vpu_inst *inst, u32 id, u32 tag) 1009 + { 1010 + struct vpu_fs_info info; 1011 + 1012 + memset(&info, 0, sizeof(info)); 1013 + info.id = id; 1014 + info.tag = tag; 1015 + vpu_session_release_fs(inst, &info); 1016 + } 1017 + 1018 + static void vdec_recycle_buffer(struct vpu_inst *inst, struct vb2_v4l2_buffer *vbuf) 1019 + { 1020 + if (!inst->fh.m2m_ctx) 1021 + return; 1022 + if (vbuf->vb2_buf.state != VB2_BUF_STATE_ACTIVE) 1023 + return; 1024 + if (vpu_find_buf_by_idx(inst, vbuf->vb2_buf.type, vbuf->vb2_buf.index)) 1025 + return; 1026 + v4l2_m2m_buf_queue(inst->fh.m2m_ctx, vbuf); 1027 + } 1028 + 1029 + static void vdec_clear_slots(struct vpu_inst *inst) 1030 + { 1031 + struct vdec_t *vdec = inst->priv; 1032 + struct vpu_vb2_buffer *vpu_buf; 1033 + struct vb2_v4l2_buffer *vbuf; 1034 + int i; 1035 + 1036 + for (i = 0; i < ARRAY_SIZE(vdec->slots); i++) { 1037 + if (!vdec->slots[i]) 1038 + continue; 1039 + 1040 + vpu_buf = vdec->slots[i]; 1041 + vbuf = &vpu_buf->m2m_buf.vb; 1042 + 1043 + vdec_recycle_buffer(inst, vbuf); 1044 + vdec->slots[i]->state = VPU_BUF_STATE_IDLE; 1045 + vdec->slots[i] = NULL; 1046 + } 1047 + } 1048 + 1049 + static void vdec_event_seq_hdr(struct vpu_inst *inst, struct vpu_dec_codec_info *hdr) 1050 + { 1051 + struct vdec_t *vdec = inst->priv; 1052 + 1053 + vpu_inst_lock(inst); 1054 + memcpy(&vdec->codec_info, hdr, sizeof(vdec->codec_info)); 1055 + 1056 + vpu_trace(inst->dev, "[%d] %d x %d, crop : (%d, %d) %d x %d, %d, %d\n", 1057 + inst->id, 1058 + vdec->codec_info.decoded_width, 1059 + vdec->codec_info.decoded_height, 1060 + vdec->codec_info.offset_x, 1061 + vdec->codec_info.offset_y, 1062 + vdec->codec_info.width, 1063 + vdec->codec_info.height, 1064 + hdr->num_ref_frms, 1065 + hdr->num_dpb_frms); 1066 + inst->min_buffer_cap = hdr->num_ref_frms + hdr->num_dpb_frms; 1067 + vdec->is_source_changed = vdec_check_source_change(inst); 1068 + vdec_init_fmt(inst); 1069 + vdec_init_crop(inst); 1070 + vdec_init_mbi(inst); 1071 + vdec_init_dcp(inst); 1072 + if (!vdec->seq_hdr_found) { 1073 + vdec->seq_tag = vdec->codec_info.tag; 1074 + if (vdec->is_source_changed) { 1075 + vdec_update_state(inst, VPU_CODEC_STATE_DYAMIC_RESOLUTION_CHANGE, 0); 1076 + vpu_notify_source_change(inst); 1077 + vdec->is_source_changed = false; 1078 + } 1079 + } 1080 + if (vdec->seq_tag != vdec->codec_info.tag) { 1081 + vdec_response_fs_request(inst, true); 1082 + vpu_trace(inst->dev, "[%d] seq tag change: %d -> %d\n", 1083 + inst->id, vdec->seq_tag, vdec->codec_info.tag); 1084 + } 1085 + vdec->seq_hdr_found++; 1086 + vdec->fixed_fmt = true; 1087 + vpu_inst_unlock(inst); 1088 + } 1089 + 1090 + static void vdec_event_resolution_change(struct vpu_inst *inst) 1091 + { 1092 + struct vdec_t *vdec = inst->priv; 1093 + 1094 + vpu_trace(inst->dev, "[%d]\n", inst->id); 1095 + vpu_inst_lock(inst); 1096 + vdec->seq_tag = vdec->codec_info.tag; 1097 + vdec_clear_fs(&vdec->mbi); 1098 + vdec_clear_fs(&vdec->dcp); 1099 + vdec_clear_slots(inst); 1100 + vdec_init_mbi(inst); 1101 + vdec_init_dcp(inst); 1102 + if (vdec->is_source_changed) { 1103 + vdec_update_state(inst, VPU_CODEC_STATE_DYAMIC_RESOLUTION_CHANGE, 0); 1104 + vdec->source_change++; 1105 + vdec_handle_resolution_change(inst); 1106 + vdec->is_source_changed = false; 1107 + } 1108 + vpu_inst_unlock(inst); 1109 + } 1110 + 1111 + static void vdec_event_req_fs(struct vpu_inst *inst, struct vpu_fs_info *fs) 1112 + { 1113 + struct vdec_t *vdec = inst->priv; 1114 + 1115 + if (!fs) 1116 + return; 1117 + 1118 + vpu_inst_lock(inst); 1119 + 1120 + switch (fs->type) { 1121 + case MEM_RES_FRAME: 1122 + vdec->req_frame_count++; 1123 + break; 1124 + case MEM_RES_MBI: 1125 + vdec_request_one_fs(&vdec->mbi); 1126 + break; 1127 + case MEM_RES_DCP: 1128 + vdec_request_one_fs(&vdec->dcp); 1129 + break; 1130 + default: 1131 + break; 1132 + } 1133 + 1134 + vdec_alloc_fs(inst, &vdec->mbi); 1135 + vdec_alloc_fs(inst, &vdec->dcp); 1136 + 1137 + vdec_response_fs_request(inst, false); 1138 + 1139 + vpu_inst_unlock(inst); 1140 + } 1141 + 1142 + static void vdec_evnet_rel_fs(struct vpu_inst *inst, struct vpu_fs_info *fs) 1143 + { 1144 + struct vdec_t *vdec = inst->priv; 1145 + struct vpu_vb2_buffer *vpu_buf; 1146 + struct vb2_v4l2_buffer *vbuf; 1147 + 1148 + if (!fs || fs->id >= ARRAY_SIZE(vdec->slots)) 1149 + return; 1150 + if (fs->type != MEM_RES_FRAME) 1151 + return; 1152 + 1153 + if (fs->id >= vpu_get_num_buffers(inst, inst->cap_format.type)) { 1154 + dev_err(inst->dev, "[%d] invalid fs(%d) to release\n", inst->id, fs->id); 1155 + return; 1156 + } 1157 + 1158 + vpu_inst_lock(inst); 1159 + vpu_buf = vdec->slots[fs->id]; 1160 + vdec->slots[fs->id] = NULL; 1161 + 1162 + if (!vpu_buf) { 1163 + dev_dbg(inst->dev, "[%d] fs[%d] has bee released\n", inst->id, fs->id); 1164 + goto exit; 1165 + } 1166 + 1167 + vbuf = &vpu_buf->m2m_buf.vb; 1168 + if (vpu_get_buffer_state(vbuf) == VPU_BUF_STATE_DECODED) { 1169 + dev_dbg(inst->dev, "[%d] frame skip\n", inst->id); 1170 + vdec->sequence++; 1171 + } 1172 + 1173 + vdec_response_fs_release(inst, fs->id, vpu_buf->tag); 1174 + if (vpu_get_buffer_state(vbuf) != VPU_BUF_STATE_READY) 1175 + vdec_recycle_buffer(inst, vbuf); 1176 + 1177 + vpu_set_buffer_state(vbuf, VPU_BUF_STATE_IDLE); 1178 + vpu_process_capture_buffer(inst); 1179 + 1180 + exit: 1181 + vpu_inst_unlock(inst); 1182 + } 1183 + 1184 + static void vdec_event_eos(struct vpu_inst *inst) 1185 + { 1186 + struct vdec_t *vdec = inst->priv; 1187 + 1188 + vpu_trace(inst->dev, "[%d] input : %d, decoded : %d, display : %d, sequence : %d\n", 1189 + inst->id, 1190 + vdec->params.frame_count, 1191 + vdec->decoded_frame_count, 1192 + vdec->display_frame_count, 1193 + vdec->sequence); 1194 + vpu_inst_lock(inst); 1195 + vdec->eos_received++; 1196 + vdec->fixed_fmt = false; 1197 + inst->min_buffer_cap = VDEC_MIN_BUFFER_CAP; 1198 + vdec_update_state(inst, VPU_CODEC_STATE_DRAIN, 0); 1199 + vdec_set_last_buffer_dequeued(inst); 1200 + vpu_inst_unlock(inst); 1201 + } 1202 + 1203 + static void vdec_event_notify(struct vpu_inst *inst, u32 event, void *data) 1204 + { 1205 + switch (event) { 1206 + case VPU_MSG_ID_SEQ_HDR_FOUND: 1207 + vdec_event_seq_hdr(inst, data); 1208 + break; 1209 + case VPU_MSG_ID_RES_CHANGE: 1210 + vdec_event_resolution_change(inst); 1211 + break; 1212 + case VPU_MSG_ID_FRAME_REQ: 1213 + vdec_event_req_fs(inst, data); 1214 + break; 1215 + case VPU_MSG_ID_FRAME_RELEASE: 1216 + vdec_evnet_rel_fs(inst, data); 1217 + break; 1218 + case VPU_MSG_ID_PIC_EOS: 1219 + vdec_event_eos(inst); 1220 + break; 1221 + default: 1222 + break; 1223 + } 1224 + } 1225 + 1226 + static int vdec_process_output(struct vpu_inst *inst, struct vb2_buffer *vb) 1227 + { 1228 + struct vdec_t *vdec = inst->priv; 1229 + struct vb2_v4l2_buffer *vbuf; 1230 + struct vpu_rpc_buffer_desc desc; 1231 + s64 timestamp; 1232 + u32 free_space; 1233 + int ret; 1234 + 1235 + vbuf = to_vb2_v4l2_buffer(vb); 1236 + dev_dbg(inst->dev, "[%d] dec output [%d] %d : %ld\n", 1237 + inst->id, vbuf->sequence, vb->index, vb2_get_plane_payload(vb, 0)); 1238 + 1239 + if (inst->state == VPU_CODEC_STATE_DEINIT) 1240 + return -EINVAL; 1241 + if (vdec->reset_codec) 1242 + return -EINVAL; 1243 + 1244 + if (inst->state == VPU_CODEC_STATE_STARTED) 1245 + vdec_update_state(inst, VPU_CODEC_STATE_ACTIVE, 0); 1246 + 1247 + ret = vpu_iface_get_stream_buffer_desc(inst, &desc); 1248 + if (ret) 1249 + return ret; 1250 + 1251 + free_space = vpu_helper_get_free_space(inst); 1252 + if (free_space < vb2_get_plane_payload(vb, 0) + 0x40000) 1253 + return -ENOMEM; 1254 + 1255 + timestamp = vb->timestamp; 1256 + if (timestamp >= 0 && vdec->ts_start < 0) 1257 + vdec->ts_start = timestamp; 1258 + if (vdec->ts_input < timestamp) 1259 + vdec->ts_input = timestamp; 1260 + 1261 + ret = vpu_iface_input_frame(inst, vb); 1262 + if (ret < 0) 1263 + return -ENOMEM; 1264 + 1265 + dev_dbg(inst->dev, "[%d][INPUT TS]%32lld\n", inst->id, vb->timestamp); 1266 + vdec->ts_pre_count++; 1267 + vdec->params.frame_count++; 1268 + 1269 + v4l2_m2m_src_buf_remove_by_buf(inst->fh.m2m_ctx, vbuf); 1270 + vpu_set_buffer_state(vbuf, VPU_BUF_STATE_IDLE); 1271 + v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_DONE); 1272 + 1273 + if (vdec->drain) 1274 + vdec_drain(inst); 1275 + 1276 + return 0; 1277 + } 1278 + 1279 + static int vdec_process_capture(struct vpu_inst *inst, struct vb2_buffer *vb) 1280 + { 1281 + struct vdec_t *vdec = inst->priv; 1282 + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 1283 + int ret; 1284 + 1285 + if (inst->state == VPU_CODEC_STATE_DYAMIC_RESOLUTION_CHANGE) 1286 + return -EINVAL; 1287 + if (vdec->reset_codec) 1288 + return -EINVAL; 1289 + 1290 + ret = vdec_response_frame(inst, vbuf); 1291 + if (ret) 1292 + return ret; 1293 + v4l2_m2m_dst_buf_remove_by_buf(inst->fh.m2m_ctx, vbuf); 1294 + return 0; 1295 + } 1296 + 1297 + static void vdec_on_queue_empty(struct vpu_inst *inst, u32 type) 1298 + { 1299 + struct vdec_t *vdec = inst->priv; 1300 + 1301 + if (V4L2_TYPE_IS_OUTPUT(type)) 1302 + return; 1303 + 1304 + vdec_handle_resolution_change(inst); 1305 + if (vdec->eos_received) 1306 + vdec_set_last_buffer_dequeued(inst); 1307 + } 1308 + 1309 + static void vdec_abort(struct vpu_inst *inst) 1310 + { 1311 + struct vdec_t *vdec = inst->priv; 1312 + struct vpu_rpc_buffer_desc desc; 1313 + int ret; 1314 + 1315 + vpu_trace(inst->dev, "[%d] state = %d\n", inst->id, inst->state); 1316 + vpu_iface_add_scode(inst, SCODE_PADDING_ABORT); 1317 + vdec->params.end_flag = 1; 1318 + vpu_iface_set_decode_params(inst, &vdec->params, 1); 1319 + 1320 + vpu_session_abort(inst); 1321 + 1322 + ret = vpu_iface_get_stream_buffer_desc(inst, &desc); 1323 + if (!ret) 1324 + vpu_iface_update_stream_buffer(inst, desc.rptr, 1); 1325 + 1326 + vpu_session_rst_buf(inst); 1327 + vpu_trace(inst->dev, "[%d] input : %d, decoded : %d, display : %d, sequence : %d\n", 1328 + inst->id, 1329 + vdec->params.frame_count, 1330 + vdec->decoded_frame_count, 1331 + vdec->display_frame_count, 1332 + vdec->sequence); 1333 + vdec->params.end_flag = 0; 1334 + vdec->drain = 0; 1335 + vdec->ts_pre_count = 0; 1336 + vdec->timestamp = VPU_INVALID_TIMESTAMP; 1337 + vdec->ts_start = VPU_INVALID_TIMESTAMP; 1338 + vdec->ts_input = VPU_INVALID_TIMESTAMP; 1339 + vdec->params.frame_count = 0; 1340 + vdec->decoded_frame_count = 0; 1341 + vdec->display_frame_count = 0; 1342 + vdec->sequence = 0; 1343 + } 1344 + 1345 + static void vdec_stop(struct vpu_inst *inst, bool free) 1346 + { 1347 + struct vdec_t *vdec = inst->priv; 1348 + 1349 + vdec_clear_slots(inst); 1350 + if (inst->state != VPU_CODEC_STATE_DEINIT) 1351 + vpu_session_stop(inst); 1352 + vdec_clear_fs(&vdec->mbi); 1353 + vdec_clear_fs(&vdec->dcp); 1354 + if (free) { 1355 + vpu_free_dma(&vdec->udata); 1356 + vpu_free_dma(&inst->stream_buffer); 1357 + } 1358 + vdec_update_state(inst, VPU_CODEC_STATE_DEINIT, 1); 1359 + vdec->reset_codec = false; 1360 + } 1361 + 1362 + static void vdec_release(struct vpu_inst *inst) 1363 + { 1364 + if (inst->id != VPU_INST_NULL_ID) 1365 + vpu_trace(inst->dev, "[%d]\n", inst->id); 1366 + vpu_inst_lock(inst); 1367 + vdec_stop(inst, true); 1368 + vpu_inst_unlock(inst); 1369 + } 1370 + 1371 + static void vdec_cleanup(struct vpu_inst *inst) 1372 + { 1373 + struct vdec_t *vdec; 1374 + 1375 + if (!inst) 1376 + return; 1377 + 1378 + vdec = inst->priv; 1379 + if (vdec) 1380 + vfree(vdec); 1381 + inst->priv = NULL; 1382 + vfree(inst); 1383 + } 1384 + 1385 + static void vdec_init_params(struct vdec_t *vdec) 1386 + { 1387 + vdec->params.frame_count = 0; 1388 + vdec->params.end_flag = 0; 1389 + } 1390 + 1391 + static int vdec_start(struct vpu_inst *inst) 1392 + { 1393 + struct vdec_t *vdec = inst->priv; 1394 + int stream_buffer_size; 1395 + int ret; 1396 + 1397 + if (inst->state != VPU_CODEC_STATE_DEINIT) 1398 + return 0; 1399 + 1400 + vpu_trace(inst->dev, "[%d]\n", inst->id); 1401 + if (!vdec->udata.virt) { 1402 + vdec->udata.length = 0x1000; 1403 + ret = vpu_alloc_dma(inst->core, &vdec->udata); 1404 + if (ret) { 1405 + dev_err(inst->dev, "[%d] alloc udata fail\n", inst->id); 1406 + goto error; 1407 + } 1408 + } 1409 + 1410 + if (!inst->stream_buffer.virt) { 1411 + stream_buffer_size = vpu_iface_get_stream_buffer_size(inst->core); 1412 + if (stream_buffer_size > 0) { 1413 + inst->stream_buffer.length = stream_buffer_size; 1414 + ret = vpu_alloc_dma(inst->core, &inst->stream_buffer); 1415 + if (ret) { 1416 + dev_err(inst->dev, "[%d] alloc stream buffer fail\n", inst->id); 1417 + goto error; 1418 + } 1419 + inst->use_stream_buffer = true; 1420 + } 1421 + } 1422 + 1423 + if (inst->use_stream_buffer) 1424 + vpu_iface_config_stream_buffer(inst, &inst->stream_buffer); 1425 + vpu_iface_init_instance(inst); 1426 + vdec->params.udata.base = vdec->udata.phys; 1427 + vdec->params.udata.size = vdec->udata.length; 1428 + ret = vpu_iface_set_decode_params(inst, &vdec->params, 0); 1429 + if (ret) { 1430 + dev_err(inst->dev, "[%d] set decode params fail\n", inst->id); 1431 + goto error; 1432 + } 1433 + 1434 + vdec_init_params(vdec); 1435 + ret = vpu_session_start(inst); 1436 + if (ret) { 1437 + dev_err(inst->dev, "[%d] start fail\n", inst->id); 1438 + goto error; 1439 + } 1440 + 1441 + vdec_update_state(inst, VPU_CODEC_STATE_STARTED, 0); 1442 + 1443 + return 0; 1444 + error: 1445 + vpu_free_dma(&vdec->udata); 1446 + vpu_free_dma(&inst->stream_buffer); 1447 + return ret; 1448 + } 1449 + 1450 + static int vdec_start_session(struct vpu_inst *inst, u32 type) 1451 + { 1452 + struct vdec_t *vdec = inst->priv; 1453 + int ret = 0; 1454 + 1455 + if (V4L2_TYPE_IS_OUTPUT(type)) { 1456 + if (vdec->reset_codec) 1457 + vdec_stop(inst, false); 1458 + if (inst->state == VPU_CODEC_STATE_DEINIT) { 1459 + ret = vdec_start(inst); 1460 + if (ret) 1461 + return ret; 1462 + } 1463 + } 1464 + 1465 + if (V4L2_TYPE_IS_OUTPUT(type)) { 1466 + if (inst->state == VPU_CODEC_STATE_SEEK) 1467 + vdec_update_state(inst, vdec->state, 1); 1468 + vdec->eos_received = 0; 1469 + vpu_process_output_buffer(inst); 1470 + } else { 1471 + vdec_cmd_start(inst); 1472 + } 1473 + if (inst->state == VPU_CODEC_STATE_ACTIVE) 1474 + vdec_response_fs_request(inst, false); 1475 + 1476 + return ret; 1477 + } 1478 + 1479 + static int vdec_stop_session(struct vpu_inst *inst, u32 type) 1480 + { 1481 + struct vdec_t *vdec = inst->priv; 1482 + 1483 + if (inst->state == VPU_CODEC_STATE_DEINIT) 1484 + return 0; 1485 + 1486 + if (V4L2_TYPE_IS_OUTPUT(type)) { 1487 + vdec_update_state(inst, VPU_CODEC_STATE_SEEK, 0); 1488 + vdec->drain = 0; 1489 + } else { 1490 + if (inst->state != VPU_CODEC_STATE_DYAMIC_RESOLUTION_CHANGE) 1491 + vdec_abort(inst); 1492 + 1493 + vdec->eos_received = 0; 1494 + vdec_clear_slots(inst); 1495 + } 1496 + 1497 + return 0; 1498 + } 1499 + 1500 + static int vdec_get_debug_info(struct vpu_inst *inst, char *str, u32 size, u32 i) 1501 + { 1502 + struct vdec_t *vdec = inst->priv; 1503 + int num = -1; 1504 + 1505 + switch (i) { 1506 + case 0: 1507 + num = scnprintf(str, size, 1508 + "req_frame_count = %d\ninterlaced = %d\n", 1509 + vdec->req_frame_count, 1510 + vdec->codec_info.progressive ? 0 : 1); 1511 + break; 1512 + case 1: 1513 + num = scnprintf(str, size, 1514 + "mbi: size = 0x%x request = %d, alloc = %d, response = %d\n", 1515 + vdec->mbi.size, 1516 + vdec->mbi.req_count, 1517 + vdec->mbi.count, 1518 + vdec->mbi.index); 1519 + break; 1520 + case 2: 1521 + num = scnprintf(str, size, 1522 + "dcp: size = 0x%x request = %d, alloc = %d, response = %d\n", 1523 + vdec->dcp.size, 1524 + vdec->dcp.req_count, 1525 + vdec->dcp.count, 1526 + vdec->dcp.index); 1527 + break; 1528 + case 3: 1529 + num = scnprintf(str, size, "input_frame_count = %d\n", vdec->params.frame_count); 1530 + break; 1531 + case 4: 1532 + num = scnprintf(str, size, "decoded_frame_count = %d\n", vdec->decoded_frame_count); 1533 + break; 1534 + case 5: 1535 + num = scnprintf(str, size, "display_frame_count = %d\n", vdec->display_frame_count); 1536 + break; 1537 + case 6: 1538 + num = scnprintf(str, size, "sequence = %d\n", vdec->sequence); 1539 + break; 1540 + case 7: 1541 + num = scnprintf(str, size, "drain = %d, eos = %d, source_change = %d\n", 1542 + vdec->drain, vdec->eos_received, vdec->source_change); 1543 + break; 1544 + case 8: 1545 + num = scnprintf(str, size, "ts_pre_count = %d, frame_depth = %d\n", 1546 + vdec->ts_pre_count, vdec->frame_depth); 1547 + break; 1548 + case 9: 1549 + num = scnprintf(str, size, "fps = %d/%d\n", 1550 + vdec->codec_info.frame_rate.numerator, 1551 + vdec->codec_info.frame_rate.denominator); 1552 + break; 1553 + case 10: 1554 + { 1555 + s64 timestamp = vdec->timestamp; 1556 + s64 ts_start = vdec->ts_start; 1557 + s64 ts_input = vdec->ts_input; 1558 + 1559 + num = scnprintf(str, size, "timestamp = %9lld.%09lld(%9lld.%09lld, %9lld.%09lld)\n", 1560 + timestamp / NSEC_PER_SEC, 1561 + timestamp % NSEC_PER_SEC, 1562 + ts_start / NSEC_PER_SEC, 1563 + ts_start % NSEC_PER_SEC, 1564 + ts_input / NSEC_PER_SEC, 1565 + ts_input % NSEC_PER_SEC); 1566 + } 1567 + break; 1568 + default: 1569 + break; 1570 + } 1571 + 1572 + return num; 1573 + } 1574 + 1575 + static struct vpu_inst_ops vdec_inst_ops = { 1576 + .ctrl_init = vdec_ctrl_init, 1577 + .check_ready = vdec_check_ready, 1578 + .buf_done = vdec_buf_done, 1579 + .get_one_frame = vdec_frame_decoded, 1580 + .stop_done = vdec_stop_done, 1581 + .event_notify = vdec_event_notify, 1582 + .release = vdec_release, 1583 + .cleanup = vdec_cleanup, 1584 + .start = vdec_start_session, 1585 + .stop = vdec_stop_session, 1586 + .process_output = vdec_process_output, 1587 + .process_capture = vdec_process_capture, 1588 + .on_queue_empty = vdec_on_queue_empty, 1589 + .get_debug_info = vdec_get_debug_info, 1590 + .wait_prepare = vpu_inst_unlock, 1591 + .wait_finish = vpu_inst_lock, 1592 + }; 1593 + 1594 + static void vdec_init(struct file *file) 1595 + { 1596 + struct vpu_inst *inst = to_inst(file); 1597 + struct vdec_t *vdec; 1598 + struct v4l2_format f; 1599 + 1600 + vdec = inst->priv; 1601 + vdec->frame_depth = VDEC_FRAME_DEPTH; 1602 + vdec->timestamp = VPU_INVALID_TIMESTAMP; 1603 + vdec->ts_start = VPU_INVALID_TIMESTAMP; 1604 + vdec->ts_input = VPU_INVALID_TIMESTAMP; 1605 + 1606 + memset(&f, 0, sizeof(f)); 1607 + f.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 1608 + f.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_H264; 1609 + f.fmt.pix_mp.width = 1280; 1610 + f.fmt.pix_mp.height = 720; 1611 + f.fmt.pix_mp.field = V4L2_FIELD_NONE; 1612 + vdec_s_fmt(file, &inst->fh, &f); 1613 + 1614 + memset(&f, 0, sizeof(f)); 1615 + f.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 1616 + f.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12M_8L128; 1617 + f.fmt.pix_mp.width = 1280; 1618 + f.fmt.pix_mp.height = 720; 1619 + f.fmt.pix_mp.field = V4L2_FIELD_NONE; 1620 + vdec_s_fmt(file, &inst->fh, &f); 1621 + } 1622 + 1623 + static int vdec_open(struct file *file) 1624 + { 1625 + struct vpu_inst *inst; 1626 + struct vdec_t *vdec; 1627 + int ret; 1628 + 1629 + inst = vzalloc(sizeof(*inst)); 1630 + if (!inst) 1631 + return -ENOMEM; 1632 + 1633 + vdec = vzalloc(sizeof(*vdec)); 1634 + if (!vdec) { 1635 + vfree(inst); 1636 + return -ENOMEM; 1637 + } 1638 + 1639 + inst->ops = &vdec_inst_ops; 1640 + inst->formats = vdec_formats; 1641 + inst->type = VPU_CORE_TYPE_DEC; 1642 + inst->priv = vdec; 1643 + 1644 + ret = vpu_v4l2_open(file, inst); 1645 + if (ret) 1646 + return ret; 1647 + 1648 + vdec->fixed_fmt = false; 1649 + inst->min_buffer_cap = VDEC_MIN_BUFFER_CAP; 1650 + vdec_init(file); 1651 + 1652 + return 0; 1653 + } 1654 + 1655 + static __poll_t vdec_poll(struct file *file, poll_table *wait) 1656 + { 1657 + struct vpu_inst *inst = to_inst(file); 1658 + struct vb2_queue *src_q, *dst_q; 1659 + __poll_t ret; 1660 + 1661 + ret = v4l2_m2m_fop_poll(file, wait); 1662 + src_q = v4l2_m2m_get_src_vq(inst->fh.m2m_ctx); 1663 + dst_q = v4l2_m2m_get_dst_vq(inst->fh.m2m_ctx); 1664 + if (vb2_is_streaming(src_q) && !vb2_is_streaming(dst_q)) 1665 + ret &= (~EPOLLERR); 1666 + if (!src_q->error && !dst_q->error && 1667 + (vb2_is_streaming(src_q) && list_empty(&src_q->queued_list)) && 1668 + (vb2_is_streaming(dst_q) && list_empty(&dst_q->queued_list))) 1669 + ret &= (~EPOLLERR); 1670 + 1671 + return ret; 1672 + } 1673 + 1674 + static const struct v4l2_file_operations vdec_fops = { 1675 + .owner = THIS_MODULE, 1676 + .open = vdec_open, 1677 + .release = vpu_v4l2_close, 1678 + .unlocked_ioctl = video_ioctl2, 1679 + .poll = vdec_poll, 1680 + .mmap = v4l2_m2m_fop_mmap, 1681 + }; 1682 + 1683 + const struct v4l2_ioctl_ops *vdec_get_ioctl_ops(void) 1684 + { 1685 + return &vdec_ioctl_ops; 1686 + } 1687 + 1688 + const struct v4l2_file_operations *vdec_get_fops(void) 1689 + { 1690 + return &vdec_fops; 1691 + }
+1358
drivers/media/platform/amphion/venc.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright 2020-2021 NXP 4 + */ 5 + 6 + #include <linux/init.h> 7 + #include <linux/interconnect.h> 8 + #include <linux/ioctl.h> 9 + #include <linux/list.h> 10 + #include <linux/kernel.h> 11 + #include <linux/module.h> 12 + #include <linux/delay.h> 13 + #include <linux/videodev2.h> 14 + #include <linux/ktime.h> 15 + #include <linux/rational.h> 16 + #include <linux/vmalloc.h> 17 + #include <media/v4l2-device.h> 18 + #include <media/v4l2-event.h> 19 + #include <media/v4l2-mem2mem.h> 20 + #include <media/v4l2-ioctl.h> 21 + #include <media/videobuf2-v4l2.h> 22 + #include <media/videobuf2-dma-contig.h> 23 + #include <media/videobuf2-vmalloc.h> 24 + #include "vpu.h" 25 + #include "vpu_defs.h" 26 + #include "vpu_core.h" 27 + #include "vpu_helpers.h" 28 + #include "vpu_v4l2.h" 29 + #include "vpu_cmds.h" 30 + #include "vpu_rpc.h" 31 + 32 + #define VENC_OUTPUT_ENABLE BIT(0) 33 + #define VENC_CAPTURE_ENABLE BIT(1) 34 + #define VENC_ENABLE_MASK (VENC_OUTPUT_ENABLE | VENC_CAPTURE_ENABLE) 35 + #define VENC_MAX_BUF_CNT 8 36 + 37 + struct venc_t { 38 + struct vpu_encode_params params; 39 + u32 request_key_frame; 40 + u32 input_ready; 41 + u32 cpb_size; 42 + bool bitrate_change; 43 + 44 + struct vpu_buffer enc[VENC_MAX_BUF_CNT]; 45 + struct vpu_buffer ref[VENC_MAX_BUF_CNT]; 46 + struct vpu_buffer act[VENC_MAX_BUF_CNT]; 47 + struct list_head frames; 48 + u32 frame_count; 49 + u32 encode_count; 50 + u32 ready_count; 51 + u32 enable; 52 + u32 stopped; 53 + 54 + u32 skipped_count; 55 + u32 skipped_bytes; 56 + 57 + wait_queue_head_t wq; 58 + }; 59 + 60 + struct venc_frame_t { 61 + struct list_head list; 62 + struct vpu_enc_pic_info info; 63 + u32 bytesused; 64 + s64 timestamp; 65 + }; 66 + 67 + static const struct vpu_format venc_formats[] = { 68 + { 69 + .pixfmt = V4L2_PIX_FMT_NV12M, 70 + .num_planes = 2, 71 + .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, 72 + }, 73 + { 74 + .pixfmt = V4L2_PIX_FMT_H264, 75 + .num_planes = 1, 76 + .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, 77 + }, 78 + {0, 0, 0, 0}, 79 + }; 80 + 81 + static int venc_querycap(struct file *file, void *fh, struct v4l2_capability *cap) 82 + { 83 + strscpy(cap->driver, "amphion-vpu", sizeof(cap->driver)); 84 + strscpy(cap->card, "amphion vpu encoder", sizeof(cap->card)); 85 + strscpy(cap->bus_info, "platform: amphion-vpu", sizeof(cap->bus_info)); 86 + 87 + return 0; 88 + } 89 + 90 + static int venc_enum_fmt(struct file *file, void *fh, struct v4l2_fmtdesc *f) 91 + { 92 + struct vpu_inst *inst = to_inst(file); 93 + const struct vpu_format *fmt; 94 + 95 + memset(f->reserved, 0, sizeof(f->reserved)); 96 + fmt = vpu_helper_enum_format(inst, f->type, f->index); 97 + if (!fmt) 98 + return -EINVAL; 99 + 100 + f->pixelformat = fmt->pixfmt; 101 + f->flags = fmt->flags; 102 + 103 + return 0; 104 + } 105 + 106 + static int venc_enum_framesizes(struct file *file, void *fh, struct v4l2_frmsizeenum *fsize) 107 + { 108 + struct vpu_inst *inst = to_inst(file); 109 + const struct vpu_core_resources *res; 110 + 111 + if (!fsize || fsize->index) 112 + return -EINVAL; 113 + 114 + if (!vpu_helper_find_format(inst, 0, fsize->pixel_format)) 115 + return -EINVAL; 116 + 117 + res = vpu_get_resource(inst); 118 + if (!res) 119 + return -EINVAL; 120 + fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE; 121 + fsize->stepwise.max_width = res->max_width; 122 + fsize->stepwise.max_height = res->max_height; 123 + fsize->stepwise.min_width = res->min_width; 124 + fsize->stepwise.min_height = res->min_height; 125 + fsize->stepwise.step_width = res->step_width; 126 + fsize->stepwise.step_height = res->step_height; 127 + 128 + return 0; 129 + } 130 + 131 + static int venc_enum_frameintervals(struct file *file, void *fh, struct v4l2_frmivalenum *fival) 132 + { 133 + struct vpu_inst *inst = to_inst(file); 134 + const struct vpu_core_resources *res; 135 + 136 + if (!fival || fival->index) 137 + return -EINVAL; 138 + 139 + if (!vpu_helper_find_format(inst, 0, fival->pixel_format)) 140 + return -EINVAL; 141 + 142 + if (!fival->width || !fival->height) 143 + return -EINVAL; 144 + 145 + res = vpu_get_resource(inst); 146 + if (!res) 147 + return -EINVAL; 148 + if (fival->width < res->min_width || fival->width > res->max_width || 149 + fival->height < res->min_height || fival->height > res->max_height) 150 + return -EINVAL; 151 + 152 + fival->type = V4L2_FRMIVAL_TYPE_CONTINUOUS; 153 + fival->stepwise.min.numerator = 1; 154 + fival->stepwise.min.denominator = USHRT_MAX; 155 + fival->stepwise.max.numerator = USHRT_MAX; 156 + fival->stepwise.max.denominator = 1; 157 + fival->stepwise.step.numerator = 1; 158 + fival->stepwise.step.denominator = 1; 159 + 160 + return 0; 161 + } 162 + 163 + static int venc_g_fmt(struct file *file, void *fh, struct v4l2_format *f) 164 + { 165 + struct vpu_inst *inst = to_inst(file); 166 + struct venc_t *venc = inst->priv; 167 + struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp; 168 + struct vpu_format *cur_fmt; 169 + int i; 170 + 171 + cur_fmt = vpu_get_format(inst, f->type); 172 + 173 + pixmp->pixelformat = cur_fmt->pixfmt; 174 + pixmp->num_planes = cur_fmt->num_planes; 175 + pixmp->width = cur_fmt->width; 176 + pixmp->height = cur_fmt->height; 177 + pixmp->field = cur_fmt->field; 178 + pixmp->flags = cur_fmt->flags; 179 + for (i = 0; i < pixmp->num_planes; i++) { 180 + pixmp->plane_fmt[i].bytesperline = cur_fmt->bytesperline[i]; 181 + pixmp->plane_fmt[i].sizeimage = cur_fmt->sizeimage[i]; 182 + } 183 + 184 + f->fmt.pix_mp.colorspace = venc->params.color.primaries; 185 + f->fmt.pix_mp.xfer_func = venc->params.color.transfer; 186 + f->fmt.pix_mp.ycbcr_enc = venc->params.color.matrix; 187 + f->fmt.pix_mp.quantization = venc->params.color.full_range; 188 + 189 + return 0; 190 + } 191 + 192 + static int venc_try_fmt(struct file *file, void *fh, struct v4l2_format *f) 193 + { 194 + struct vpu_inst *inst = to_inst(file); 195 + 196 + vpu_try_fmt_common(inst, f); 197 + 198 + return 0; 199 + } 200 + 201 + static int venc_s_fmt(struct file *file, void *fh, struct v4l2_format *f) 202 + { 203 + struct vpu_inst *inst = to_inst(file); 204 + const struct vpu_format *fmt; 205 + struct vpu_format *cur_fmt; 206 + struct vb2_queue *q; 207 + struct venc_t *venc = inst->priv; 208 + struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp; 209 + int i; 210 + 211 + q = v4l2_m2m_get_vq(inst->fh.m2m_ctx, f->type); 212 + if (!q) 213 + return -EINVAL; 214 + if (vb2_is_busy(q)) 215 + return -EBUSY; 216 + 217 + fmt = vpu_try_fmt_common(inst, f); 218 + if (!fmt) 219 + return -EINVAL; 220 + 221 + cur_fmt = vpu_get_format(inst, f->type); 222 + 223 + cur_fmt->pixfmt = fmt->pixfmt; 224 + cur_fmt->num_planes = fmt->num_planes; 225 + cur_fmt->flags = fmt->flags; 226 + cur_fmt->width = pix_mp->width; 227 + cur_fmt->height = pix_mp->height; 228 + for (i = 0; i < fmt->num_planes; i++) { 229 + cur_fmt->sizeimage[i] = pix_mp->plane_fmt[i].sizeimage; 230 + cur_fmt->bytesperline[i] = pix_mp->plane_fmt[i].bytesperline; 231 + } 232 + 233 + if (pix_mp->field != V4L2_FIELD_ANY) 234 + cur_fmt->field = pix_mp->field; 235 + 236 + if (V4L2_TYPE_IS_OUTPUT(f->type)) { 237 + venc->params.input_format = cur_fmt->pixfmt; 238 + venc->params.src_stride = cur_fmt->bytesperline[0]; 239 + venc->params.src_width = cur_fmt->width; 240 + venc->params.src_height = cur_fmt->height; 241 + venc->params.crop.left = 0; 242 + venc->params.crop.top = 0; 243 + venc->params.crop.width = cur_fmt->width; 244 + venc->params.crop.height = cur_fmt->height; 245 + } else { 246 + venc->params.codec_format = cur_fmt->pixfmt; 247 + venc->params.out_width = cur_fmt->width; 248 + venc->params.out_height = cur_fmt->height; 249 + } 250 + 251 + if (V4L2_TYPE_IS_OUTPUT(f->type)) { 252 + if (!vpu_color_check_primaries(pix_mp->colorspace)) { 253 + venc->params.color.primaries = pix_mp->colorspace; 254 + vpu_color_get_default(venc->params.color.primaries, 255 + &venc->params.color.transfer, 256 + &venc->params.color.matrix, 257 + &venc->params.color.full_range); 258 + } 259 + if (!vpu_color_check_transfers(pix_mp->xfer_func)) 260 + venc->params.color.transfer = pix_mp->xfer_func; 261 + if (!vpu_color_check_matrix(pix_mp->ycbcr_enc)) 262 + venc->params.color.matrix = pix_mp->ycbcr_enc; 263 + if (!vpu_color_check_full_range(pix_mp->quantization)) 264 + venc->params.color.full_range = pix_mp->quantization; 265 + } 266 + 267 + pix_mp->colorspace = venc->params.color.primaries; 268 + pix_mp->xfer_func = venc->params.color.transfer; 269 + pix_mp->ycbcr_enc = venc->params.color.matrix; 270 + pix_mp->quantization = venc->params.color.full_range; 271 + 272 + return 0; 273 + } 274 + 275 + static int venc_g_parm(struct file *file, void *fh, struct v4l2_streamparm *parm) 276 + { 277 + struct vpu_inst *inst = to_inst(file); 278 + struct venc_t *venc = inst->priv; 279 + struct v4l2_fract *timeperframe = &parm->parm.capture.timeperframe; 280 + 281 + if (!parm) 282 + return -EINVAL; 283 + 284 + if (!vpu_helper_check_type(inst, parm->type)) 285 + return -EINVAL; 286 + 287 + parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME; 288 + parm->parm.capture.readbuffers = 0; 289 + timeperframe->numerator = venc->params.frame_rate.numerator; 290 + timeperframe->denominator = venc->params.frame_rate.denominator; 291 + 292 + return 0; 293 + } 294 + 295 + static int venc_s_parm(struct file *file, void *fh, struct v4l2_streamparm *parm) 296 + { 297 + struct vpu_inst *inst = to_inst(file); 298 + struct venc_t *venc = inst->priv; 299 + struct v4l2_fract *timeperframe = &parm->parm.capture.timeperframe; 300 + unsigned long n, d; 301 + 302 + if (!parm) 303 + return -EINVAL; 304 + 305 + if (!vpu_helper_check_type(inst, parm->type)) 306 + return -EINVAL; 307 + 308 + if (!timeperframe->numerator) 309 + timeperframe->numerator = venc->params.frame_rate.numerator; 310 + if (!timeperframe->denominator) 311 + timeperframe->denominator = venc->params.frame_rate.denominator; 312 + 313 + venc->params.frame_rate.numerator = timeperframe->numerator; 314 + venc->params.frame_rate.denominator = timeperframe->denominator; 315 + 316 + rational_best_approximation(venc->params.frame_rate.numerator, 317 + venc->params.frame_rate.denominator, 318 + venc->params.frame_rate.numerator, 319 + venc->params.frame_rate.denominator, 320 + &n, &d); 321 + venc->params.frame_rate.numerator = n; 322 + venc->params.frame_rate.denominator = d; 323 + 324 + parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME; 325 + memset(parm->parm.capture.reserved, 0, sizeof(parm->parm.capture.reserved)); 326 + 327 + return 0; 328 + } 329 + 330 + static int venc_g_selection(struct file *file, void *fh, struct v4l2_selection *s) 331 + { 332 + struct vpu_inst *inst = to_inst(file); 333 + struct venc_t *venc = inst->priv; 334 + 335 + if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT && s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) 336 + return -EINVAL; 337 + 338 + switch (s->target) { 339 + case V4L2_SEL_TGT_CROP_DEFAULT: 340 + case V4L2_SEL_TGT_CROP_BOUNDS: 341 + s->r.left = 0; 342 + s->r.top = 0; 343 + s->r.width = inst->out_format.width; 344 + s->r.height = inst->out_format.height; 345 + break; 346 + case V4L2_SEL_TGT_CROP: 347 + s->r = venc->params.crop; 348 + break; 349 + default: 350 + return -EINVAL; 351 + } 352 + 353 + return 0; 354 + } 355 + 356 + static int venc_valid_crop(struct venc_t *venc, const struct vpu_core_resources *res) 357 + { 358 + struct v4l2_rect *rect = NULL; 359 + u32 min_width; 360 + u32 min_height; 361 + u32 src_width; 362 + u32 src_height; 363 + 364 + rect = &venc->params.crop; 365 + min_width = res->min_width; 366 + min_height = res->min_height; 367 + src_width = venc->params.src_width; 368 + src_height = venc->params.src_height; 369 + 370 + if (rect->width == 0 || rect->height == 0) 371 + return -EINVAL; 372 + if (rect->left > src_width - min_width || rect->top > src_height - min_height) 373 + return -EINVAL; 374 + 375 + rect->width = min(rect->width, src_width - rect->left); 376 + rect->width = max_t(u32, rect->width, min_width); 377 + 378 + rect->height = min(rect->height, src_height - rect->top); 379 + rect->height = max_t(u32, rect->height, min_height); 380 + 381 + return 0; 382 + } 383 + 384 + static int venc_s_selection(struct file *file, void *fh, struct v4l2_selection *s) 385 + { 386 + struct vpu_inst *inst = to_inst(file); 387 + const struct vpu_core_resources *res; 388 + struct venc_t *venc = inst->priv; 389 + 390 + res = vpu_get_resource(inst); 391 + if (!res) 392 + return -EINVAL; 393 + 394 + if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT && s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) 395 + return -EINVAL; 396 + if (s->target != V4L2_SEL_TGT_CROP) 397 + return -EINVAL; 398 + 399 + venc->params.crop.left = ALIGN(s->r.left, res->step_width); 400 + venc->params.crop.top = ALIGN(s->r.top, res->step_height); 401 + venc->params.crop.width = ALIGN(s->r.width, res->step_width); 402 + venc->params.crop.height = ALIGN(s->r.height, res->step_height); 403 + if (venc_valid_crop(venc, res)) { 404 + venc->params.crop.left = 0; 405 + venc->params.crop.top = 0; 406 + venc->params.crop.width = venc->params.src_width; 407 + venc->params.crop.height = venc->params.src_height; 408 + } 409 + 410 + inst->crop = venc->params.crop; 411 + 412 + return 0; 413 + } 414 + 415 + static int venc_drain(struct vpu_inst *inst) 416 + { 417 + struct venc_t *venc = inst->priv; 418 + int ret; 419 + 420 + if (!inst->fh.m2m_ctx) 421 + return 0; 422 + 423 + if (inst->state != VPU_CODEC_STATE_DRAIN) 424 + return 0; 425 + 426 + if (v4l2_m2m_num_src_bufs_ready(inst->fh.m2m_ctx)) 427 + return 0; 428 + 429 + if (!venc->input_ready) 430 + return 0; 431 + 432 + venc->input_ready = false; 433 + vpu_trace(inst->dev, "[%d]\n", inst->id); 434 + ret = vpu_session_stop(inst); 435 + if (ret) 436 + return ret; 437 + inst->state = VPU_CODEC_STATE_STOP; 438 + wake_up_all(&venc->wq); 439 + 440 + return 0; 441 + } 442 + 443 + static int venc_request_eos(struct vpu_inst *inst) 444 + { 445 + inst->state = VPU_CODEC_STATE_DRAIN; 446 + venc_drain(inst); 447 + 448 + return 0; 449 + } 450 + 451 + static int venc_encoder_cmd(struct file *file, void *fh, struct v4l2_encoder_cmd *cmd) 452 + { 453 + struct vpu_inst *inst = to_inst(file); 454 + int ret; 455 + 456 + ret = v4l2_m2m_ioctl_try_encoder_cmd(file, fh, cmd); 457 + if (ret) 458 + return ret; 459 + 460 + vpu_inst_lock(inst); 461 + if (cmd->cmd == V4L2_ENC_CMD_STOP) { 462 + if (inst->state == VPU_CODEC_STATE_DEINIT) 463 + vpu_set_last_buffer_dequeued(inst); 464 + else 465 + venc_request_eos(inst); 466 + } 467 + vpu_inst_unlock(inst); 468 + 469 + return 0; 470 + } 471 + 472 + static int venc_subscribe_event(struct v4l2_fh *fh, const struct v4l2_event_subscription *sub) 473 + { 474 + switch (sub->type) { 475 + case V4L2_EVENT_EOS: 476 + return v4l2_event_subscribe(fh, sub, 0, NULL); 477 + case V4L2_EVENT_CTRL: 478 + return v4l2_ctrl_subscribe_event(fh, sub); 479 + default: 480 + return -EINVAL; 481 + } 482 + } 483 + 484 + static const struct v4l2_ioctl_ops venc_ioctl_ops = { 485 + .vidioc_querycap = venc_querycap, 486 + .vidioc_enum_fmt_vid_cap = venc_enum_fmt, 487 + .vidioc_enum_fmt_vid_out = venc_enum_fmt, 488 + .vidioc_enum_framesizes = venc_enum_framesizes, 489 + .vidioc_enum_frameintervals = venc_enum_frameintervals, 490 + .vidioc_g_fmt_vid_cap_mplane = venc_g_fmt, 491 + .vidioc_g_fmt_vid_out_mplane = venc_g_fmt, 492 + .vidioc_try_fmt_vid_cap_mplane = venc_try_fmt, 493 + .vidioc_try_fmt_vid_out_mplane = venc_try_fmt, 494 + .vidioc_s_fmt_vid_cap_mplane = venc_s_fmt, 495 + .vidioc_s_fmt_vid_out_mplane = venc_s_fmt, 496 + .vidioc_g_parm = venc_g_parm, 497 + .vidioc_s_parm = venc_s_parm, 498 + .vidioc_g_selection = venc_g_selection, 499 + .vidioc_s_selection = venc_s_selection, 500 + .vidioc_try_encoder_cmd = v4l2_m2m_ioctl_try_encoder_cmd, 501 + .vidioc_encoder_cmd = venc_encoder_cmd, 502 + .vidioc_subscribe_event = venc_subscribe_event, 503 + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, 504 + .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs, 505 + .vidioc_querybuf = v4l2_m2m_ioctl_querybuf, 506 + .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs, 507 + .vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf, 508 + .vidioc_qbuf = v4l2_m2m_ioctl_qbuf, 509 + .vidioc_expbuf = v4l2_m2m_ioctl_expbuf, 510 + .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf, 511 + .vidioc_streamon = v4l2_m2m_ioctl_streamon, 512 + .vidioc_streamoff = v4l2_m2m_ioctl_streamoff, 513 + }; 514 + 515 + static int venc_op_s_ctrl(struct v4l2_ctrl *ctrl) 516 + { 517 + struct vpu_inst *inst = ctrl_to_inst(ctrl); 518 + struct venc_t *venc = inst->priv; 519 + int ret = 0; 520 + 521 + vpu_inst_lock(inst); 522 + switch (ctrl->id) { 523 + case V4L2_CID_MPEG_VIDEO_H264_PROFILE: 524 + venc->params.profile = ctrl->val; 525 + break; 526 + case V4L2_CID_MPEG_VIDEO_H264_LEVEL: 527 + venc->params.level = ctrl->val; 528 + break; 529 + case V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE: 530 + venc->params.rc_enable = ctrl->val; 531 + break; 532 + case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: 533 + venc->params.rc_mode = ctrl->val; 534 + break; 535 + case V4L2_CID_MPEG_VIDEO_BITRATE: 536 + if (ctrl->val != venc->params.bitrate) 537 + venc->bitrate_change = true; 538 + venc->params.bitrate = ctrl->val; 539 + break; 540 + case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: 541 + venc->params.bitrate_max = ctrl->val; 542 + break; 543 + case V4L2_CID_MPEG_VIDEO_GOP_SIZE: 544 + venc->params.gop_length = ctrl->val; 545 + break; 546 + case V4L2_CID_MPEG_VIDEO_B_FRAMES: 547 + venc->params.bframes = ctrl->val; 548 + break; 549 + case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP: 550 + venc->params.i_frame_qp = ctrl->val; 551 + break; 552 + case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP: 553 + venc->params.p_frame_qp = ctrl->val; 554 + break; 555 + case V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP: 556 + venc->params.b_frame_qp = ctrl->val; 557 + break; 558 + case V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME: 559 + venc->request_key_frame = 1; 560 + break; 561 + case V4L2_CID_MPEG_VIDEO_H264_CPB_SIZE: 562 + venc->cpb_size = ctrl->val * 1024; 563 + break; 564 + case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_ENABLE: 565 + venc->params.sar.enable = ctrl->val; 566 + break; 567 + case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC: 568 + venc->params.sar.idc = ctrl->val; 569 + break; 570 + case V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_WIDTH: 571 + venc->params.sar.width = ctrl->val; 572 + break; 573 + case V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_HEIGHT: 574 + venc->params.sar.height = ctrl->val; 575 + break; 576 + case V4L2_CID_MPEG_VIDEO_HEADER_MODE: 577 + break; 578 + default: 579 + ret = -EINVAL; 580 + break; 581 + } 582 + vpu_inst_unlock(inst); 583 + 584 + return ret; 585 + } 586 + 587 + static const struct v4l2_ctrl_ops venc_ctrl_ops = { 588 + .s_ctrl = venc_op_s_ctrl, 589 + .g_volatile_ctrl = vpu_helper_g_volatile_ctrl, 590 + }; 591 + 592 + static int venc_ctrl_init(struct vpu_inst *inst) 593 + { 594 + struct v4l2_ctrl *ctrl; 595 + int ret; 596 + 597 + ret = v4l2_ctrl_handler_init(&inst->ctrl_handler, 20); 598 + if (ret) 599 + return ret; 600 + 601 + v4l2_ctrl_new_std_menu(&inst->ctrl_handler, &venc_ctrl_ops, 602 + V4L2_CID_MPEG_VIDEO_H264_PROFILE, 603 + V4L2_MPEG_VIDEO_H264_PROFILE_HIGH, 604 + ~((1 << V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) | 605 + (1 << V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) | 606 + (1 << V4L2_MPEG_VIDEO_H264_PROFILE_HIGH)), 607 + V4L2_MPEG_VIDEO_H264_PROFILE_HIGH); 608 + 609 + v4l2_ctrl_new_std_menu(&inst->ctrl_handler, &venc_ctrl_ops, 610 + V4L2_CID_MPEG_VIDEO_H264_LEVEL, 611 + V4L2_MPEG_VIDEO_H264_LEVEL_5_1, 612 + 0x0, 613 + V4L2_MPEG_VIDEO_H264_LEVEL_4_0); 614 + 615 + v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops, 616 + V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE, 0, 1, 1, 1); 617 + 618 + v4l2_ctrl_new_std_menu(&inst->ctrl_handler, &venc_ctrl_ops, 619 + V4L2_CID_MPEG_VIDEO_BITRATE_MODE, 620 + V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 621 + ~((1 << V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) | 622 + (1 << V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)), 623 + V4L2_MPEG_VIDEO_BITRATE_MODE_CBR); 624 + 625 + v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops, 626 + V4L2_CID_MPEG_VIDEO_BITRATE, 627 + BITRATE_MIN, 628 + BITRATE_MAX, 629 + BITRATE_STEP, 630 + BITRATE_DEFAULT); 631 + 632 + v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops, 633 + V4L2_CID_MPEG_VIDEO_BITRATE_PEAK, 634 + BITRATE_MIN, BITRATE_MAX, 635 + BITRATE_STEP, 636 + BITRATE_DEFAULT_PEAK); 637 + 638 + v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops, 639 + V4L2_CID_MPEG_VIDEO_GOP_SIZE, 0, (1 << 16) - 1, 1, 30); 640 + 641 + v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops, 642 + V4L2_CID_MPEG_VIDEO_B_FRAMES, 0, 4, 1, 0); 643 + 644 + v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops, 645 + V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP, 1, 51, 1, 26); 646 + v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops, 647 + V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP, 1, 51, 1, 28); 648 + v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops, 649 + V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP, 1, 51, 1, 30); 650 + v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops, 651 + V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME, 0, 0, 0, 0); 652 + ctrl = v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops, 653 + V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, 1, 32, 1, 2); 654 + if (ctrl) 655 + ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE; 656 + ctrl = v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops, 657 + V4L2_CID_MIN_BUFFERS_FOR_OUTPUT, 1, 32, 1, 2); 658 + if (ctrl) 659 + ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE; 660 + 661 + v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops, 662 + V4L2_CID_MPEG_VIDEO_H264_CPB_SIZE, 64, 10240, 1, 1024); 663 + 664 + v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops, 665 + V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_ENABLE, 0, 1, 1, 1); 666 + v4l2_ctrl_new_std_menu(&inst->ctrl_handler, &venc_ctrl_ops, 667 + V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC, 668 + V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_EXTENDED, 669 + 0x0, 670 + V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_1x1); 671 + v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops, 672 + V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_WIDTH, 673 + 0, USHRT_MAX, 1, 1); 674 + v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops, 675 + V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_HEIGHT, 676 + 0, USHRT_MAX, 1, 1); 677 + v4l2_ctrl_new_std_menu(&inst->ctrl_handler, &venc_ctrl_ops, 678 + V4L2_CID_MPEG_VIDEO_HEADER_MODE, 679 + V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME, 680 + ~(1 << V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME), 681 + V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME); 682 + 683 + ret = v4l2_ctrl_handler_setup(&inst->ctrl_handler); 684 + if (ret) { 685 + dev_err(inst->dev, "[%d] setup ctrls fail, ret = %d\n", inst->id, ret); 686 + v4l2_ctrl_handler_free(&inst->ctrl_handler); 687 + return ret; 688 + } 689 + 690 + return 0; 691 + } 692 + 693 + static bool venc_check_ready(struct vpu_inst *inst, unsigned int type) 694 + { 695 + struct venc_t *venc = inst->priv; 696 + 697 + if (V4L2_TYPE_IS_OUTPUT(type)) { 698 + if (vpu_helper_get_free_space(inst) < venc->cpb_size) 699 + return false; 700 + return venc->input_ready; 701 + } 702 + 703 + if (list_empty(&venc->frames)) 704 + return false; 705 + return true; 706 + } 707 + 708 + static u32 venc_get_enable_mask(u32 type) 709 + { 710 + if (V4L2_TYPE_IS_OUTPUT(type)) 711 + return VENC_OUTPUT_ENABLE; 712 + else 713 + return VENC_CAPTURE_ENABLE; 714 + } 715 + 716 + static void venc_set_enable(struct venc_t *venc, u32 type, int enable) 717 + { 718 + u32 mask = venc_get_enable_mask(type); 719 + 720 + if (enable) 721 + venc->enable |= mask; 722 + else 723 + venc->enable &= ~mask; 724 + } 725 + 726 + static u32 venc_get_enable(struct venc_t *venc, u32 type) 727 + { 728 + return venc->enable & venc_get_enable_mask(type); 729 + } 730 + 731 + static void venc_input_done(struct vpu_inst *inst) 732 + { 733 + struct venc_t *venc = inst->priv; 734 + 735 + vpu_inst_lock(inst); 736 + venc->input_ready = true; 737 + vpu_process_output_buffer(inst); 738 + if (inst->state == VPU_CODEC_STATE_DRAIN) 739 + venc_drain(inst); 740 + vpu_inst_unlock(inst); 741 + } 742 + 743 + /* 744 + * It's hardware limitation, that there may be several bytes 745 + * redundant data at the beginning of frame. 746 + * For android platform, the redundant data may cause cts test fail 747 + * So driver will strip them 748 + */ 749 + static int venc_precheck_encoded_frame(struct vpu_inst *inst, struct venc_frame_t *frame) 750 + { 751 + struct venc_t *venc; 752 + int skipped; 753 + 754 + if (!frame || !frame->bytesused) 755 + return -EINVAL; 756 + 757 + venc = inst->priv; 758 + skipped = vpu_helper_find_startcode(&inst->stream_buffer, 759 + inst->cap_format.pixfmt, 760 + frame->info.wptr - inst->stream_buffer.phys, 761 + frame->bytesused); 762 + if (skipped > 0) { 763 + frame->bytesused -= skipped; 764 + frame->info.wptr = vpu_helper_step_walk(&inst->stream_buffer, 765 + frame->info.wptr, skipped); 766 + venc->skipped_bytes += skipped; 767 + venc->skipped_count++; 768 + } 769 + 770 + return 0; 771 + } 772 + 773 + static int venc_get_one_encoded_frame(struct vpu_inst *inst, 774 + struct venc_frame_t *frame, 775 + struct vb2_v4l2_buffer *vbuf) 776 + { 777 + struct venc_t *venc = inst->priv; 778 + 779 + if (!vbuf) 780 + return -EAGAIN; 781 + 782 + if (!venc_get_enable(inst->priv, vbuf->vb2_buf.type)) { 783 + v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR); 784 + return 0; 785 + } 786 + if (frame->bytesused > vbuf->vb2_buf.planes[0].length) { 787 + v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR); 788 + return -ENOMEM; 789 + } 790 + 791 + venc_precheck_encoded_frame(inst, frame); 792 + 793 + if (frame->bytesused) { 794 + u32 rptr = frame->info.wptr; 795 + void *dst = vb2_plane_vaddr(&vbuf->vb2_buf, 0); 796 + 797 + vpu_helper_copy_from_stream_buffer(&inst->stream_buffer, 798 + &rptr, frame->bytesused, dst); 799 + vpu_iface_update_stream_buffer(inst, rptr, 0); 800 + } 801 + vb2_set_plane_payload(&vbuf->vb2_buf, 0, frame->bytesused); 802 + vbuf->sequence = frame->info.frame_id; 803 + vbuf->vb2_buf.timestamp = frame->info.timestamp; 804 + vbuf->field = inst->cap_format.field; 805 + vbuf->flags |= frame->info.pic_type; 806 + vpu_set_buffer_state(vbuf, VPU_BUF_STATE_IDLE); 807 + dev_dbg(inst->dev, "[%d][OUTPUT TS]%32lld\n", inst->id, frame->info.timestamp); 808 + v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_DONE); 809 + venc->ready_count++; 810 + 811 + if (vbuf->flags & V4L2_BUF_FLAG_KEYFRAME) 812 + dev_dbg(inst->dev, "[%d][%d]key frame\n", inst->id, frame->info.frame_id); 813 + 814 + return 0; 815 + } 816 + 817 + static int venc_get_encoded_frames(struct vpu_inst *inst) 818 + { 819 + struct venc_t *venc; 820 + struct venc_frame_t *frame; 821 + struct venc_frame_t *tmp; 822 + 823 + if (!inst->fh.m2m_ctx) 824 + return 0; 825 + venc = inst->priv; 826 + list_for_each_entry_safe(frame, tmp, &venc->frames, list) { 827 + if (venc_get_one_encoded_frame(inst, frame, 828 + v4l2_m2m_dst_buf_remove(inst->fh.m2m_ctx))) 829 + break; 830 + list_del_init(&frame->list); 831 + vfree(frame); 832 + } 833 + 834 + return 0; 835 + } 836 + 837 + static int venc_frame_encoded(struct vpu_inst *inst, void *arg) 838 + { 839 + struct vpu_enc_pic_info *info = arg; 840 + struct venc_frame_t *frame; 841 + struct venc_t *venc; 842 + int ret = 0; 843 + 844 + if (!info) 845 + return -EINVAL; 846 + venc = inst->priv; 847 + frame = vzalloc(sizeof(*frame)); 848 + if (!frame) 849 + return -ENOMEM; 850 + 851 + memcpy(&frame->info, info, sizeof(frame->info)); 852 + frame->bytesused = info->frame_size; 853 + 854 + vpu_inst_lock(inst); 855 + list_add_tail(&frame->list, &venc->frames); 856 + venc->encode_count++; 857 + venc_get_encoded_frames(inst); 858 + vpu_inst_unlock(inst); 859 + 860 + return ret; 861 + } 862 + 863 + static void venc_buf_done(struct vpu_inst *inst, struct vpu_frame_info *frame) 864 + { 865 + struct vb2_v4l2_buffer *vbuf; 866 + 867 + if (!inst->fh.m2m_ctx) 868 + return; 869 + 870 + vpu_inst_lock(inst); 871 + if (!venc_get_enable(inst->priv, frame->type)) 872 + goto exit; 873 + vbuf = vpu_find_buf_by_sequence(inst, frame->type, frame->sequence); 874 + if (!vbuf) { 875 + dev_err(inst->dev, "[%d] can't find buf: type %d, sequence %d\n", 876 + inst->id, frame->type, frame->sequence); 877 + goto exit; 878 + } 879 + 880 + vpu_set_buffer_state(vbuf, VPU_BUF_STATE_IDLE); 881 + if (V4L2_TYPE_IS_OUTPUT(frame->type)) 882 + v4l2_m2m_src_buf_remove_by_buf(inst->fh.m2m_ctx, vbuf); 883 + else 884 + v4l2_m2m_dst_buf_remove_by_buf(inst->fh.m2m_ctx, vbuf); 885 + v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_DONE); 886 + exit: 887 + vpu_inst_unlock(inst); 888 + } 889 + 890 + static void venc_set_last_buffer_dequeued(struct vpu_inst *inst) 891 + { 892 + struct venc_t *venc = inst->priv; 893 + 894 + if (venc->stopped && list_empty(&venc->frames)) 895 + vpu_set_last_buffer_dequeued(inst); 896 + } 897 + 898 + static void venc_stop_done(struct vpu_inst *inst) 899 + { 900 + struct venc_t *venc = inst->priv; 901 + 902 + vpu_inst_lock(inst); 903 + venc->stopped = true; 904 + venc_set_last_buffer_dequeued(inst); 905 + vpu_inst_unlock(inst); 906 + 907 + wake_up_all(&venc->wq); 908 + } 909 + 910 + static void venc_event_notify(struct vpu_inst *inst, u32 event, void *data) 911 + { 912 + } 913 + 914 + static void venc_release(struct vpu_inst *inst) 915 + { 916 + } 917 + 918 + static void venc_cleanup(struct vpu_inst *inst) 919 + { 920 + struct venc_t *venc; 921 + 922 + if (!inst) 923 + return; 924 + 925 + venc = inst->priv; 926 + if (venc) 927 + vfree(venc); 928 + inst->priv = NULL; 929 + vfree(inst); 930 + } 931 + 932 + static int venc_start_session(struct vpu_inst *inst, u32 type) 933 + { 934 + struct venc_t *venc = inst->priv; 935 + int stream_buffer_size; 936 + int ret; 937 + 938 + venc_set_enable(venc, type, 1); 939 + if ((venc->enable & VENC_ENABLE_MASK) != VENC_ENABLE_MASK) 940 + return 0; 941 + 942 + vpu_iface_init_instance(inst); 943 + stream_buffer_size = vpu_iface_get_stream_buffer_size(inst->core); 944 + if (stream_buffer_size > 0) { 945 + inst->stream_buffer.length = max_t(u32, stream_buffer_size, venc->cpb_size * 3); 946 + ret = vpu_alloc_dma(inst->core, &inst->stream_buffer); 947 + if (ret) 948 + goto error; 949 + 950 + inst->use_stream_buffer = true; 951 + vpu_iface_config_stream_buffer(inst, &inst->stream_buffer); 952 + } 953 + 954 + ret = vpu_iface_set_encode_params(inst, &venc->params, 0); 955 + if (ret) 956 + goto error; 957 + ret = vpu_session_configure_codec(inst); 958 + if (ret) 959 + goto error; 960 + 961 + inst->state = VPU_CODEC_STATE_CONFIGURED; 962 + /*vpu_iface_config_memory_resource*/ 963 + 964 + /*config enc expert mode parameter*/ 965 + ret = vpu_iface_set_encode_params(inst, &venc->params, 1); 966 + if (ret) 967 + goto error; 968 + 969 + ret = vpu_session_start(inst); 970 + if (ret) 971 + goto error; 972 + inst->state = VPU_CODEC_STATE_STARTED; 973 + 974 + venc->bitrate_change = false; 975 + venc->input_ready = true; 976 + venc->frame_count = 0; 977 + venc->encode_count = 0; 978 + venc->ready_count = 0; 979 + venc->stopped = false; 980 + vpu_process_output_buffer(inst); 981 + if (venc->frame_count == 0) 982 + dev_err(inst->dev, "[%d] there is no input when starting\n", inst->id); 983 + 984 + return 0; 985 + error: 986 + venc_set_enable(venc, type, 0); 987 + inst->state = VPU_CODEC_STATE_DEINIT; 988 + 989 + vpu_free_dma(&inst->stream_buffer); 990 + return ret; 991 + } 992 + 993 + static void venc_cleanup_mem_resource(struct vpu_inst *inst) 994 + { 995 + struct venc_t *venc; 996 + u32 i; 997 + 998 + venc = inst->priv; 999 + 1000 + for (i = 0; i < ARRAY_SIZE(venc->enc); i++) 1001 + vpu_free_dma(&venc->enc[i]); 1002 + for (i = 0; i < ARRAY_SIZE(venc->ref); i++) 1003 + vpu_free_dma(&venc->ref[i]); 1004 + } 1005 + 1006 + static void venc_request_mem_resource(struct vpu_inst *inst, 1007 + u32 enc_frame_size, 1008 + u32 enc_frame_num, 1009 + u32 ref_frame_size, 1010 + u32 ref_frame_num, 1011 + u32 act_frame_size, 1012 + u32 act_frame_num) 1013 + { 1014 + struct venc_t *venc; 1015 + u32 i; 1016 + int ret; 1017 + 1018 + venc = inst->priv; 1019 + if (enc_frame_num > ARRAY_SIZE(venc->enc)) { 1020 + dev_err(inst->dev, "[%d] enc num(%d) is out of range\n", inst->id, enc_frame_num); 1021 + return; 1022 + } 1023 + if (ref_frame_num > ARRAY_SIZE(venc->ref)) { 1024 + dev_err(inst->dev, "[%d] ref num(%d) is out of range\n", inst->id, ref_frame_num); 1025 + return; 1026 + } 1027 + if (act_frame_num > ARRAY_SIZE(venc->act)) { 1028 + dev_err(inst->dev, "[%d] act num(%d) is out of range\n", inst->id, act_frame_num); 1029 + return; 1030 + } 1031 + 1032 + for (i = 0; i < enc_frame_num; i++) { 1033 + venc->enc[i].length = enc_frame_size; 1034 + ret = vpu_alloc_dma(inst->core, &venc->enc[i]); 1035 + if (ret) { 1036 + venc_cleanup_mem_resource(inst); 1037 + return; 1038 + } 1039 + } 1040 + for (i = 0; i < ref_frame_num; i++) { 1041 + venc->ref[i].length = ref_frame_size; 1042 + ret = vpu_alloc_dma(inst->core, &venc->ref[i]); 1043 + if (ret) { 1044 + venc_cleanup_mem_resource(inst); 1045 + return; 1046 + } 1047 + } 1048 + if (act_frame_num != 1 || act_frame_size > inst->act.length) { 1049 + venc_cleanup_mem_resource(inst); 1050 + return; 1051 + } 1052 + venc->act[0].length = act_frame_size; 1053 + venc->act[0].phys = inst->act.phys; 1054 + venc->act[0].virt = inst->act.virt; 1055 + 1056 + for (i = 0; i < enc_frame_num; i++) 1057 + vpu_iface_config_memory_resource(inst, MEM_RES_ENC, i, &venc->enc[i]); 1058 + for (i = 0; i < ref_frame_num; i++) 1059 + vpu_iface_config_memory_resource(inst, MEM_RES_REF, i, &venc->ref[i]); 1060 + for (i = 0; i < act_frame_num; i++) 1061 + vpu_iface_config_memory_resource(inst, MEM_RES_ACT, i, &venc->act[i]); 1062 + } 1063 + 1064 + static void venc_cleanup_frames(struct venc_t *venc) 1065 + { 1066 + struct venc_frame_t *frame; 1067 + struct venc_frame_t *tmp; 1068 + 1069 + list_for_each_entry_safe(frame, tmp, &venc->frames, list) { 1070 + list_del_init(&frame->list); 1071 + vfree(frame); 1072 + } 1073 + } 1074 + 1075 + static int venc_stop_session(struct vpu_inst *inst, u32 type) 1076 + { 1077 + struct venc_t *venc = inst->priv; 1078 + 1079 + venc_set_enable(venc, type, 0); 1080 + if (venc->enable & VENC_ENABLE_MASK) 1081 + return 0; 1082 + 1083 + if (inst->state == VPU_CODEC_STATE_DEINIT) 1084 + return 0; 1085 + 1086 + if (inst->state != VPU_CODEC_STATE_STOP) 1087 + venc_request_eos(inst); 1088 + 1089 + call_void_vop(inst, wait_prepare); 1090 + if (!wait_event_timeout(venc->wq, venc->stopped, VPU_TIMEOUT)) { 1091 + set_bit(inst->id, &inst->core->hang_mask); 1092 + vpu_session_debug(inst); 1093 + } 1094 + call_void_vop(inst, wait_finish); 1095 + 1096 + inst->state = VPU_CODEC_STATE_DEINIT; 1097 + venc_cleanup_frames(inst->priv); 1098 + vpu_free_dma(&inst->stream_buffer); 1099 + venc_cleanup_mem_resource(inst); 1100 + 1101 + return 0; 1102 + } 1103 + 1104 + static int venc_process_output(struct vpu_inst *inst, struct vb2_buffer *vb) 1105 + { 1106 + struct venc_t *venc = inst->priv; 1107 + struct vb2_v4l2_buffer *vbuf; 1108 + u32 flags; 1109 + 1110 + if (inst->state == VPU_CODEC_STATE_DEINIT) 1111 + return -EINVAL; 1112 + 1113 + vbuf = to_vb2_v4l2_buffer(vb); 1114 + if (inst->state == VPU_CODEC_STATE_STARTED) 1115 + inst->state = VPU_CODEC_STATE_ACTIVE; 1116 + 1117 + flags = vbuf->flags; 1118 + if (venc->request_key_frame) { 1119 + vbuf->flags |= V4L2_BUF_FLAG_KEYFRAME; 1120 + venc->request_key_frame = 0; 1121 + } 1122 + if (venc->bitrate_change) { 1123 + vpu_session_update_parameters(inst, &venc->params); 1124 + venc->bitrate_change = false; 1125 + } 1126 + dev_dbg(inst->dev, "[%d][INPUT TS]%32lld\n", inst->id, vb->timestamp); 1127 + vpu_iface_input_frame(inst, vb); 1128 + vbuf->flags = flags; 1129 + venc->input_ready = false; 1130 + venc->frame_count++; 1131 + vpu_set_buffer_state(vbuf, VPU_BUF_STATE_INUSE); 1132 + 1133 + return 0; 1134 + } 1135 + 1136 + static int venc_process_capture(struct vpu_inst *inst, struct vb2_buffer *vb) 1137 + { 1138 + struct venc_t *venc; 1139 + struct venc_frame_t *frame = NULL; 1140 + struct vb2_v4l2_buffer *vbuf; 1141 + int ret; 1142 + 1143 + venc = inst->priv; 1144 + if (list_empty(&venc->frames)) 1145 + return -EINVAL; 1146 + 1147 + frame = list_first_entry(&venc->frames, struct venc_frame_t, list); 1148 + vbuf = to_vb2_v4l2_buffer(vb); 1149 + v4l2_m2m_dst_buf_remove_by_buf(inst->fh.m2m_ctx, vbuf); 1150 + ret = venc_get_one_encoded_frame(inst, frame, vbuf); 1151 + if (ret) 1152 + return ret; 1153 + 1154 + list_del_init(&frame->list); 1155 + vfree(frame); 1156 + return 0; 1157 + } 1158 + 1159 + static void venc_on_queue_empty(struct vpu_inst *inst, u32 type) 1160 + { 1161 + struct venc_t *venc = inst->priv; 1162 + 1163 + if (V4L2_TYPE_IS_OUTPUT(type)) 1164 + return; 1165 + 1166 + if (venc->stopped) 1167 + venc_set_last_buffer_dequeued(inst); 1168 + } 1169 + 1170 + static int venc_get_debug_info(struct vpu_inst *inst, char *str, u32 size, u32 i) 1171 + { 1172 + struct venc_t *venc = inst->priv; 1173 + int num = -1; 1174 + 1175 + switch (i) { 1176 + case 0: 1177 + num = scnprintf(str, size, "profile = %d\n", venc->params.profile); 1178 + break; 1179 + case 1: 1180 + num = scnprintf(str, size, "level = %d\n", venc->params.level); 1181 + break; 1182 + case 2: 1183 + num = scnprintf(str, size, "fps = %d/%d\n", 1184 + venc->params.frame_rate.numerator, 1185 + venc->params.frame_rate.denominator); 1186 + break; 1187 + case 3: 1188 + num = scnprintf(str, size, "%d x %d -> %d x %d\n", 1189 + venc->params.src_width, 1190 + venc->params.src_height, 1191 + venc->params.out_width, 1192 + venc->params.out_height); 1193 + break; 1194 + case 4: 1195 + num = scnprintf(str, size, "(%d, %d) %d x %d\n", 1196 + venc->params.crop.left, 1197 + venc->params.crop.top, 1198 + venc->params.crop.width, 1199 + venc->params.crop.height); 1200 + break; 1201 + case 5: 1202 + num = scnprintf(str, size, 1203 + "enable = 0x%x, input = %d, encode = %d, ready = %d, stopped = %d\n", 1204 + venc->enable, 1205 + venc->frame_count, venc->encode_count, 1206 + venc->ready_count, 1207 + venc->stopped); 1208 + break; 1209 + case 6: 1210 + num = scnprintf(str, size, "gop = %d\n", venc->params.gop_length); 1211 + break; 1212 + case 7: 1213 + num = scnprintf(str, size, "bframes = %d\n", venc->params.bframes); 1214 + break; 1215 + case 8: 1216 + num = scnprintf(str, size, "rc: %s, mode = %d, bitrate = %d(%d), qp = %d\n", 1217 + venc->params.rc_enable ? "enable" : "disable", 1218 + venc->params.rc_mode, 1219 + venc->params.bitrate, 1220 + venc->params.bitrate_max, 1221 + venc->params.i_frame_qp); 1222 + break; 1223 + case 9: 1224 + num = scnprintf(str, size, "sar: enable = %d, idc = %d, %d x %d\n", 1225 + venc->params.sar.enable, 1226 + venc->params.sar.idc, 1227 + venc->params.sar.width, 1228 + venc->params.sar.height); 1229 + 1230 + break; 1231 + case 10: 1232 + num = scnprintf(str, size, 1233 + "colorspace: primaries = %d, transfer = %d, matrix = %d, full_range = %d\n", 1234 + venc->params.color.primaries, 1235 + venc->params.color.transfer, 1236 + venc->params.color.matrix, 1237 + venc->params.color.full_range); 1238 + break; 1239 + case 11: 1240 + num = scnprintf(str, size, "skipped: count = %d, bytes = %d\n", 1241 + venc->skipped_count, venc->skipped_bytes); 1242 + break; 1243 + default: 1244 + break; 1245 + } 1246 + 1247 + return num; 1248 + } 1249 + 1250 + static struct vpu_inst_ops venc_inst_ops = { 1251 + .ctrl_init = venc_ctrl_init, 1252 + .check_ready = venc_check_ready, 1253 + .input_done = venc_input_done, 1254 + .get_one_frame = venc_frame_encoded, 1255 + .buf_done = venc_buf_done, 1256 + .stop_done = venc_stop_done, 1257 + .event_notify = venc_event_notify, 1258 + .release = venc_release, 1259 + .cleanup = venc_cleanup, 1260 + .start = venc_start_session, 1261 + .mem_request = venc_request_mem_resource, 1262 + .stop = venc_stop_session, 1263 + .process_output = venc_process_output, 1264 + .process_capture = venc_process_capture, 1265 + .on_queue_empty = venc_on_queue_empty, 1266 + .get_debug_info = venc_get_debug_info, 1267 + .wait_prepare = vpu_inst_unlock, 1268 + .wait_finish = vpu_inst_lock, 1269 + }; 1270 + 1271 + static void venc_init(struct file *file) 1272 + { 1273 + struct vpu_inst *inst = to_inst(file); 1274 + struct venc_t *venc; 1275 + struct v4l2_format f; 1276 + struct v4l2_streamparm parm; 1277 + 1278 + venc = inst->priv; 1279 + venc->params.qp_min = 1; 1280 + venc->params.qp_max = 51; 1281 + venc->params.qp_min_i = 1; 1282 + venc->params.qp_max_i = 51; 1283 + venc->params.bitrate_min = BITRATE_MIN; 1284 + 1285 + memset(&f, 0, sizeof(f)); 1286 + f.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 1287 + f.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12M; 1288 + f.fmt.pix_mp.width = 1280; 1289 + f.fmt.pix_mp.height = 720; 1290 + f.fmt.pix_mp.field = V4L2_FIELD_NONE; 1291 + f.fmt.pix_mp.colorspace = V4L2_COLORSPACE_REC709; 1292 + venc_s_fmt(file, &inst->fh, &f); 1293 + 1294 + memset(&f, 0, sizeof(f)); 1295 + f.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 1296 + f.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_H264; 1297 + f.fmt.pix_mp.width = 1280; 1298 + f.fmt.pix_mp.height = 720; 1299 + f.fmt.pix_mp.field = V4L2_FIELD_NONE; 1300 + venc_s_fmt(file, &inst->fh, &f); 1301 + 1302 + memset(&parm, 0, sizeof(parm)); 1303 + parm.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 1304 + parm.parm.capture.timeperframe.numerator = 1; 1305 + parm.parm.capture.timeperframe.denominator = 30; 1306 + venc_s_parm(file, &inst->fh, &parm); 1307 + } 1308 + 1309 + static int venc_open(struct file *file) 1310 + { 1311 + struct vpu_inst *inst; 1312 + struct venc_t *venc; 1313 + int ret; 1314 + 1315 + inst = vzalloc(sizeof(*inst)); 1316 + if (!inst) 1317 + return -ENOMEM; 1318 + 1319 + venc = vzalloc(sizeof(*venc)); 1320 + if (!venc) { 1321 + vfree(inst); 1322 + return -ENOMEM; 1323 + } 1324 + 1325 + inst->ops = &venc_inst_ops; 1326 + inst->formats = venc_formats; 1327 + inst->type = VPU_CORE_TYPE_ENC; 1328 + inst->priv = venc; 1329 + INIT_LIST_HEAD(&venc->frames); 1330 + init_waitqueue_head(&venc->wq); 1331 + 1332 + ret = vpu_v4l2_open(file, inst); 1333 + if (ret) 1334 + return ret; 1335 + 1336 + venc_init(file); 1337 + 1338 + return 0; 1339 + } 1340 + 1341 + static const struct v4l2_file_operations venc_fops = { 1342 + .owner = THIS_MODULE, 1343 + .open = venc_open, 1344 + .release = vpu_v4l2_close, 1345 + .unlocked_ioctl = video_ioctl2, 1346 + .poll = v4l2_m2m_fop_poll, 1347 + .mmap = v4l2_m2m_fop_mmap, 1348 + }; 1349 + 1350 + const struct v4l2_ioctl_ops *venc_get_ioctl_ops(void) 1351 + { 1352 + return &venc_ioctl_ops; 1353 + } 1354 + 1355 + const struct v4l2_file_operations *venc_get_fops(void) 1356 + { 1357 + return &venc_fops; 1358 + }
+362
drivers/media/platform/amphion/vpu.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Copyright 2020-2021 NXP 4 + */ 5 + 6 + #ifndef _AMPHION_VPU_H 7 + #define _AMPHION_VPU_H 8 + 9 + #include <media/v4l2-device.h> 10 + #include <media/v4l2-ctrls.h> 11 + #include <media/v4l2-mem2mem.h> 12 + #include <linux/mailbox_client.h> 13 + #include <linux/mailbox_controller.h> 14 + #include <linux/kfifo.h> 15 + 16 + #define VPU_TIMEOUT msecs_to_jiffies(1000) 17 + #define VPU_INST_NULL_ID (-1L) 18 + #define VPU_MSG_BUFFER_SIZE (8192) 19 + 20 + enum imx_plat_type { 21 + IMX8QXP = 0, 22 + IMX8QM = 1, 23 + IMX8DM, 24 + IMX8DX, 25 + PLAT_TYPE_RESERVED 26 + }; 27 + 28 + enum vpu_core_type { 29 + VPU_CORE_TYPE_ENC = 0, 30 + VPU_CORE_TYPE_DEC = 0x10, 31 + }; 32 + 33 + struct vpu_dev; 34 + struct vpu_resources { 35 + enum imx_plat_type plat_type; 36 + u32 mreg_base; 37 + int (*setup)(struct vpu_dev *vpu); 38 + int (*setup_encoder)(struct vpu_dev *vpu); 39 + int (*setup_decoder)(struct vpu_dev *vpu); 40 + int (*reset)(struct vpu_dev *vpu); 41 + }; 42 + 43 + struct vpu_buffer { 44 + void *virt; 45 + dma_addr_t phys; 46 + u32 length; 47 + u32 bytesused; 48 + struct device *dev; 49 + }; 50 + 51 + struct vpu_func { 52 + struct video_device *vfd; 53 + struct v4l2_m2m_dev *m2m_dev; 54 + enum vpu_core_type type; 55 + int function; 56 + }; 57 + 58 + struct vpu_dev { 59 + void __iomem *base; 60 + struct platform_device *pdev; 61 + struct device *dev; 62 + struct mutex lock; /* protect vpu device */ 63 + const struct vpu_resources *res; 64 + struct list_head cores; 65 + 66 + struct v4l2_device v4l2_dev; 67 + struct vpu_func encoder; 68 + struct vpu_func decoder; 69 + struct media_device mdev; 70 + 71 + struct delayed_work watchdog_work; 72 + void (*get_vpu)(struct vpu_dev *vpu); 73 + void (*put_vpu)(struct vpu_dev *vpu); 74 + void (*get_enc)(struct vpu_dev *vpu); 75 + void (*put_enc)(struct vpu_dev *vpu); 76 + void (*get_dec)(struct vpu_dev *vpu); 77 + void (*put_dec)(struct vpu_dev *vpu); 78 + atomic_t ref_vpu; 79 + atomic_t ref_enc; 80 + atomic_t ref_dec; 81 + 82 + struct dentry *debugfs; 83 + }; 84 + 85 + struct vpu_format { 86 + u32 pixfmt; 87 + unsigned int num_planes; 88 + u32 type; 89 + u32 flags; 90 + u32 width; 91 + u32 height; 92 + u32 sizeimage[VIDEO_MAX_PLANES]; 93 + u32 bytesperline[VIDEO_MAX_PLANES]; 94 + u32 field; 95 + }; 96 + 97 + struct vpu_core_resources { 98 + enum vpu_core_type type; 99 + const char *fwname; 100 + u32 stride; 101 + u32 max_width; 102 + u32 min_width; 103 + u32 step_width; 104 + u32 max_height; 105 + u32 min_height; 106 + u32 step_height; 107 + u32 rpc_size; 108 + u32 fwlog_size; 109 + u32 act_size; 110 + }; 111 + 112 + struct vpu_mbox { 113 + char name[20]; 114 + struct mbox_client cl; 115 + struct mbox_chan *ch; 116 + bool block; 117 + }; 118 + 119 + enum vpu_core_state { 120 + VPU_CORE_DEINIT = 0, 121 + VPU_CORE_ACTIVE, 122 + VPU_CORE_SNAPSHOT, 123 + VPU_CORE_HANG 124 + }; 125 + 126 + struct vpu_core { 127 + void __iomem *base; 128 + struct platform_device *pdev; 129 + struct device *dev; 130 + struct device *parent; 131 + struct device *pd; 132 + struct device_link *pd_link; 133 + struct mutex lock; /* protect vpu core */ 134 + struct mutex cmd_lock; /* Lock vpu command */ 135 + struct list_head list; 136 + enum vpu_core_type type; 137 + int id; 138 + const struct vpu_core_resources *res; 139 + unsigned long instance_mask; 140 + u32 supported_instance_count; 141 + unsigned long hang_mask; 142 + u32 request_count; 143 + struct list_head instances; 144 + enum vpu_core_state state; 145 + u32 fw_version; 146 + 147 + struct vpu_buffer fw; 148 + struct vpu_buffer rpc; 149 + struct vpu_buffer log; 150 + struct vpu_buffer act; 151 + 152 + struct vpu_mbox tx_type; 153 + struct vpu_mbox tx_data; 154 + struct vpu_mbox rx; 155 + unsigned long cmd_seq; 156 + 157 + wait_queue_head_t ack_wq; 158 + struct completion cmp; 159 + struct workqueue_struct *workqueue; 160 + struct work_struct msg_work; 161 + struct delayed_work msg_delayed_work; 162 + struct kfifo msg_fifo; 163 + void *msg_buffer; 164 + unsigned int msg_buffer_size; 165 + 166 + struct vpu_dev *vpu; 167 + void *iface; 168 + 169 + struct dentry *debugfs; 170 + struct dentry *debugfs_fwlog; 171 + }; 172 + 173 + enum vpu_codec_state { 174 + VPU_CODEC_STATE_DEINIT = 1, 175 + VPU_CODEC_STATE_CONFIGURED, 176 + VPU_CODEC_STATE_START, 177 + VPU_CODEC_STATE_STARTED, 178 + VPU_CODEC_STATE_ACTIVE, 179 + VPU_CODEC_STATE_SEEK, 180 + VPU_CODEC_STATE_STOP, 181 + VPU_CODEC_STATE_DRAIN, 182 + VPU_CODEC_STATE_DYAMIC_RESOLUTION_CHANGE, 183 + }; 184 + 185 + struct vpu_frame_info { 186 + u32 type; 187 + u32 id; 188 + u32 sequence; 189 + u32 luma; 190 + u32 chroma_u; 191 + u32 chroma_v; 192 + u32 data_offset; 193 + u32 flags; 194 + u32 skipped; 195 + s64 timestamp; 196 + }; 197 + 198 + struct vpu_inst; 199 + struct vpu_inst_ops { 200 + int (*ctrl_init)(struct vpu_inst *inst); 201 + int (*start)(struct vpu_inst *inst, u32 type); 202 + int (*stop)(struct vpu_inst *inst, u32 type); 203 + int (*abort)(struct vpu_inst *inst); 204 + bool (*check_ready)(struct vpu_inst *inst, unsigned int type); 205 + void (*buf_done)(struct vpu_inst *inst, struct vpu_frame_info *frame); 206 + void (*event_notify)(struct vpu_inst *inst, u32 event, void *data); 207 + void (*release)(struct vpu_inst *inst); 208 + void (*cleanup)(struct vpu_inst *inst); 209 + void (*mem_request)(struct vpu_inst *inst, 210 + u32 enc_frame_size, 211 + u32 enc_frame_num, 212 + u32 ref_frame_size, 213 + u32 ref_frame_num, 214 + u32 act_frame_size, 215 + u32 act_frame_num); 216 + void (*input_done)(struct vpu_inst *inst); 217 + void (*stop_done)(struct vpu_inst *inst); 218 + int (*process_output)(struct vpu_inst *inst, struct vb2_buffer *vb); 219 + int (*process_capture)(struct vpu_inst *inst, struct vb2_buffer *vb); 220 + int (*get_one_frame)(struct vpu_inst *inst, void *info); 221 + void (*on_queue_empty)(struct vpu_inst *inst, u32 type); 222 + int (*get_debug_info)(struct vpu_inst *inst, char *str, u32 size, u32 i); 223 + void (*wait_prepare)(struct vpu_inst *inst); 224 + void (*wait_finish)(struct vpu_inst *inst); 225 + }; 226 + 227 + struct vpu_inst { 228 + struct list_head list; 229 + struct mutex lock; /* v4l2 and videobuf2 lock */ 230 + struct vpu_dev *vpu; 231 + struct vpu_core *core; 232 + struct device *dev; 233 + int id; 234 + 235 + struct v4l2_fh fh; 236 + struct v4l2_ctrl_handler ctrl_handler; 237 + atomic_t ref_count; 238 + int (*release)(struct vpu_inst *inst); 239 + 240 + enum vpu_codec_state state; 241 + enum vpu_core_type type; 242 + 243 + struct workqueue_struct *workqueue; 244 + struct work_struct msg_work; 245 + struct kfifo msg_fifo; 246 + u8 msg_buffer[VPU_MSG_BUFFER_SIZE]; 247 + 248 + struct vpu_buffer stream_buffer; 249 + bool use_stream_buffer; 250 + struct vpu_buffer act; 251 + 252 + struct list_head cmd_q; 253 + void *pending; 254 + 255 + struct vpu_inst_ops *ops; 256 + const struct vpu_format *formats; 257 + struct vpu_format out_format; 258 + struct vpu_format cap_format; 259 + u32 min_buffer_cap; 260 + u32 min_buffer_out; 261 + 262 + struct v4l2_rect crop; 263 + u32 colorspace; 264 + u8 ycbcr_enc; 265 + u8 quantization; 266 + u8 xfer_func; 267 + u32 sequence; 268 + u32 extra_size; 269 + 270 + u32 flows[16]; 271 + u32 flow_idx; 272 + 273 + pid_t pid; 274 + pid_t tgid; 275 + struct dentry *debugfs; 276 + 277 + void *priv; 278 + }; 279 + 280 + #define call_vop(inst, op, args...) \ 281 + ((inst)->ops->op ? (inst)->ops->op(inst, ##args) : 0) \ 282 + 283 + #define call_void_vop(inst, op, args...) \ 284 + do { \ 285 + if ((inst)->ops->op) \ 286 + (inst)->ops->op(inst, ##args); \ 287 + } while (0) 288 + 289 + enum { 290 + VPU_BUF_STATE_IDLE = 0, 291 + VPU_BUF_STATE_INUSE, 292 + VPU_BUF_STATE_DECODED, 293 + VPU_BUF_STATE_READY, 294 + VPU_BUF_STATE_SKIP, 295 + VPU_BUF_STATE_ERROR 296 + }; 297 + 298 + struct vpu_vb2_buffer { 299 + struct v4l2_m2m_buffer m2m_buf; 300 + dma_addr_t luma; 301 + dma_addr_t chroma_u; 302 + dma_addr_t chroma_v; 303 + unsigned int state; 304 + u32 tag; 305 + }; 306 + 307 + void vpu_writel(struct vpu_dev *vpu, u32 reg, u32 val); 308 + u32 vpu_readl(struct vpu_dev *vpu, u32 reg); 309 + 310 + static inline struct vpu_vb2_buffer *to_vpu_vb2_buffer(struct vb2_v4l2_buffer *vbuf) 311 + { 312 + struct v4l2_m2m_buffer *m2m_buf = container_of(vbuf, struct v4l2_m2m_buffer, vb); 313 + 314 + return container_of(m2m_buf, struct vpu_vb2_buffer, m2m_buf); 315 + } 316 + 317 + static inline const char *vpu_core_type_desc(enum vpu_core_type type) 318 + { 319 + return type == VPU_CORE_TYPE_ENC ? "encoder" : "decoder"; 320 + } 321 + 322 + static inline struct vpu_inst *to_inst(struct file *filp) 323 + { 324 + return container_of(filp->private_data, struct vpu_inst, fh); 325 + } 326 + 327 + #define ctrl_to_inst(ctrl) \ 328 + container_of((ctrl)->handler, struct vpu_inst, ctrl_handler) 329 + 330 + const struct v4l2_ioctl_ops *venc_get_ioctl_ops(void); 331 + const struct v4l2_file_operations *venc_get_fops(void); 332 + const struct v4l2_ioctl_ops *vdec_get_ioctl_ops(void); 333 + const struct v4l2_file_operations *vdec_get_fops(void); 334 + 335 + int vpu_add_func(struct vpu_dev *vpu, struct vpu_func *func); 336 + void vpu_remove_func(struct vpu_func *func); 337 + 338 + struct vpu_inst *vpu_inst_get(struct vpu_inst *inst); 339 + void vpu_inst_put(struct vpu_inst *inst); 340 + struct vpu_core *vpu_request_core(struct vpu_dev *vpu, enum vpu_core_type type); 341 + void vpu_release_core(struct vpu_core *core); 342 + int vpu_inst_register(struct vpu_inst *inst); 343 + int vpu_inst_unregister(struct vpu_inst *inst); 344 + const struct vpu_core_resources *vpu_get_resource(struct vpu_inst *inst); 345 + 346 + int vpu_inst_create_dbgfs_file(struct vpu_inst *inst); 347 + int vpu_inst_remove_dbgfs_file(struct vpu_inst *inst); 348 + int vpu_core_create_dbgfs_file(struct vpu_core *core); 349 + int vpu_core_remove_dbgfs_file(struct vpu_core *core); 350 + void vpu_inst_record_flow(struct vpu_inst *inst, u32 flow); 351 + 352 + int vpu_core_driver_init(void); 353 + void vpu_core_driver_exit(void); 354 + 355 + extern bool debug; 356 + #define vpu_trace(dev, fmt, arg...) \ 357 + do { \ 358 + if (debug) \ 359 + dev_info(dev, "%s: " fmt, __func__, ## arg); \ 360 + } while (0) 361 + 362 + #endif
+433
drivers/media/platform/amphion/vpu_cmds.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright 2020-2021 NXP 4 + */ 5 + 6 + #include <linux/init.h> 7 + #include <linux/interconnect.h> 8 + #include <linux/ioctl.h> 9 + #include <linux/list.h> 10 + #include <linux/kernel.h> 11 + #include <linux/module.h> 12 + #include <linux/of_device.h> 13 + #include <linux/of_address.h> 14 + #include <linux/platform_device.h> 15 + #include <linux/slab.h> 16 + #include <linux/types.h> 17 + #include <linux/delay.h> 18 + #include <linux/vmalloc.h> 19 + #include "vpu.h" 20 + #include "vpu_defs.h" 21 + #include "vpu_cmds.h" 22 + #include "vpu_rpc.h" 23 + #include "vpu_mbox.h" 24 + 25 + struct vpu_cmd_request { 26 + u32 request; 27 + u32 response; 28 + u32 handled; 29 + }; 30 + 31 + struct vpu_cmd_t { 32 + struct list_head list; 33 + u32 id; 34 + struct vpu_cmd_request *request; 35 + struct vpu_rpc_event *pkt; 36 + unsigned long key; 37 + }; 38 + 39 + static struct vpu_cmd_request vpu_cmd_requests[] = { 40 + { 41 + .request = VPU_CMD_ID_CONFIGURE_CODEC, 42 + .response = VPU_MSG_ID_MEM_REQUEST, 43 + .handled = 1, 44 + }, 45 + { 46 + .request = VPU_CMD_ID_START, 47 + .response = VPU_MSG_ID_START_DONE, 48 + .handled = 0, 49 + }, 50 + { 51 + .request = VPU_CMD_ID_STOP, 52 + .response = VPU_MSG_ID_STOP_DONE, 53 + .handled = 0, 54 + }, 55 + { 56 + .request = VPU_CMD_ID_ABORT, 57 + .response = VPU_MSG_ID_ABORT_DONE, 58 + .handled = 0, 59 + }, 60 + { 61 + .request = VPU_CMD_ID_RST_BUF, 62 + .response = VPU_MSG_ID_BUF_RST, 63 + .handled = 1, 64 + }, 65 + }; 66 + 67 + static int vpu_cmd_send(struct vpu_core *core, struct vpu_rpc_event *pkt) 68 + { 69 + int ret = 0; 70 + 71 + ret = vpu_iface_send_cmd(core, pkt); 72 + if (ret) 73 + return ret; 74 + 75 + /*write cmd data to cmd buffer before trigger a cmd interrupt*/ 76 + mb(); 77 + vpu_mbox_send_type(core, COMMAND); 78 + 79 + return ret; 80 + } 81 + 82 + static struct vpu_cmd_t *vpu_alloc_cmd(struct vpu_inst *inst, u32 id, void *data) 83 + { 84 + struct vpu_cmd_t *cmd; 85 + int i; 86 + int ret; 87 + 88 + cmd = vzalloc(sizeof(*cmd)); 89 + if (!cmd) 90 + return NULL; 91 + 92 + cmd->pkt = vzalloc(sizeof(*cmd->pkt)); 93 + if (!cmd->pkt) { 94 + vfree(cmd); 95 + return NULL; 96 + } 97 + 98 + cmd->id = id; 99 + ret = vpu_iface_pack_cmd(inst->core, cmd->pkt, inst->id, id, data); 100 + if (ret) { 101 + dev_err(inst->dev, "iface pack cmd(%d) fail\n", id); 102 + vfree(cmd->pkt); 103 + vfree(cmd); 104 + return NULL; 105 + } 106 + for (i = 0; i < ARRAY_SIZE(vpu_cmd_requests); i++) { 107 + if (vpu_cmd_requests[i].request == id) { 108 + cmd->request = &vpu_cmd_requests[i]; 109 + break; 110 + } 111 + } 112 + 113 + return cmd; 114 + } 115 + 116 + static void vpu_free_cmd(struct vpu_cmd_t *cmd) 117 + { 118 + if (!cmd) 119 + return; 120 + if (cmd->pkt) 121 + vfree(cmd->pkt); 122 + vfree(cmd); 123 + } 124 + 125 + static int vpu_session_process_cmd(struct vpu_inst *inst, struct vpu_cmd_t *cmd) 126 + { 127 + int ret; 128 + 129 + dev_dbg(inst->dev, "[%d]send cmd(0x%x)\n", inst->id, cmd->id); 130 + vpu_iface_pre_send_cmd(inst); 131 + ret = vpu_cmd_send(inst->core, cmd->pkt); 132 + if (!ret) { 133 + vpu_iface_post_send_cmd(inst); 134 + vpu_inst_record_flow(inst, cmd->id); 135 + } else { 136 + dev_err(inst->dev, "[%d] iface send cmd(0x%x) fail\n", inst->id, cmd->id); 137 + } 138 + 139 + return ret; 140 + } 141 + 142 + static void vpu_process_cmd_request(struct vpu_inst *inst) 143 + { 144 + struct vpu_cmd_t *cmd; 145 + struct vpu_cmd_t *tmp; 146 + 147 + if (!inst || inst->pending) 148 + return; 149 + 150 + list_for_each_entry_safe(cmd, tmp, &inst->cmd_q, list) { 151 + list_del_init(&cmd->list); 152 + if (vpu_session_process_cmd(inst, cmd)) 153 + dev_err(inst->dev, "[%d] process cmd(%d) fail\n", inst->id, cmd->id); 154 + if (cmd->request) { 155 + inst->pending = (void *)cmd; 156 + break; 157 + } 158 + vpu_free_cmd(cmd); 159 + } 160 + } 161 + 162 + static int vpu_request_cmd(struct vpu_inst *inst, u32 id, void *data, 163 + unsigned long *key, int *sync) 164 + { 165 + struct vpu_core *core; 166 + struct vpu_cmd_t *cmd; 167 + 168 + if (!inst || !inst->core) 169 + return -EINVAL; 170 + 171 + core = inst->core; 172 + cmd = vpu_alloc_cmd(inst, id, data); 173 + if (!cmd) 174 + return -ENOMEM; 175 + 176 + mutex_lock(&core->cmd_lock); 177 + cmd->key = core->cmd_seq++; 178 + if (key) 179 + *key = cmd->key; 180 + if (sync) 181 + *sync = cmd->request ? true : false; 182 + list_add_tail(&cmd->list, &inst->cmd_q); 183 + vpu_process_cmd_request(inst); 184 + mutex_unlock(&core->cmd_lock); 185 + 186 + return 0; 187 + } 188 + 189 + static void vpu_clear_pending(struct vpu_inst *inst) 190 + { 191 + if (!inst || !inst->pending) 192 + return; 193 + 194 + vpu_free_cmd(inst->pending); 195 + wake_up_all(&inst->core->ack_wq); 196 + inst->pending = NULL; 197 + } 198 + 199 + static bool vpu_check_response(struct vpu_cmd_t *cmd, u32 response, u32 handled) 200 + { 201 + struct vpu_cmd_request *request; 202 + 203 + if (!cmd || !cmd->request) 204 + return false; 205 + 206 + request = cmd->request; 207 + if (request->response != response) 208 + return false; 209 + if (request->handled != handled) 210 + return false; 211 + 212 + return true; 213 + } 214 + 215 + int vpu_response_cmd(struct vpu_inst *inst, u32 response, u32 handled) 216 + { 217 + struct vpu_core *core; 218 + 219 + if (!inst || !inst->core) 220 + return -EINVAL; 221 + 222 + core = inst->core; 223 + mutex_lock(&core->cmd_lock); 224 + if (vpu_check_response(inst->pending, response, handled)) 225 + vpu_clear_pending(inst); 226 + 227 + vpu_process_cmd_request(inst); 228 + mutex_unlock(&core->cmd_lock); 229 + 230 + return 0; 231 + } 232 + 233 + void vpu_clear_request(struct vpu_inst *inst) 234 + { 235 + struct vpu_cmd_t *cmd; 236 + struct vpu_cmd_t *tmp; 237 + 238 + mutex_lock(&inst->core->cmd_lock); 239 + if (inst->pending) 240 + vpu_clear_pending(inst); 241 + 242 + list_for_each_entry_safe(cmd, tmp, &inst->cmd_q, list) { 243 + list_del_init(&cmd->list); 244 + vpu_free_cmd(cmd); 245 + } 246 + mutex_unlock(&inst->core->cmd_lock); 247 + } 248 + 249 + static bool check_is_responsed(struct vpu_inst *inst, unsigned long key) 250 + { 251 + struct vpu_core *core = inst->core; 252 + struct vpu_cmd_t *cmd; 253 + bool flag = true; 254 + 255 + mutex_lock(&core->cmd_lock); 256 + cmd = inst->pending; 257 + if (cmd && key == cmd->key) { 258 + flag = false; 259 + goto exit; 260 + } 261 + list_for_each_entry(cmd, &inst->cmd_q, list) { 262 + if (key == cmd->key) { 263 + flag = false; 264 + break; 265 + } 266 + } 267 + exit: 268 + mutex_unlock(&core->cmd_lock); 269 + 270 + return flag; 271 + } 272 + 273 + static int sync_session_response(struct vpu_inst *inst, unsigned long key) 274 + { 275 + struct vpu_core *core; 276 + 277 + if (!inst || !inst->core) 278 + return -EINVAL; 279 + 280 + core = inst->core; 281 + 282 + call_void_vop(inst, wait_prepare); 283 + wait_event_timeout(core->ack_wq, check_is_responsed(inst, key), VPU_TIMEOUT); 284 + call_void_vop(inst, wait_finish); 285 + 286 + if (!check_is_responsed(inst, key)) { 287 + dev_err(inst->dev, "[%d] sync session timeout\n", inst->id); 288 + set_bit(inst->id, &core->hang_mask); 289 + mutex_lock(&inst->core->cmd_lock); 290 + vpu_clear_pending(inst); 291 + mutex_unlock(&inst->core->cmd_lock); 292 + return -EINVAL; 293 + } 294 + 295 + return 0; 296 + } 297 + 298 + static int vpu_session_send_cmd(struct vpu_inst *inst, u32 id, void *data) 299 + { 300 + unsigned long key; 301 + int sync = false; 302 + int ret = -EINVAL; 303 + 304 + if (inst->id < 0) 305 + return -EINVAL; 306 + 307 + ret = vpu_request_cmd(inst, id, data, &key, &sync); 308 + if (!ret && sync) 309 + ret = sync_session_response(inst, key); 310 + 311 + if (ret) 312 + dev_err(inst->dev, "[%d] send cmd(0x%x) fail\n", inst->id, id); 313 + 314 + return ret; 315 + } 316 + 317 + int vpu_session_configure_codec(struct vpu_inst *inst) 318 + { 319 + return vpu_session_send_cmd(inst, VPU_CMD_ID_CONFIGURE_CODEC, NULL); 320 + } 321 + 322 + int vpu_session_start(struct vpu_inst *inst) 323 + { 324 + vpu_trace(inst->dev, "[%d]\n", inst->id); 325 + 326 + return vpu_session_send_cmd(inst, VPU_CMD_ID_START, NULL); 327 + } 328 + 329 + int vpu_session_stop(struct vpu_inst *inst) 330 + { 331 + int ret; 332 + 333 + vpu_trace(inst->dev, "[%d]\n", inst->id); 334 + 335 + ret = vpu_session_send_cmd(inst, VPU_CMD_ID_STOP, NULL); 336 + /* workaround for a firmware bug, 337 + * if the next command is too close after stop cmd, 338 + * the firmware may enter wfi wrongly. 339 + */ 340 + usleep_range(3000, 5000); 341 + return ret; 342 + } 343 + 344 + int vpu_session_encode_frame(struct vpu_inst *inst, s64 timestamp) 345 + { 346 + return vpu_session_send_cmd(inst, VPU_CMD_ID_FRAME_ENCODE, &timestamp); 347 + } 348 + 349 + int vpu_session_alloc_fs(struct vpu_inst *inst, struct vpu_fs_info *fs) 350 + { 351 + return vpu_session_send_cmd(inst, VPU_CMD_ID_FS_ALLOC, fs); 352 + } 353 + 354 + int vpu_session_release_fs(struct vpu_inst *inst, struct vpu_fs_info *fs) 355 + { 356 + return vpu_session_send_cmd(inst, VPU_CMD_ID_FS_RELEASE, fs); 357 + } 358 + 359 + int vpu_session_abort(struct vpu_inst *inst) 360 + { 361 + return vpu_session_send_cmd(inst, VPU_CMD_ID_ABORT, NULL); 362 + } 363 + 364 + int vpu_session_rst_buf(struct vpu_inst *inst) 365 + { 366 + return vpu_session_send_cmd(inst, VPU_CMD_ID_RST_BUF, NULL); 367 + } 368 + 369 + int vpu_session_fill_timestamp(struct vpu_inst *inst, struct vpu_ts_info *info) 370 + { 371 + return vpu_session_send_cmd(inst, VPU_CMD_ID_TIMESTAMP, info); 372 + } 373 + 374 + int vpu_session_update_parameters(struct vpu_inst *inst, void *arg) 375 + { 376 + if (inst->type & VPU_CORE_TYPE_DEC) 377 + vpu_iface_set_decode_params(inst, arg, 1); 378 + else 379 + vpu_iface_set_encode_params(inst, arg, 1); 380 + 381 + return vpu_session_send_cmd(inst, VPU_CMD_ID_UPDATE_PARAMETER, arg); 382 + } 383 + 384 + int vpu_session_debug(struct vpu_inst *inst) 385 + { 386 + return vpu_session_send_cmd(inst, VPU_CMD_ID_DEBUG, NULL); 387 + } 388 + 389 + int vpu_core_snapshot(struct vpu_core *core) 390 + { 391 + struct vpu_inst *inst; 392 + int ret; 393 + 394 + if (!core || list_empty(&core->instances)) 395 + return 0; 396 + 397 + inst = list_first_entry(&core->instances, struct vpu_inst, list); 398 + 399 + reinit_completion(&core->cmp); 400 + ret = vpu_session_send_cmd(inst, VPU_CMD_ID_SNAPSHOT, NULL); 401 + if (ret) 402 + return ret; 403 + ret = wait_for_completion_timeout(&core->cmp, VPU_TIMEOUT); 404 + if (!ret) { 405 + dev_err(core->dev, "snapshot timeout\n"); 406 + return -EINVAL; 407 + } 408 + 409 + return 0; 410 + } 411 + 412 + int vpu_core_sw_reset(struct vpu_core *core) 413 + { 414 + struct vpu_rpc_event pkt; 415 + int ret; 416 + 417 + memset(&pkt, 0, sizeof(pkt)); 418 + vpu_iface_pack_cmd(core, &pkt, 0, VPU_CMD_ID_FIRM_RESET, NULL); 419 + 420 + reinit_completion(&core->cmp); 421 + mutex_lock(&core->cmd_lock); 422 + ret = vpu_cmd_send(core, &pkt); 423 + mutex_unlock(&core->cmd_lock); 424 + if (ret) 425 + return ret; 426 + ret = wait_for_completion_timeout(&core->cmp, VPU_TIMEOUT); 427 + if (!ret) { 428 + dev_err(core->dev, "sw reset timeout\n"); 429 + return -EINVAL; 430 + } 431 + 432 + return 0; 433 + }
+25
drivers/media/platform/amphion/vpu_cmds.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Copyright 2020-2021 NXP 4 + */ 5 + 6 + #ifndef _AMPHION_VPU_CMDS_H 7 + #define _AMPHION_VPU_CMDS_H 8 + 9 + int vpu_session_configure_codec(struct vpu_inst *inst); 10 + int vpu_session_start(struct vpu_inst *inst); 11 + int vpu_session_stop(struct vpu_inst *inst); 12 + int vpu_session_abort(struct vpu_inst *inst); 13 + int vpu_session_rst_buf(struct vpu_inst *inst); 14 + int vpu_session_encode_frame(struct vpu_inst *inst, s64 timestamp); 15 + int vpu_session_alloc_fs(struct vpu_inst *inst, struct vpu_fs_info *fs); 16 + int vpu_session_release_fs(struct vpu_inst *inst, struct vpu_fs_info *fs); 17 + int vpu_session_fill_timestamp(struct vpu_inst *inst, struct vpu_ts_info *info); 18 + int vpu_session_update_parameters(struct vpu_inst *inst, void *arg); 19 + int vpu_core_snapshot(struct vpu_core *core); 20 + int vpu_core_sw_reset(struct vpu_core *core); 21 + int vpu_response_cmd(struct vpu_inst *inst, u32 response, u32 handled); 22 + void vpu_clear_request(struct vpu_inst *inst); 23 + int vpu_session_debug(struct vpu_inst *inst); 24 + 25 + #endif
+68
drivers/media/platform/amphion/vpu_codec.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Copyright 2020-2021 NXP 4 + */ 5 + 6 + #ifndef _AMPHION_VPU_CODEC_H 7 + #define _AMPHION_VPU_CODEC_H 8 + 9 + struct vpu_encode_params { 10 + u32 input_format; 11 + u32 codec_format; 12 + u32 profile; 13 + u32 tier; 14 + u32 level; 15 + struct v4l2_fract frame_rate; 16 + u32 src_stride; 17 + u32 src_width; 18 + u32 src_height; 19 + struct v4l2_rect crop; 20 + u32 out_width; 21 + u32 out_height; 22 + 23 + u32 gop_length; 24 + u32 bframes; 25 + 26 + u32 rc_enable; 27 + u32 rc_mode; 28 + u32 bitrate; 29 + u32 bitrate_min; 30 + u32 bitrate_max; 31 + 32 + u32 i_frame_qp; 33 + u32 p_frame_qp; 34 + u32 b_frame_qp; 35 + u32 qp_min; 36 + u32 qp_max; 37 + u32 qp_min_i; 38 + u32 qp_max_i; 39 + 40 + struct { 41 + u32 enable; 42 + u32 idc; 43 + u32 width; 44 + u32 height; 45 + } sar; 46 + 47 + struct { 48 + u32 primaries; 49 + u32 transfer; 50 + u32 matrix; 51 + u32 full_range; 52 + } color; 53 + }; 54 + 55 + struct vpu_decode_params { 56 + u32 codec_format; 57 + u32 output_format; 58 + u32 b_dis_reorder; 59 + u32 b_non_frame; 60 + u32 frame_count; 61 + u32 end_flag; 62 + struct { 63 + u32 base; 64 + u32 size; 65 + } udata; 66 + }; 67 + 68 + #endif
+183
drivers/media/platform/amphion/vpu_color.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright 2020-2021 NXP 4 + */ 5 + 6 + #include <linux/init.h> 7 + #include <linux/device.h> 8 + #include <linux/ioctl.h> 9 + #include <linux/list.h> 10 + #include <linux/module.h> 11 + #include <linux/kernel.h> 12 + #include <linux/slab.h> 13 + #include <linux/delay.h> 14 + #include <linux/types.h> 15 + #include <media/v4l2-device.h> 16 + #include "vpu.h" 17 + #include "vpu_helpers.h" 18 + 19 + static const u8 colorprimaries[] = { 20 + 0, 21 + V4L2_COLORSPACE_REC709, /*Rec. ITU-R BT.709-6*/ 22 + 0, 23 + 0, 24 + V4L2_COLORSPACE_470_SYSTEM_M, /*Rec. ITU-R BT.470-6 System M*/ 25 + V4L2_COLORSPACE_470_SYSTEM_BG, /*Rec. ITU-R BT.470-6 System B, G*/ 26 + V4L2_COLORSPACE_SMPTE170M, /*SMPTE170M*/ 27 + V4L2_COLORSPACE_SMPTE240M, /*SMPTE240M*/ 28 + 0, /*Generic film*/ 29 + V4L2_COLORSPACE_BT2020, /*Rec. ITU-R BT.2020-2*/ 30 + 0, /*SMPTE ST 428-1*/ 31 + }; 32 + 33 + static const u8 colortransfers[] = { 34 + 0, 35 + V4L2_XFER_FUNC_709, /*Rec. ITU-R BT.709-6*/ 36 + 0, 37 + 0, 38 + 0, /*Rec. ITU-R BT.470-6 System M*/ 39 + 0, /*Rec. ITU-R BT.470-6 System B, G*/ 40 + V4L2_XFER_FUNC_709, /*SMPTE170M*/ 41 + V4L2_XFER_FUNC_SMPTE240M, /*SMPTE240M*/ 42 + V4L2_XFER_FUNC_NONE, /*Linear transfer characteristics*/ 43 + 0, 44 + 0, 45 + 0, /*IEC 61966-2-4*/ 46 + 0, /*Rec. ITU-R BT.1361-0 extended colour gamut*/ 47 + V4L2_XFER_FUNC_SRGB, /*IEC 61966-2-1 sRGB or sYCC*/ 48 + V4L2_XFER_FUNC_709, /*Rec. ITU-R BT.2020-2 (10 bit system)*/ 49 + V4L2_XFER_FUNC_709, /*Rec. ITU-R BT.2020-2 (12 bit system)*/ 50 + V4L2_XFER_FUNC_SMPTE2084, /*SMPTE ST 2084*/ 51 + 0, /*SMPTE ST 428-1*/ 52 + 0 /*Rec. ITU-R BT.2100-0 hybrid log-gamma (HLG)*/ 53 + }; 54 + 55 + static const u8 colormatrixcoefs[] = { 56 + 0, 57 + V4L2_YCBCR_ENC_709, /*Rec. ITU-R BT.709-6*/ 58 + 0, 59 + 0, 60 + 0, /*Title 47 Code of Federal Regulations*/ 61 + V4L2_YCBCR_ENC_601, /*Rec. ITU-R BT.601-7 625*/ 62 + V4L2_YCBCR_ENC_601, /*Rec. ITU-R BT.601-7 525*/ 63 + V4L2_YCBCR_ENC_SMPTE240M, /*SMPTE240M*/ 64 + 0, 65 + V4L2_YCBCR_ENC_BT2020, /*Rec. ITU-R BT.2020-2*/ 66 + V4L2_YCBCR_ENC_BT2020_CONST_LUM /*Rec. ITU-R BT.2020-2 constant*/ 67 + }; 68 + 69 + u32 vpu_color_cvrt_primaries_v2i(u32 primaries) 70 + { 71 + return vpu_helper_find_in_array_u8(colorprimaries, ARRAY_SIZE(colorprimaries), primaries); 72 + } 73 + 74 + u32 vpu_color_cvrt_primaries_i2v(u32 primaries) 75 + { 76 + return primaries < ARRAY_SIZE(colorprimaries) ? colorprimaries[primaries] : 0; 77 + } 78 + 79 + u32 vpu_color_cvrt_transfers_v2i(u32 transfers) 80 + { 81 + return vpu_helper_find_in_array_u8(colortransfers, ARRAY_SIZE(colortransfers), transfers); 82 + } 83 + 84 + u32 vpu_color_cvrt_transfers_i2v(u32 transfers) 85 + { 86 + return transfers < ARRAY_SIZE(colortransfers) ? colortransfers[transfers] : 0; 87 + } 88 + 89 + u32 vpu_color_cvrt_matrix_v2i(u32 matrix) 90 + { 91 + return vpu_helper_find_in_array_u8(colormatrixcoefs, ARRAY_SIZE(colormatrixcoefs), matrix); 92 + } 93 + 94 + u32 vpu_color_cvrt_matrix_i2v(u32 matrix) 95 + { 96 + return matrix < ARRAY_SIZE(colormatrixcoefs) ? colormatrixcoefs[matrix] : 0; 97 + } 98 + 99 + u32 vpu_color_cvrt_full_range_v2i(u32 full_range) 100 + { 101 + return (full_range == V4L2_QUANTIZATION_FULL_RANGE); 102 + } 103 + 104 + u32 vpu_color_cvrt_full_range_i2v(u32 full_range) 105 + { 106 + if (full_range) 107 + return V4L2_QUANTIZATION_FULL_RANGE; 108 + 109 + return V4L2_QUANTIZATION_LIM_RANGE; 110 + } 111 + 112 + int vpu_color_check_primaries(u32 primaries) 113 + { 114 + return vpu_color_cvrt_primaries_v2i(primaries) ? 0 : -EINVAL; 115 + } 116 + 117 + int vpu_color_check_transfers(u32 transfers) 118 + { 119 + return vpu_color_cvrt_transfers_v2i(transfers) ? 0 : -EINVAL; 120 + } 121 + 122 + int vpu_color_check_matrix(u32 matrix) 123 + { 124 + return vpu_color_cvrt_matrix_v2i(matrix) ? 0 : -EINVAL; 125 + } 126 + 127 + int vpu_color_check_full_range(u32 full_range) 128 + { 129 + int ret = -EINVAL; 130 + 131 + switch (full_range) { 132 + case V4L2_QUANTIZATION_FULL_RANGE: 133 + case V4L2_QUANTIZATION_LIM_RANGE: 134 + ret = 0; 135 + break; 136 + default: 137 + break; 138 + } 139 + 140 + return ret; 141 + } 142 + 143 + int vpu_color_get_default(u32 primaries, u32 *ptransfers, u32 *pmatrix, u32 *pfull_range) 144 + { 145 + u32 transfers; 146 + u32 matrix; 147 + u32 full_range; 148 + 149 + switch (primaries) { 150 + case V4L2_COLORSPACE_REC709: 151 + transfers = V4L2_XFER_FUNC_709; 152 + matrix = V4L2_YCBCR_ENC_709; 153 + break; 154 + case V4L2_COLORSPACE_470_SYSTEM_M: 155 + case V4L2_COLORSPACE_470_SYSTEM_BG: 156 + case V4L2_COLORSPACE_SMPTE170M: 157 + transfers = V4L2_XFER_FUNC_709; 158 + matrix = V4L2_YCBCR_ENC_601; 159 + break; 160 + case V4L2_COLORSPACE_SMPTE240M: 161 + transfers = V4L2_XFER_FUNC_SMPTE240M; 162 + matrix = V4L2_YCBCR_ENC_SMPTE240M; 163 + break; 164 + case V4L2_COLORSPACE_BT2020: 165 + transfers = V4L2_XFER_FUNC_709; 166 + matrix = V4L2_YCBCR_ENC_BT2020; 167 + break; 168 + default: 169 + transfers = V4L2_XFER_FUNC_DEFAULT; 170 + matrix = V4L2_YCBCR_ENC_DEFAULT; 171 + break; 172 + } 173 + full_range = V4L2_QUANTIZATION_LIM_RANGE; 174 + 175 + if (ptransfers) 176 + *ptransfers = transfers; 177 + if (pmatrix) 178 + *pmatrix = matrix; 179 + if (pfull_range) 180 + *pfull_range = full_range; 181 + 182 + return 0; 183 + }
+871
drivers/media/platform/amphion/vpu_core.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright 2020-2021 NXP 4 + */ 5 + 6 + #include <linux/init.h> 7 + #include <linux/interconnect.h> 8 + #include <linux/ioctl.h> 9 + #include <linux/list.h> 10 + #include <linux/kernel.h> 11 + #include <linux/module.h> 12 + #include <linux/of_device.h> 13 + #include <linux/of_address.h> 14 + #include <linux/platform_device.h> 15 + #include <linux/slab.h> 16 + #include <linux/types.h> 17 + #include <linux/pm_runtime.h> 18 + #include <linux/pm_domain.h> 19 + #include <linux/firmware.h> 20 + #include <linux/vmalloc.h> 21 + #include "vpu.h" 22 + #include "vpu_defs.h" 23 + #include "vpu_core.h" 24 + #include "vpu_mbox.h" 25 + #include "vpu_msgs.h" 26 + #include "vpu_rpc.h" 27 + #include "vpu_cmds.h" 28 + 29 + void csr_writel(struct vpu_core *core, u32 reg, u32 val) 30 + { 31 + writel(val, core->base + reg); 32 + } 33 + 34 + u32 csr_readl(struct vpu_core *core, u32 reg) 35 + { 36 + return readl(core->base + reg); 37 + } 38 + 39 + static int vpu_core_load_firmware(struct vpu_core *core) 40 + { 41 + const struct firmware *pfw = NULL; 42 + int ret = 0; 43 + 44 + if (!core->fw.virt) { 45 + dev_err(core->dev, "firmware buffer is not ready\n"); 46 + return -EINVAL; 47 + } 48 + 49 + ret = request_firmware(&pfw, core->res->fwname, core->dev); 50 + dev_dbg(core->dev, "request_firmware %s : %d\n", core->res->fwname, ret); 51 + if (ret) { 52 + dev_err(core->dev, "request firmware %s failed, ret = %d\n", 53 + core->res->fwname, ret); 54 + return ret; 55 + } 56 + 57 + if (core->fw.length < pfw->size) { 58 + dev_err(core->dev, "firmware buffer size want %zu, but %d\n", 59 + pfw->size, core->fw.length); 60 + ret = -EINVAL; 61 + goto exit; 62 + } 63 + 64 + memset(core->fw.virt, 0, core->fw.length); 65 + memcpy(core->fw.virt, pfw->data, pfw->size); 66 + core->fw.bytesused = pfw->size; 67 + ret = vpu_iface_on_firmware_loaded(core); 68 + exit: 69 + release_firmware(pfw); 70 + pfw = NULL; 71 + 72 + return ret; 73 + } 74 + 75 + static int vpu_core_boot_done(struct vpu_core *core) 76 + { 77 + u32 fw_version; 78 + 79 + fw_version = vpu_iface_get_version(core); 80 + dev_info(core->dev, "%s firmware version : %d.%d.%d\n", 81 + vpu_core_type_desc(core->type), 82 + (fw_version >> 16) & 0xff, 83 + (fw_version >> 8) & 0xff, 84 + fw_version & 0xff); 85 + core->supported_instance_count = vpu_iface_get_max_instance_count(core); 86 + if (core->res->act_size) { 87 + u32 count = core->act.length / core->res->act_size; 88 + 89 + core->supported_instance_count = min(core->supported_instance_count, count); 90 + } 91 + core->fw_version = fw_version; 92 + core->state = VPU_CORE_ACTIVE; 93 + 94 + return 0; 95 + } 96 + 97 + static int vpu_core_wait_boot_done(struct vpu_core *core) 98 + { 99 + int ret; 100 + 101 + ret = wait_for_completion_timeout(&core->cmp, VPU_TIMEOUT); 102 + if (!ret) { 103 + dev_err(core->dev, "boot timeout\n"); 104 + return -EINVAL; 105 + } 106 + return vpu_core_boot_done(core); 107 + } 108 + 109 + static int vpu_core_boot(struct vpu_core *core, bool load) 110 + { 111 + int ret; 112 + 113 + reinit_completion(&core->cmp); 114 + if (load) { 115 + ret = vpu_core_load_firmware(core); 116 + if (ret) 117 + return ret; 118 + } 119 + 120 + vpu_iface_boot_core(core); 121 + return vpu_core_wait_boot_done(core); 122 + } 123 + 124 + static int vpu_core_shutdown(struct vpu_core *core) 125 + { 126 + return vpu_iface_shutdown_core(core); 127 + } 128 + 129 + static int vpu_core_restore(struct vpu_core *core) 130 + { 131 + int ret; 132 + 133 + ret = vpu_core_sw_reset(core); 134 + if (ret) 135 + return ret; 136 + 137 + vpu_core_boot_done(core); 138 + return vpu_iface_restore_core(core); 139 + } 140 + 141 + static int __vpu_alloc_dma(struct device *dev, struct vpu_buffer *buf) 142 + { 143 + gfp_t gfp = GFP_KERNEL | GFP_DMA32; 144 + 145 + if (!buf->length) 146 + return 0; 147 + 148 + buf->virt = dma_alloc_coherent(dev, buf->length, &buf->phys, gfp); 149 + if (!buf->virt) 150 + return -ENOMEM; 151 + 152 + buf->dev = dev; 153 + 154 + return 0; 155 + } 156 + 157 + void vpu_free_dma(struct vpu_buffer *buf) 158 + { 159 + if (!buf->virt || !buf->dev) 160 + return; 161 + 162 + dma_free_coherent(buf->dev, buf->length, buf->virt, buf->phys); 163 + buf->virt = NULL; 164 + buf->phys = 0; 165 + buf->length = 0; 166 + buf->bytesused = 0; 167 + buf->dev = NULL; 168 + } 169 + 170 + int vpu_alloc_dma(struct vpu_core *core, struct vpu_buffer *buf) 171 + { 172 + return __vpu_alloc_dma(core->dev, buf); 173 + } 174 + 175 + static void vpu_core_check_hang(struct vpu_core *core) 176 + { 177 + if (core->hang_mask) 178 + core->state = VPU_CORE_HANG; 179 + } 180 + 181 + static struct vpu_core *vpu_core_find_proper_by_type(struct vpu_dev *vpu, u32 type) 182 + { 183 + struct vpu_core *core = NULL; 184 + int request_count = INT_MAX; 185 + struct vpu_core *c; 186 + 187 + list_for_each_entry(c, &vpu->cores, list) { 188 + dev_dbg(c->dev, "instance_mask = 0x%lx, state = %d\n", c->instance_mask, c->state); 189 + if (c->type != type) 190 + continue; 191 + if (c->state == VPU_CORE_DEINIT) { 192 + core = c; 193 + break; 194 + } 195 + vpu_core_check_hang(c); 196 + if (c->state != VPU_CORE_ACTIVE) 197 + continue; 198 + if (c->request_count < request_count) { 199 + request_count = c->request_count; 200 + core = c; 201 + } 202 + if (!request_count) 203 + break; 204 + } 205 + 206 + return core; 207 + } 208 + 209 + static bool vpu_core_is_exist(struct vpu_dev *vpu, struct vpu_core *core) 210 + { 211 + struct vpu_core *c; 212 + 213 + list_for_each_entry(c, &vpu->cores, list) { 214 + if (c == core) 215 + return true; 216 + } 217 + 218 + return false; 219 + } 220 + 221 + static void vpu_core_get_vpu(struct vpu_core *core) 222 + { 223 + core->vpu->get_vpu(core->vpu); 224 + if (core->type == VPU_CORE_TYPE_ENC) 225 + core->vpu->get_enc(core->vpu); 226 + if (core->type == VPU_CORE_TYPE_DEC) 227 + core->vpu->get_dec(core->vpu); 228 + } 229 + 230 + static int vpu_core_register(struct device *dev, struct vpu_core *core) 231 + { 232 + struct vpu_dev *vpu = dev_get_drvdata(dev); 233 + int ret = 0; 234 + 235 + dev_dbg(core->dev, "register core %s\n", vpu_core_type_desc(core->type)); 236 + if (vpu_core_is_exist(vpu, core)) 237 + return 0; 238 + 239 + core->workqueue = alloc_workqueue("vpu", WQ_UNBOUND | WQ_MEM_RECLAIM, 1); 240 + if (!core->workqueue) { 241 + dev_err(core->dev, "fail to alloc workqueue\n"); 242 + return -ENOMEM; 243 + } 244 + INIT_WORK(&core->msg_work, vpu_msg_run_work); 245 + INIT_DELAYED_WORK(&core->msg_delayed_work, vpu_msg_delayed_work); 246 + core->msg_buffer_size = roundup_pow_of_two(VPU_MSG_BUFFER_SIZE); 247 + core->msg_buffer = vzalloc(core->msg_buffer_size); 248 + if (!core->msg_buffer) { 249 + dev_err(core->dev, "failed allocate buffer for fifo\n"); 250 + ret = -ENOMEM; 251 + goto error; 252 + } 253 + ret = kfifo_init(&core->msg_fifo, core->msg_buffer, core->msg_buffer_size); 254 + if (ret) { 255 + dev_err(core->dev, "failed init kfifo\n"); 256 + goto error; 257 + } 258 + 259 + list_add_tail(&core->list, &vpu->cores); 260 + 261 + vpu_core_get_vpu(core); 262 + 263 + if (vpu_iface_get_power_state(core)) 264 + ret = vpu_core_restore(core); 265 + if (ret) 266 + goto error; 267 + 268 + return 0; 269 + error: 270 + if (core->msg_buffer) { 271 + vfree(core->msg_buffer); 272 + core->msg_buffer = NULL; 273 + } 274 + if (core->workqueue) { 275 + destroy_workqueue(core->workqueue); 276 + core->workqueue = NULL; 277 + } 278 + return ret; 279 + } 280 + 281 + static void vpu_core_put_vpu(struct vpu_core *core) 282 + { 283 + if (core->type == VPU_CORE_TYPE_ENC) 284 + core->vpu->put_enc(core->vpu); 285 + if (core->type == VPU_CORE_TYPE_DEC) 286 + core->vpu->put_dec(core->vpu); 287 + core->vpu->put_vpu(core->vpu); 288 + } 289 + 290 + static int vpu_core_unregister(struct device *dev, struct vpu_core *core) 291 + { 292 + list_del_init(&core->list); 293 + 294 + vpu_core_put_vpu(core); 295 + core->vpu = NULL; 296 + vfree(core->msg_buffer); 297 + core->msg_buffer = NULL; 298 + 299 + if (core->workqueue) { 300 + cancel_work_sync(&core->msg_work); 301 + cancel_delayed_work_sync(&core->msg_delayed_work); 302 + destroy_workqueue(core->workqueue); 303 + core->workqueue = NULL; 304 + } 305 + 306 + return 0; 307 + } 308 + 309 + static int vpu_core_acquire_instance(struct vpu_core *core) 310 + { 311 + int id; 312 + 313 + id = ffz(core->instance_mask); 314 + if (id >= core->supported_instance_count) 315 + return -EINVAL; 316 + 317 + set_bit(id, &core->instance_mask); 318 + 319 + return id; 320 + } 321 + 322 + static void vpu_core_release_instance(struct vpu_core *core, int id) 323 + { 324 + if (id < 0 || id >= core->supported_instance_count) 325 + return; 326 + 327 + clear_bit(id, &core->instance_mask); 328 + } 329 + 330 + struct vpu_inst *vpu_inst_get(struct vpu_inst *inst) 331 + { 332 + if (!inst) 333 + return NULL; 334 + 335 + atomic_inc(&inst->ref_count); 336 + 337 + return inst; 338 + } 339 + 340 + void vpu_inst_put(struct vpu_inst *inst) 341 + { 342 + if (!inst) 343 + return; 344 + if (atomic_dec_and_test(&inst->ref_count)) { 345 + if (inst->release) 346 + inst->release(inst); 347 + } 348 + } 349 + 350 + struct vpu_core *vpu_request_core(struct vpu_dev *vpu, enum vpu_core_type type) 351 + { 352 + struct vpu_core *core = NULL; 353 + int ret; 354 + 355 + mutex_lock(&vpu->lock); 356 + 357 + core = vpu_core_find_proper_by_type(vpu, type); 358 + if (!core) 359 + goto exit; 360 + 361 + mutex_lock(&core->lock); 362 + pm_runtime_get_sync(core->dev); 363 + 364 + if (core->state == VPU_CORE_DEINIT) { 365 + ret = vpu_core_boot(core, true); 366 + if (ret) { 367 + pm_runtime_put_sync(core->dev); 368 + mutex_unlock(&core->lock); 369 + core = NULL; 370 + goto exit; 371 + } 372 + } 373 + 374 + core->request_count++; 375 + 376 + mutex_unlock(&core->lock); 377 + exit: 378 + mutex_unlock(&vpu->lock); 379 + 380 + return core; 381 + } 382 + 383 + void vpu_release_core(struct vpu_core *core) 384 + { 385 + if (!core) 386 + return; 387 + 388 + mutex_lock(&core->lock); 389 + pm_runtime_put_sync(core->dev); 390 + if (core->request_count) 391 + core->request_count--; 392 + mutex_unlock(&core->lock); 393 + } 394 + 395 + int vpu_inst_register(struct vpu_inst *inst) 396 + { 397 + struct vpu_dev *vpu; 398 + struct vpu_core *core; 399 + int ret = 0; 400 + 401 + vpu = inst->vpu; 402 + core = inst->core; 403 + if (!core) { 404 + core = vpu_request_core(vpu, inst->type); 405 + if (!core) { 406 + dev_err(vpu->dev, "there is no vpu core for %s\n", 407 + vpu_core_type_desc(inst->type)); 408 + return -EINVAL; 409 + } 410 + inst->core = core; 411 + inst->dev = get_device(core->dev); 412 + } 413 + 414 + mutex_lock(&core->lock); 415 + if (inst->id >= 0 && inst->id < core->supported_instance_count) 416 + goto exit; 417 + 418 + ret = vpu_core_acquire_instance(core); 419 + if (ret < 0) 420 + goto exit; 421 + 422 + vpu_trace(inst->dev, "[%d] %p\n", ret, inst); 423 + inst->id = ret; 424 + list_add_tail(&inst->list, &core->instances); 425 + ret = 0; 426 + if (core->res->act_size) { 427 + inst->act.phys = core->act.phys + core->res->act_size * inst->id; 428 + inst->act.virt = core->act.virt + core->res->act_size * inst->id; 429 + inst->act.length = core->res->act_size; 430 + } 431 + vpu_inst_create_dbgfs_file(inst); 432 + exit: 433 + mutex_unlock(&core->lock); 434 + 435 + if (ret) 436 + dev_err(core->dev, "register instance fail\n"); 437 + return ret; 438 + } 439 + 440 + int vpu_inst_unregister(struct vpu_inst *inst) 441 + { 442 + struct vpu_core *core; 443 + 444 + if (!inst->core) 445 + return 0; 446 + 447 + core = inst->core; 448 + vpu_clear_request(inst); 449 + mutex_lock(&core->lock); 450 + if (inst->id >= 0 && inst->id < core->supported_instance_count) { 451 + vpu_inst_remove_dbgfs_file(inst); 452 + list_del_init(&inst->list); 453 + vpu_core_release_instance(core, inst->id); 454 + inst->id = VPU_INST_NULL_ID; 455 + } 456 + vpu_core_check_hang(core); 457 + if (core->state == VPU_CORE_HANG && !core->instance_mask) { 458 + dev_info(core->dev, "reset hang core\n"); 459 + if (!vpu_core_sw_reset(core)) { 460 + core->state = VPU_CORE_ACTIVE; 461 + core->hang_mask = 0; 462 + } 463 + } 464 + mutex_unlock(&core->lock); 465 + 466 + return 0; 467 + } 468 + 469 + struct vpu_inst *vpu_core_find_instance(struct vpu_core *core, u32 index) 470 + { 471 + struct vpu_inst *inst = NULL; 472 + struct vpu_inst *tmp; 473 + 474 + mutex_lock(&core->lock); 475 + if (!test_bit(index, &core->instance_mask)) 476 + goto exit; 477 + list_for_each_entry(tmp, &core->instances, list) { 478 + if (tmp->id == index) { 479 + inst = vpu_inst_get(tmp); 480 + break; 481 + } 482 + } 483 + exit: 484 + mutex_unlock(&core->lock); 485 + 486 + return inst; 487 + } 488 + 489 + const struct vpu_core_resources *vpu_get_resource(struct vpu_inst *inst) 490 + { 491 + struct vpu_dev *vpu; 492 + struct vpu_core *core = NULL; 493 + const struct vpu_core_resources *res = NULL; 494 + 495 + if (!inst || !inst->vpu) 496 + return NULL; 497 + 498 + if (inst->core && inst->core->res) 499 + return inst->core->res; 500 + 501 + vpu = inst->vpu; 502 + mutex_lock(&vpu->lock); 503 + list_for_each_entry(core, &vpu->cores, list) { 504 + if (core->type == inst->type) { 505 + res = core->res; 506 + break; 507 + } 508 + } 509 + mutex_unlock(&vpu->lock); 510 + 511 + return res; 512 + } 513 + 514 + static int vpu_core_parse_dt(struct vpu_core *core, struct device_node *np) 515 + { 516 + struct device_node *node; 517 + struct resource res; 518 + int ret; 519 + 520 + if (of_count_phandle_with_args(np, "memory-region", NULL) < 2) { 521 + dev_err(core->dev, "need 2 memory-region for boot and rpc\n"); 522 + return -ENODEV; 523 + } 524 + 525 + node = of_parse_phandle(np, "memory-region", 0); 526 + if (!node) { 527 + dev_err(core->dev, "boot-region of_parse_phandle error\n"); 528 + return -ENODEV; 529 + } 530 + if (of_address_to_resource(node, 0, &res)) { 531 + dev_err(core->dev, "boot-region of_address_to_resource error\n"); 532 + return -EINVAL; 533 + } 534 + core->fw.phys = res.start; 535 + core->fw.length = resource_size(&res); 536 + 537 + node = of_parse_phandle(np, "memory-region", 1); 538 + if (!node) { 539 + dev_err(core->dev, "rpc-region of_parse_phandle error\n"); 540 + return -ENODEV; 541 + } 542 + if (of_address_to_resource(node, 0, &res)) { 543 + dev_err(core->dev, "rpc-region of_address_to_resource error\n"); 544 + return -EINVAL; 545 + } 546 + core->rpc.phys = res.start; 547 + core->rpc.length = resource_size(&res); 548 + 549 + if (core->rpc.length < core->res->rpc_size + core->res->fwlog_size) { 550 + dev_err(core->dev, "the rpc-region <%pad, 0x%x> is not enough\n", 551 + &core->rpc.phys, core->rpc.length); 552 + return -EINVAL; 553 + } 554 + 555 + core->fw.virt = memremap(core->fw.phys, core->fw.length, MEMREMAP_WC); 556 + core->rpc.virt = memremap(core->rpc.phys, core->rpc.length, MEMREMAP_WC); 557 + memset(core->rpc.virt, 0, core->rpc.length); 558 + 559 + ret = vpu_iface_check_memory_region(core, core->rpc.phys, core->rpc.length); 560 + if (ret != VPU_CORE_MEMORY_UNCACHED) { 561 + dev_err(core->dev, "rpc region<%pad, 0x%x> isn't uncached\n", 562 + &core->rpc.phys, core->rpc.length); 563 + return -EINVAL; 564 + } 565 + 566 + core->log.phys = core->rpc.phys + core->res->rpc_size; 567 + core->log.virt = core->rpc.virt + core->res->rpc_size; 568 + core->log.length = core->res->fwlog_size; 569 + core->act.phys = core->log.phys + core->log.length; 570 + core->act.virt = core->log.virt + core->log.length; 571 + core->act.length = core->rpc.length - core->res->rpc_size - core->log.length; 572 + core->rpc.length = core->res->rpc_size; 573 + 574 + return 0; 575 + } 576 + 577 + static int vpu_core_probe(struct platform_device *pdev) 578 + { 579 + struct device *dev = &pdev->dev; 580 + struct vpu_core *core; 581 + struct vpu_dev *vpu = dev_get_drvdata(dev->parent); 582 + struct vpu_shared_addr *iface; 583 + u32 iface_data_size; 584 + int ret; 585 + 586 + dev_dbg(dev, "probe\n"); 587 + if (!vpu) 588 + return -EINVAL; 589 + core = devm_kzalloc(dev, sizeof(*core), GFP_KERNEL); 590 + if (!core) 591 + return -ENOMEM; 592 + 593 + core->pdev = pdev; 594 + core->dev = dev; 595 + platform_set_drvdata(pdev, core); 596 + core->vpu = vpu; 597 + INIT_LIST_HEAD(&core->instances); 598 + mutex_init(&core->lock); 599 + mutex_init(&core->cmd_lock); 600 + init_completion(&core->cmp); 601 + init_waitqueue_head(&core->ack_wq); 602 + core->state = VPU_CORE_DEINIT; 603 + 604 + core->res = of_device_get_match_data(dev); 605 + if (!core->res) 606 + return -ENODEV; 607 + 608 + core->type = core->res->type; 609 + core->id = of_alias_get_id(dev->of_node, "vpu_core"); 610 + if (core->id < 0) { 611 + dev_err(dev, "can't get vpu core id\n"); 612 + return core->id; 613 + } 614 + dev_info(core->dev, "[%d] = %s\n", core->id, vpu_core_type_desc(core->type)); 615 + ret = vpu_core_parse_dt(core, dev->of_node); 616 + if (ret) 617 + return ret; 618 + 619 + core->base = devm_platform_ioremap_resource(pdev, 0); 620 + if (IS_ERR(core->base)) 621 + return PTR_ERR(core->base); 622 + 623 + if (!vpu_iface_check_codec(core)) { 624 + dev_err(core->dev, "is not supported\n"); 625 + return -EINVAL; 626 + } 627 + 628 + ret = vpu_mbox_init(core); 629 + if (ret) 630 + return ret; 631 + 632 + iface = devm_kzalloc(dev, sizeof(*iface), GFP_KERNEL); 633 + if (!iface) 634 + return -ENOMEM; 635 + 636 + iface_data_size = vpu_iface_get_data_size(core); 637 + if (iface_data_size) { 638 + iface->priv = devm_kzalloc(dev, iface_data_size, GFP_KERNEL); 639 + if (!iface->priv) 640 + return -ENOMEM; 641 + } 642 + 643 + ret = vpu_iface_init(core, iface, &core->rpc, core->fw.phys); 644 + if (ret) { 645 + dev_err(core->dev, "init iface fail, ret = %d\n", ret); 646 + return ret; 647 + } 648 + 649 + vpu_iface_config_system(core, vpu->res->mreg_base, vpu->base); 650 + vpu_iface_set_log_buf(core, &core->log); 651 + 652 + pm_runtime_enable(dev); 653 + ret = pm_runtime_get_sync(dev); 654 + if (ret) { 655 + pm_runtime_put_noidle(dev); 656 + pm_runtime_set_suspended(dev); 657 + goto err_runtime_disable; 658 + } 659 + 660 + ret = vpu_core_register(dev->parent, core); 661 + if (ret) 662 + goto err_core_register; 663 + core->parent = dev->parent; 664 + 665 + pm_runtime_put_sync(dev); 666 + vpu_core_create_dbgfs_file(core); 667 + 668 + return 0; 669 + 670 + err_core_register: 671 + pm_runtime_put_sync(dev); 672 + err_runtime_disable: 673 + pm_runtime_disable(dev); 674 + 675 + return ret; 676 + } 677 + 678 + static int vpu_core_remove(struct platform_device *pdev) 679 + { 680 + struct device *dev = &pdev->dev; 681 + struct vpu_core *core = platform_get_drvdata(pdev); 682 + int ret; 683 + 684 + vpu_core_remove_dbgfs_file(core); 685 + ret = pm_runtime_get_sync(dev); 686 + WARN_ON(ret < 0); 687 + 688 + vpu_core_shutdown(core); 689 + pm_runtime_put_sync(dev); 690 + pm_runtime_disable(dev); 691 + 692 + vpu_core_unregister(core->parent, core); 693 + memunmap(core->fw.virt); 694 + memunmap(core->rpc.virt); 695 + mutex_destroy(&core->lock); 696 + mutex_destroy(&core->cmd_lock); 697 + 698 + return 0; 699 + } 700 + 701 + static int __maybe_unused vpu_core_runtime_resume(struct device *dev) 702 + { 703 + struct vpu_core *core = dev_get_drvdata(dev); 704 + 705 + return vpu_mbox_request(core); 706 + } 707 + 708 + static int __maybe_unused vpu_core_runtime_suspend(struct device *dev) 709 + { 710 + struct vpu_core *core = dev_get_drvdata(dev); 711 + 712 + vpu_mbox_free(core); 713 + return 0; 714 + } 715 + 716 + static void vpu_core_cancel_work(struct vpu_core *core) 717 + { 718 + struct vpu_inst *inst = NULL; 719 + 720 + cancel_work_sync(&core->msg_work); 721 + cancel_delayed_work_sync(&core->msg_delayed_work); 722 + 723 + mutex_lock(&core->lock); 724 + list_for_each_entry(inst, &core->instances, list) 725 + cancel_work_sync(&inst->msg_work); 726 + mutex_unlock(&core->lock); 727 + } 728 + 729 + static void vpu_core_resume_work(struct vpu_core *core) 730 + { 731 + struct vpu_inst *inst = NULL; 732 + unsigned long delay = msecs_to_jiffies(10); 733 + 734 + queue_work(core->workqueue, &core->msg_work); 735 + queue_delayed_work(core->workqueue, &core->msg_delayed_work, delay); 736 + 737 + mutex_lock(&core->lock); 738 + list_for_each_entry(inst, &core->instances, list) 739 + queue_work(inst->workqueue, &inst->msg_work); 740 + mutex_unlock(&core->lock); 741 + } 742 + 743 + static int __maybe_unused vpu_core_resume(struct device *dev) 744 + { 745 + struct vpu_core *core = dev_get_drvdata(dev); 746 + int ret = 0; 747 + 748 + mutex_lock(&core->lock); 749 + pm_runtime_get_sync(dev); 750 + vpu_core_get_vpu(core); 751 + if (core->state != VPU_CORE_SNAPSHOT) 752 + goto exit; 753 + 754 + if (!vpu_iface_get_power_state(core)) { 755 + if (!list_empty(&core->instances)) { 756 + ret = vpu_core_boot(core, false); 757 + if (ret) { 758 + dev_err(core->dev, "%s boot fail\n", __func__); 759 + core->state = VPU_CORE_DEINIT; 760 + goto exit; 761 + } 762 + } else { 763 + core->state = VPU_CORE_DEINIT; 764 + } 765 + } else { 766 + if (!list_empty(&core->instances)) { 767 + ret = vpu_core_sw_reset(core); 768 + if (ret) { 769 + dev_err(core->dev, "%s sw_reset fail\n", __func__); 770 + core->state = VPU_CORE_HANG; 771 + goto exit; 772 + } 773 + } 774 + core->state = VPU_CORE_ACTIVE; 775 + } 776 + 777 + exit: 778 + pm_runtime_put_sync(dev); 779 + mutex_unlock(&core->lock); 780 + 781 + vpu_core_resume_work(core); 782 + return ret; 783 + } 784 + 785 + static int __maybe_unused vpu_core_suspend(struct device *dev) 786 + { 787 + struct vpu_core *core = dev_get_drvdata(dev); 788 + int ret = 0; 789 + 790 + mutex_lock(&core->lock); 791 + if (core->state == VPU_CORE_ACTIVE) { 792 + if (!list_empty(&core->instances)) { 793 + ret = vpu_core_snapshot(core); 794 + if (ret) { 795 + mutex_unlock(&core->lock); 796 + return ret; 797 + } 798 + } 799 + 800 + core->state = VPU_CORE_SNAPSHOT; 801 + } 802 + mutex_unlock(&core->lock); 803 + 804 + vpu_core_cancel_work(core); 805 + 806 + mutex_lock(&core->lock); 807 + vpu_core_put_vpu(core); 808 + mutex_unlock(&core->lock); 809 + return ret; 810 + } 811 + 812 + static const struct dev_pm_ops vpu_core_pm_ops = { 813 + SET_RUNTIME_PM_OPS(vpu_core_runtime_suspend, vpu_core_runtime_resume, NULL) 814 + SET_SYSTEM_SLEEP_PM_OPS(vpu_core_suspend, vpu_core_resume) 815 + }; 816 + 817 + static struct vpu_core_resources imx8q_enc = { 818 + .type = VPU_CORE_TYPE_ENC, 819 + .fwname = "vpu/vpu_fw_imx8_enc.bin", 820 + .stride = 16, 821 + .max_width = 1920, 822 + .max_height = 1920, 823 + .min_width = 64, 824 + .min_height = 48, 825 + .step_width = 2, 826 + .step_height = 2, 827 + .rpc_size = 0x80000, 828 + .fwlog_size = 0x80000, 829 + .act_size = 0xc0000, 830 + }; 831 + 832 + static struct vpu_core_resources imx8q_dec = { 833 + .type = VPU_CORE_TYPE_DEC, 834 + .fwname = "vpu/vpu_fw_imx8_dec.bin", 835 + .stride = 256, 836 + .max_width = 8188, 837 + .max_height = 8188, 838 + .min_width = 16, 839 + .min_height = 16, 840 + .step_width = 1, 841 + .step_height = 1, 842 + .rpc_size = 0x80000, 843 + .fwlog_size = 0x80000, 844 + }; 845 + 846 + static const struct of_device_id vpu_core_dt_match[] = { 847 + { .compatible = "nxp,imx8q-vpu-encoder", .data = &imx8q_enc }, 848 + { .compatible = "nxp,imx8q-vpu-decoder", .data = &imx8q_dec }, 849 + {} 850 + }; 851 + MODULE_DEVICE_TABLE(of, vpu_core_dt_match); 852 + 853 + static struct platform_driver amphion_vpu_core_driver = { 854 + .probe = vpu_core_probe, 855 + .remove = vpu_core_remove, 856 + .driver = { 857 + .name = "amphion-vpu-core", 858 + .of_match_table = vpu_core_dt_match, 859 + .pm = &vpu_core_pm_ops, 860 + }, 861 + }; 862 + 863 + int __init vpu_core_driver_init(void) 864 + { 865 + return platform_driver_register(&amphion_vpu_core_driver); 866 + } 867 + 868 + void __exit vpu_core_driver_exit(void) 869 + { 870 + platform_driver_unregister(&amphion_vpu_core_driver); 871 + }
+15
drivers/media/platform/amphion/vpu_core.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Copyright 2020-2021 NXP 4 + */ 5 + 6 + #ifndef _AMPHION_VPU_CORE_H 7 + #define _AMPHION_VPU_CORE_H 8 + 9 + void csr_writel(struct vpu_core *core, u32 reg, u32 val); 10 + u32 csr_readl(struct vpu_core *core, u32 reg); 11 + int vpu_alloc_dma(struct vpu_core *core, struct vpu_buffer *buf); 12 + void vpu_free_dma(struct vpu_buffer *buf); 13 + struct vpu_inst *vpu_core_find_instance(struct vpu_core *core, u32 index); 14 + 15 + #endif
+494
drivers/media/platform/amphion/vpu_dbg.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright 2020-2021 NXP 4 + */ 5 + 6 + #include <linux/init.h> 7 + #include <linux/device.h> 8 + #include <linux/ioctl.h> 9 + #include <linux/list.h> 10 + #include <linux/module.h> 11 + #include <linux/kernel.h> 12 + #include <linux/types.h> 13 + #include <linux/pm_runtime.h> 14 + #include <media/v4l2-device.h> 15 + #include <linux/debugfs.h> 16 + #include "vpu.h" 17 + #include "vpu_defs.h" 18 + #include "vpu_helpers.h" 19 + #include "vpu_cmds.h" 20 + #include "vpu_rpc.h" 21 + #include "vpu_v4l2.h" 22 + 23 + struct print_buf_desc { 24 + u32 start_h_phy; 25 + u32 start_h_vir; 26 + u32 start_m; 27 + u32 bytes; 28 + u32 read; 29 + u32 write; 30 + char buffer[0]; 31 + }; 32 + 33 + static char *vb2_stat_name[] = { 34 + [VB2_BUF_STATE_DEQUEUED] = "dequeued", 35 + [VB2_BUF_STATE_IN_REQUEST] = "in_request", 36 + [VB2_BUF_STATE_PREPARING] = "preparing", 37 + [VB2_BUF_STATE_QUEUED] = "queued", 38 + [VB2_BUF_STATE_ACTIVE] = "active", 39 + [VB2_BUF_STATE_DONE] = "done", 40 + [VB2_BUF_STATE_ERROR] = "error", 41 + }; 42 + 43 + static char *vpu_stat_name[] = { 44 + [VPU_BUF_STATE_IDLE] = "idle", 45 + [VPU_BUF_STATE_INUSE] = "inuse", 46 + [VPU_BUF_STATE_DECODED] = "decoded", 47 + [VPU_BUF_STATE_READY] = "ready", 48 + [VPU_BUF_STATE_SKIP] = "skip", 49 + [VPU_BUF_STATE_ERROR] = "error", 50 + }; 51 + 52 + static int vpu_dbg_instance(struct seq_file *s, void *data) 53 + { 54 + struct vpu_inst *inst = s->private; 55 + char str[128]; 56 + int num; 57 + struct vb2_queue *vq; 58 + int i; 59 + 60 + if (!inst->fh.m2m_ctx) 61 + return 0; 62 + num = scnprintf(str, sizeof(str), "[%s]\n", vpu_core_type_desc(inst->type)); 63 + if (seq_write(s, str, num)) 64 + return 0; 65 + 66 + num = scnprintf(str, sizeof(str), "tgig = %d,pid = %d\n", inst->tgid, inst->pid); 67 + if (seq_write(s, str, num)) 68 + return 0; 69 + num = scnprintf(str, sizeof(str), "state = %d\n", inst->state); 70 + if (seq_write(s, str, num)) 71 + return 0; 72 + num = scnprintf(str, sizeof(str), 73 + "min_buffer_out = %d, min_buffer_cap = %d\n", 74 + inst->min_buffer_out, inst->min_buffer_cap); 75 + if (seq_write(s, str, num)) 76 + return 0; 77 + 78 + vq = v4l2_m2m_get_src_vq(inst->fh.m2m_ctx); 79 + num = scnprintf(str, sizeof(str), 80 + "output (%2d, %2d): fmt = %c%c%c%c %d x %d, %d;", 81 + vb2_is_streaming(vq), 82 + vq->num_buffers, 83 + inst->out_format.pixfmt, 84 + inst->out_format.pixfmt >> 8, 85 + inst->out_format.pixfmt >> 16, 86 + inst->out_format.pixfmt >> 24, 87 + inst->out_format.width, 88 + inst->out_format.height, 89 + vq->last_buffer_dequeued); 90 + if (seq_write(s, str, num)) 91 + return 0; 92 + for (i = 0; i < inst->out_format.num_planes; i++) { 93 + num = scnprintf(str, sizeof(str), " %d(%d)", 94 + inst->out_format.sizeimage[i], 95 + inst->out_format.bytesperline[i]); 96 + if (seq_write(s, str, num)) 97 + return 0; 98 + } 99 + if (seq_write(s, "\n", 1)) 100 + return 0; 101 + 102 + vq = v4l2_m2m_get_dst_vq(inst->fh.m2m_ctx); 103 + num = scnprintf(str, sizeof(str), 104 + "capture(%2d, %2d): fmt = %c%c%c%c %d x %d, %d;", 105 + vb2_is_streaming(vq), 106 + vq->num_buffers, 107 + inst->cap_format.pixfmt, 108 + inst->cap_format.pixfmt >> 8, 109 + inst->cap_format.pixfmt >> 16, 110 + inst->cap_format.pixfmt >> 24, 111 + inst->cap_format.width, 112 + inst->cap_format.height, 113 + vq->last_buffer_dequeued); 114 + if (seq_write(s, str, num)) 115 + return 0; 116 + for (i = 0; i < inst->cap_format.num_planes; i++) { 117 + num = scnprintf(str, sizeof(str), " %d(%d)", 118 + inst->cap_format.sizeimage[i], 119 + inst->cap_format.bytesperline[i]); 120 + if (seq_write(s, str, num)) 121 + return 0; 122 + } 123 + if (seq_write(s, "\n", 1)) 124 + return 0; 125 + num = scnprintf(str, sizeof(str), "crop: (%d, %d) %d x %d\n", 126 + inst->crop.left, 127 + inst->crop.top, 128 + inst->crop.width, 129 + inst->crop.height); 130 + if (seq_write(s, str, num)) 131 + return 0; 132 + 133 + vq = v4l2_m2m_get_src_vq(inst->fh.m2m_ctx); 134 + for (i = 0; i < vq->num_buffers; i++) { 135 + struct vb2_buffer *vb = vq->bufs[i]; 136 + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 137 + 138 + if (vb->state == VB2_BUF_STATE_DEQUEUED) 139 + continue; 140 + num = scnprintf(str, sizeof(str), 141 + "output [%2d] state = %10s, %8s\n", 142 + i, vb2_stat_name[vb->state], 143 + vpu_stat_name[vpu_get_buffer_state(vbuf)]); 144 + if (seq_write(s, str, num)) 145 + return 0; 146 + } 147 + 148 + vq = v4l2_m2m_get_dst_vq(inst->fh.m2m_ctx); 149 + for (i = 0; i < vq->num_buffers; i++) { 150 + struct vb2_buffer *vb = vq->bufs[i]; 151 + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 152 + 153 + if (vb->state == VB2_BUF_STATE_DEQUEUED) 154 + continue; 155 + num = scnprintf(str, sizeof(str), 156 + "capture[%2d] state = %10s, %8s\n", 157 + i, vb2_stat_name[vb->state], 158 + vpu_stat_name[vpu_get_buffer_state(vbuf)]); 159 + if (seq_write(s, str, num)) 160 + return 0; 161 + } 162 + 163 + num = scnprintf(str, sizeof(str), "sequence = %d\n", inst->sequence); 164 + if (seq_write(s, str, num)) 165 + return 0; 166 + 167 + if (inst->use_stream_buffer) { 168 + num = scnprintf(str, sizeof(str), "stream_buffer = %d / %d, <%pad, 0x%x>\n", 169 + vpu_helper_get_used_space(inst), 170 + inst->stream_buffer.length, 171 + &inst->stream_buffer.phys, 172 + inst->stream_buffer.length); 173 + if (seq_write(s, str, num)) 174 + return 0; 175 + } 176 + num = scnprintf(str, sizeof(str), "kfifo len = 0x%x\n", kfifo_len(&inst->msg_fifo)); 177 + if (seq_write(s, str, num)) 178 + return 0; 179 + 180 + num = scnprintf(str, sizeof(str), "flow :\n"); 181 + if (seq_write(s, str, num)) 182 + return 0; 183 + 184 + mutex_lock(&inst->core->cmd_lock); 185 + for (i = 0; i < ARRAY_SIZE(inst->flows); i++) { 186 + u32 idx = (inst->flow_idx + i) % (ARRAY_SIZE(inst->flows)); 187 + 188 + if (!inst->flows[idx]) 189 + continue; 190 + num = scnprintf(str, sizeof(str), "\t[%s]0x%x\n", 191 + inst->flows[idx] >= VPU_MSG_ID_NOOP ? "M" : "C", 192 + inst->flows[idx]); 193 + if (seq_write(s, str, num)) { 194 + mutex_unlock(&inst->core->cmd_lock); 195 + return 0; 196 + } 197 + } 198 + mutex_unlock(&inst->core->cmd_lock); 199 + 200 + i = 0; 201 + while (true) { 202 + num = call_vop(inst, get_debug_info, str, sizeof(str), i++); 203 + if (num <= 0) 204 + break; 205 + if (seq_write(s, str, num)) 206 + return 0; 207 + } 208 + 209 + return 0; 210 + } 211 + 212 + static int vpu_dbg_core(struct seq_file *s, void *data) 213 + { 214 + struct vpu_core *core = s->private; 215 + struct vpu_shared_addr *iface = core->iface; 216 + char str[128]; 217 + int num; 218 + 219 + num = scnprintf(str, sizeof(str), "[%s]\n", vpu_core_type_desc(core->type)); 220 + if (seq_write(s, str, num)) 221 + return 0; 222 + 223 + num = scnprintf(str, sizeof(str), "boot_region = <%pad, 0x%x>\n", 224 + &core->fw.phys, core->fw.length); 225 + if (seq_write(s, str, num)) 226 + return 0; 227 + num = scnprintf(str, sizeof(str), "rpc_region = <%pad, 0x%x> used = 0x%x\n", 228 + &core->rpc.phys, core->rpc.length, core->rpc.bytesused); 229 + if (seq_write(s, str, num)) 230 + return 0; 231 + num = scnprintf(str, sizeof(str), "fwlog_region = <%pad, 0x%x>\n", 232 + &core->log.phys, core->log.length); 233 + if (seq_write(s, str, num)) 234 + return 0; 235 + 236 + num = scnprintf(str, sizeof(str), "state = %d\n", core->state); 237 + if (seq_write(s, str, num)) 238 + return 0; 239 + if (core->state == VPU_CORE_DEINIT) 240 + return 0; 241 + num = scnprintf(str, sizeof(str), "fw version = %d.%d.%d\n", 242 + (core->fw_version >> 16) & 0xff, 243 + (core->fw_version >> 8) & 0xff, 244 + core->fw_version & 0xff); 245 + if (seq_write(s, str, num)) 246 + return 0; 247 + num = scnprintf(str, sizeof(str), "instances = %d/%d (0x%02lx), %d\n", 248 + hweight32(core->instance_mask), 249 + core->supported_instance_count, 250 + core->instance_mask, 251 + core->request_count); 252 + if (seq_write(s, str, num)) 253 + return 0; 254 + num = scnprintf(str, sizeof(str), "kfifo len = 0x%x\n", kfifo_len(&core->msg_fifo)); 255 + if (seq_write(s, str, num)) 256 + return 0; 257 + num = scnprintf(str, sizeof(str), 258 + "cmd_buf:[0x%x, 0x%x], wptr = 0x%x, rptr = 0x%x\n", 259 + iface->cmd_desc->start, 260 + iface->cmd_desc->end, 261 + iface->cmd_desc->wptr, 262 + iface->cmd_desc->rptr); 263 + if (seq_write(s, str, num)) 264 + return 0; 265 + num = scnprintf(str, sizeof(str), 266 + "msg_buf:[0x%x, 0x%x], wptr = 0x%x, rptr = 0x%x\n", 267 + iface->msg_desc->start, 268 + iface->msg_desc->end, 269 + iface->msg_desc->wptr, 270 + iface->msg_desc->rptr); 271 + if (seq_write(s, str, num)) 272 + return 0; 273 + 274 + return 0; 275 + } 276 + 277 + static int vpu_dbg_fwlog(struct seq_file *s, void *data) 278 + { 279 + struct vpu_core *core = s->private; 280 + struct print_buf_desc *print_buf; 281 + int length; 282 + u32 rptr; 283 + u32 wptr; 284 + int ret = 0; 285 + 286 + if (!core->log.virt || core->state == VPU_CORE_DEINIT) 287 + return 0; 288 + 289 + print_buf = core->log.virt; 290 + rptr = print_buf->read; 291 + wptr = print_buf->write; 292 + 293 + if (rptr == wptr) 294 + return 0; 295 + else if (rptr < wptr) 296 + length = wptr - rptr; 297 + else 298 + length = print_buf->bytes + wptr - rptr; 299 + 300 + if (s->count + length >= s->size) { 301 + s->count = s->size; 302 + return 0; 303 + } 304 + 305 + if (rptr + length >= print_buf->bytes) { 306 + int num = print_buf->bytes - rptr; 307 + 308 + if (seq_write(s, print_buf->buffer + rptr, num)) 309 + ret = -1; 310 + length -= num; 311 + rptr = 0; 312 + } 313 + 314 + if (length) { 315 + if (seq_write(s, print_buf->buffer + rptr, length)) 316 + ret = -1; 317 + rptr += length; 318 + } 319 + if (!ret) 320 + print_buf->read = rptr; 321 + 322 + return 0; 323 + } 324 + 325 + static int vpu_dbg_inst_open(struct inode *inode, struct file *filp) 326 + { 327 + return single_open(filp, vpu_dbg_instance, inode->i_private); 328 + } 329 + 330 + static ssize_t vpu_dbg_inst_write(struct file *file, 331 + const char __user *user_buf, size_t size, loff_t *ppos) 332 + { 333 + struct seq_file *s = file->private_data; 334 + struct vpu_inst *inst = s->private; 335 + 336 + vpu_session_debug(inst); 337 + 338 + return size; 339 + } 340 + 341 + static ssize_t vpu_dbg_core_write(struct file *file, 342 + const char __user *user_buf, size_t size, loff_t *ppos) 343 + { 344 + struct seq_file *s = file->private_data; 345 + struct vpu_core *core = s->private; 346 + 347 + pm_runtime_get_sync(core->dev); 348 + mutex_lock(&core->lock); 349 + if (core->state != VPU_CORE_DEINIT && !core->instance_mask) { 350 + dev_info(core->dev, "reset\n"); 351 + if (!vpu_core_sw_reset(core)) { 352 + core->state = VPU_CORE_ACTIVE; 353 + core->hang_mask = 0; 354 + } 355 + } 356 + mutex_unlock(&core->lock); 357 + pm_runtime_put_sync(core->dev); 358 + 359 + return size; 360 + } 361 + 362 + static int vpu_dbg_core_open(struct inode *inode, struct file *filp) 363 + { 364 + return single_open(filp, vpu_dbg_core, inode->i_private); 365 + } 366 + 367 + static int vpu_dbg_fwlog_open(struct inode *inode, struct file *filp) 368 + { 369 + return single_open(filp, vpu_dbg_fwlog, inode->i_private); 370 + } 371 + 372 + static const struct file_operations vpu_dbg_inst_fops = { 373 + .owner = THIS_MODULE, 374 + .open = vpu_dbg_inst_open, 375 + .release = single_release, 376 + .read = seq_read, 377 + .write = vpu_dbg_inst_write, 378 + }; 379 + 380 + static const struct file_operations vpu_dbg_core_fops = { 381 + .owner = THIS_MODULE, 382 + .open = vpu_dbg_core_open, 383 + .release = single_release, 384 + .read = seq_read, 385 + .write = vpu_dbg_core_write, 386 + }; 387 + 388 + static const struct file_operations vpu_dbg_fwlog_fops = { 389 + .owner = THIS_MODULE, 390 + .open = vpu_dbg_fwlog_open, 391 + .release = single_release, 392 + .read = seq_read, 393 + }; 394 + 395 + int vpu_inst_create_dbgfs_file(struct vpu_inst *inst) 396 + { 397 + struct vpu_dev *vpu; 398 + char name[64]; 399 + 400 + if (!inst || !inst->core || !inst->core->vpu) 401 + return -EINVAL; 402 + 403 + vpu = inst->core->vpu; 404 + if (!vpu->debugfs) 405 + return -EINVAL; 406 + 407 + if (inst->debugfs) 408 + return 0; 409 + 410 + scnprintf(name, sizeof(name), "instance.%d.%d", inst->core->id, inst->id); 411 + inst->debugfs = debugfs_create_file((const char *)name, 412 + VERIFY_OCTAL_PERMISSIONS(0644), 413 + vpu->debugfs, 414 + inst, 415 + &vpu_dbg_inst_fops); 416 + if (!inst->debugfs) { 417 + dev_err(inst->dev, "vpu create debugfs %s fail\n", name); 418 + return -EINVAL; 419 + } 420 + 421 + return 0; 422 + } 423 + 424 + int vpu_inst_remove_dbgfs_file(struct vpu_inst *inst) 425 + { 426 + if (!inst) 427 + return 0; 428 + 429 + debugfs_remove(inst->debugfs); 430 + inst->debugfs = NULL; 431 + 432 + return 0; 433 + } 434 + 435 + int vpu_core_create_dbgfs_file(struct vpu_core *core) 436 + { 437 + struct vpu_dev *vpu; 438 + char name[64]; 439 + 440 + if (!core || !core->vpu) 441 + return -EINVAL; 442 + 443 + vpu = core->vpu; 444 + if (!vpu->debugfs) 445 + return -EINVAL; 446 + 447 + if (!core->debugfs) { 448 + scnprintf(name, sizeof(name), "core.%d", core->id); 449 + core->debugfs = debugfs_create_file((const char *)name, 450 + VERIFY_OCTAL_PERMISSIONS(0644), 451 + vpu->debugfs, 452 + core, 453 + &vpu_dbg_core_fops); 454 + if (!core->debugfs) { 455 + dev_err(core->dev, "vpu create debugfs %s fail\n", name); 456 + return -EINVAL; 457 + } 458 + } 459 + if (!core->debugfs_fwlog) { 460 + scnprintf(name, sizeof(name), "fwlog.%d", core->id); 461 + core->debugfs_fwlog = debugfs_create_file((const char *)name, 462 + VERIFY_OCTAL_PERMISSIONS(0444), 463 + vpu->debugfs, 464 + core, 465 + &vpu_dbg_fwlog_fops); 466 + if (!core->debugfs_fwlog) { 467 + dev_err(core->dev, "vpu create debugfs %s fail\n", name); 468 + return -EINVAL; 469 + } 470 + } 471 + 472 + return 0; 473 + } 474 + 475 + int vpu_core_remove_dbgfs_file(struct vpu_core *core) 476 + { 477 + if (!core) 478 + return 0; 479 + debugfs_remove(core->debugfs); 480 + core->debugfs = NULL; 481 + debugfs_remove(core->debugfs_fwlog); 482 + core->debugfs_fwlog = NULL; 483 + 484 + return 0; 485 + } 486 + 487 + void vpu_inst_record_flow(struct vpu_inst *inst, u32 flow) 488 + { 489 + if (!inst) 490 + return; 491 + 492 + inst->flows[inst->flow_idx] = flow; 493 + inst->flow_idx = (inst->flow_idx + 1) % (ARRAY_SIZE(inst->flows)); 494 + }
+187
drivers/media/platform/amphion/vpu_defs.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Copyright 2020-2021 NXP 4 + */ 5 + 6 + #ifndef _AMPHION_VPU_DEFS_H 7 + #define _AMPHION_VPU_DEFS_H 8 + 9 + enum MSG_TYPE { 10 + INIT_DONE = 1, 11 + PRC_BUF_OFFSET, 12 + BOOT_ADDRESS, 13 + COMMAND, 14 + EVENT, 15 + }; 16 + 17 + enum { 18 + VPU_IRQ_CODE_BOOT_DONE = 0x55, 19 + VPU_IRQ_CODE_SNAPSHOT_DONE = 0xa5, 20 + VPU_IRQ_CODE_SYNC = 0xaa, 21 + }; 22 + 23 + enum { 24 + VPU_CMD_ID_NOOP = 0x0, 25 + VPU_CMD_ID_CONFIGURE_CODEC, 26 + VPU_CMD_ID_START, 27 + VPU_CMD_ID_STOP, 28 + VPU_CMD_ID_ABORT, 29 + VPU_CMD_ID_RST_BUF, 30 + VPU_CMD_ID_SNAPSHOT, 31 + VPU_CMD_ID_FIRM_RESET, 32 + VPU_CMD_ID_UPDATE_PARAMETER, 33 + VPU_CMD_ID_FRAME_ENCODE, 34 + VPU_CMD_ID_SKIP, 35 + VPU_CMD_ID_PARSE_NEXT_SEQ, 36 + VPU_CMD_ID_PARSE_NEXT_I, 37 + VPU_CMD_ID_PARSE_NEXT_IP, 38 + VPU_CMD_ID_PARSE_NEXT_ANY, 39 + VPU_CMD_ID_DEC_PIC, 40 + VPU_CMD_ID_FS_ALLOC, 41 + VPU_CMD_ID_FS_RELEASE, 42 + VPU_CMD_ID_TIMESTAMP, 43 + VPU_CMD_ID_DEBUG 44 + }; 45 + 46 + enum { 47 + VPU_MSG_ID_NOOP = 0x100, 48 + VPU_MSG_ID_RESET_DONE, 49 + VPU_MSG_ID_START_DONE, 50 + VPU_MSG_ID_STOP_DONE, 51 + VPU_MSG_ID_ABORT_DONE, 52 + VPU_MSG_ID_BUF_RST, 53 + VPU_MSG_ID_MEM_REQUEST, 54 + VPU_MSG_ID_PARAM_UPD_DONE, 55 + VPU_MSG_ID_FRAME_INPUT_DONE, 56 + VPU_MSG_ID_ENC_DONE, 57 + VPU_MSG_ID_DEC_DONE, 58 + VPU_MSG_ID_FRAME_REQ, 59 + VPU_MSG_ID_FRAME_RELEASE, 60 + VPU_MSG_ID_SEQ_HDR_FOUND, 61 + VPU_MSG_ID_RES_CHANGE, 62 + VPU_MSG_ID_PIC_HDR_FOUND, 63 + VPU_MSG_ID_PIC_DECODED, 64 + VPU_MSG_ID_PIC_EOS, 65 + VPU_MSG_ID_FIFO_LOW, 66 + VPU_MSG_ID_FIFO_HIGH, 67 + VPU_MSG_ID_FIFO_EMPTY, 68 + VPU_MSG_ID_FIFO_FULL, 69 + VPU_MSG_ID_BS_ERROR, 70 + VPU_MSG_ID_UNSUPPORTED, 71 + VPU_MSG_ID_TIMESTAMP_INFO, 72 + 73 + VPU_MSG_ID_FIRMWARE_XCPT, 74 + }; 75 + 76 + enum VPU_ENC_MEMORY_RESOURSE { 77 + MEM_RES_ENC, 78 + MEM_RES_REF, 79 + MEM_RES_ACT 80 + }; 81 + 82 + enum VPU_DEC_MEMORY_RESOURCE { 83 + MEM_RES_FRAME, 84 + MEM_RES_MBI, 85 + MEM_RES_DCP 86 + }; 87 + 88 + enum VPU_SCODE_TYPE { 89 + SCODE_PADDING_EOS = 1, 90 + SCODE_PADDING_BUFFLUSH = 2, 91 + SCODE_PADDING_ABORT = 3, 92 + SCODE_SEQUENCE = 0x31, 93 + SCODE_PICTURE = 0x32, 94 + SCODE_SLICE = 0x33 95 + }; 96 + 97 + struct vpu_pkt_mem_req_data { 98 + u32 enc_frame_size; 99 + u32 enc_frame_num; 100 + u32 ref_frame_size; 101 + u32 ref_frame_num; 102 + u32 act_buf_size; 103 + u32 act_buf_num; 104 + }; 105 + 106 + struct vpu_enc_pic_info { 107 + u32 frame_id; 108 + u32 pic_type; 109 + u32 skipped_frame; 110 + u32 error_flag; 111 + u32 psnr; 112 + u32 frame_size; 113 + u32 wptr; 114 + u32 crc; 115 + s64 timestamp; 116 + }; 117 + 118 + struct vpu_dec_codec_info { 119 + u32 pixfmt; 120 + u32 num_ref_frms; 121 + u32 num_dpb_frms; 122 + u32 num_dfe_area; 123 + u32 color_primaries; 124 + u32 transfer_chars; 125 + u32 matrix_coeffs; 126 + u32 full_range; 127 + u32 vui_present; 128 + u32 progressive; 129 + u32 width; 130 + u32 height; 131 + u32 decoded_width; 132 + u32 decoded_height; 133 + struct v4l2_fract frame_rate; 134 + u32 dsp_asp_ratio; 135 + u32 level_idc; 136 + u32 bit_depth_luma; 137 + u32 bit_depth_chroma; 138 + u32 chroma_fmt; 139 + u32 mvc_num_views; 140 + u32 offset_x; 141 + u32 offset_y; 142 + u32 tag; 143 + u32 sizeimage[VIDEO_MAX_PLANES]; 144 + u32 bytesperline[VIDEO_MAX_PLANES]; 145 + u32 mbi_size; 146 + u32 dcp_size; 147 + u32 stride; 148 + }; 149 + 150 + struct vpu_dec_pic_info { 151 + u32 id; 152 + u32 luma; 153 + u32 start; 154 + u32 end; 155 + u32 pic_size; 156 + u32 stride; 157 + u32 skipped; 158 + s64 timestamp; 159 + u32 consumed_count; 160 + }; 161 + 162 + struct vpu_fs_info { 163 + u32 id; 164 + u32 type; 165 + u32 tag; 166 + u32 luma_addr; 167 + u32 luma_size; 168 + u32 chroma_addr; 169 + u32 chromau_size; 170 + u32 chromav_addr; 171 + u32 chromav_size; 172 + u32 bytesperline; 173 + u32 not_displayed; 174 + }; 175 + 176 + struct vpu_ts_info { 177 + s64 timestamp; 178 + u32 size; 179 + }; 180 + 181 + #define BITRATE_STEP (1024) 182 + #define BITRATE_MIN (16 * BITRATE_STEP) 183 + #define BITRATE_MAX (240 * 1024 * BITRATE_STEP) 184 + #define BITRATE_DEFAULT (2 * 1024 * BITRATE_STEP) 185 + #define BITRATE_DEFAULT_PEAK (BITRATE_DEFAULT * 2) 186 + 187 + #endif
+260
drivers/media/platform/amphion/vpu_drv.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright 2020-2021 NXP 4 + */ 5 + 6 + #include <linux/init.h> 7 + #include <linux/interconnect.h> 8 + #include <linux/ioctl.h> 9 + #include <linux/list.h> 10 + #include <linux/kernel.h> 11 + #include <linux/module.h> 12 + #include <linux/dma-map-ops.h> 13 + #include <linux/of_device.h> 14 + #include <linux/of_address.h> 15 + #include <linux/platform_device.h> 16 + #include <linux/slab.h> 17 + #include <linux/types.h> 18 + #include <linux/pm_runtime.h> 19 + #include <linux/videodev2.h> 20 + #include <linux/of_reserved_mem.h> 21 + #include <media/v4l2-device.h> 22 + #include <media/videobuf2-v4l2.h> 23 + #include <media/v4l2-mem2mem.h> 24 + #include <media/v4l2-ioctl.h> 25 + #include <linux/debugfs.h> 26 + #include "vpu.h" 27 + #include "vpu_imx8q.h" 28 + 29 + bool debug; 30 + module_param(debug, bool, 0644); 31 + 32 + void vpu_writel(struct vpu_dev *vpu, u32 reg, u32 val) 33 + { 34 + writel(val, vpu->base + reg); 35 + } 36 + 37 + u32 vpu_readl(struct vpu_dev *vpu, u32 reg) 38 + { 39 + return readl(vpu->base + reg); 40 + } 41 + 42 + static void vpu_dev_get(struct vpu_dev *vpu) 43 + { 44 + if (atomic_inc_return(&vpu->ref_vpu) == 1 && vpu->res->setup) 45 + vpu->res->setup(vpu); 46 + } 47 + 48 + static void vpu_dev_put(struct vpu_dev *vpu) 49 + { 50 + atomic_dec(&vpu->ref_vpu); 51 + } 52 + 53 + static void vpu_enc_get(struct vpu_dev *vpu) 54 + { 55 + if (atomic_inc_return(&vpu->ref_enc) == 1 && vpu->res->setup_encoder) 56 + vpu->res->setup_encoder(vpu); 57 + } 58 + 59 + static void vpu_enc_put(struct vpu_dev *vpu) 60 + { 61 + atomic_dec(&vpu->ref_enc); 62 + } 63 + 64 + static void vpu_dec_get(struct vpu_dev *vpu) 65 + { 66 + if (atomic_inc_return(&vpu->ref_dec) == 1 && vpu->res->setup_decoder) 67 + vpu->res->setup_decoder(vpu); 68 + } 69 + 70 + static void vpu_dec_put(struct vpu_dev *vpu) 71 + { 72 + atomic_dec(&vpu->ref_dec); 73 + } 74 + 75 + static int vpu_init_media_device(struct vpu_dev *vpu) 76 + { 77 + vpu->mdev.dev = vpu->dev; 78 + strscpy(vpu->mdev.model, "amphion-vpu", sizeof(vpu->mdev.model)); 79 + strscpy(vpu->mdev.bus_info, "platform: amphion-vpu", sizeof(vpu->mdev.bus_info)); 80 + media_device_init(&vpu->mdev); 81 + vpu->v4l2_dev.mdev = &vpu->mdev; 82 + 83 + return 0; 84 + } 85 + 86 + static int vpu_probe(struct platform_device *pdev) 87 + { 88 + struct device *dev = &pdev->dev; 89 + struct vpu_dev *vpu; 90 + int ret; 91 + 92 + dev_dbg(dev, "probe\n"); 93 + vpu = devm_kzalloc(dev, sizeof(*vpu), GFP_KERNEL); 94 + if (!vpu) 95 + return -ENOMEM; 96 + 97 + vpu->pdev = pdev; 98 + vpu->dev = dev; 99 + mutex_init(&vpu->lock); 100 + INIT_LIST_HEAD(&vpu->cores); 101 + platform_set_drvdata(pdev, vpu); 102 + atomic_set(&vpu->ref_vpu, 0); 103 + atomic_set(&vpu->ref_enc, 0); 104 + atomic_set(&vpu->ref_dec, 0); 105 + vpu->get_vpu = vpu_dev_get; 106 + vpu->put_vpu = vpu_dev_put; 107 + vpu->get_enc = vpu_enc_get; 108 + vpu->put_enc = vpu_enc_put; 109 + vpu->get_dec = vpu_dec_get; 110 + vpu->put_dec = vpu_dec_put; 111 + 112 + vpu->base = devm_platform_ioremap_resource(pdev, 0); 113 + if (IS_ERR(vpu->base)) 114 + return PTR_ERR(vpu->base); 115 + 116 + vpu->res = of_device_get_match_data(dev); 117 + if (!vpu->res) 118 + return -ENODEV; 119 + 120 + pm_runtime_enable(dev); 121 + ret = pm_runtime_get_sync(dev); 122 + if (ret) 123 + goto err_runtime_disable; 124 + 125 + pm_runtime_put_sync(dev); 126 + 127 + ret = v4l2_device_register(dev, &vpu->v4l2_dev); 128 + if (ret) 129 + goto err_vpu_deinit; 130 + 131 + vpu_init_media_device(vpu); 132 + vpu->encoder.type = VPU_CORE_TYPE_ENC; 133 + vpu->encoder.function = MEDIA_ENT_F_PROC_VIDEO_ENCODER; 134 + vpu->decoder.type = VPU_CORE_TYPE_DEC; 135 + vpu->decoder.function = MEDIA_ENT_F_PROC_VIDEO_DECODER; 136 + vpu_add_func(vpu, &vpu->decoder); 137 + vpu_add_func(vpu, &vpu->encoder); 138 + ret = media_device_register(&vpu->mdev); 139 + if (ret) 140 + goto err_vpu_media; 141 + vpu->debugfs = debugfs_create_dir("amphion_vpu", NULL); 142 + 143 + of_platform_populate(dev->of_node, NULL, NULL, dev); 144 + 145 + return 0; 146 + 147 + err_vpu_media: 148 + vpu_remove_func(&vpu->encoder); 149 + vpu_remove_func(&vpu->decoder); 150 + v4l2_device_unregister(&vpu->v4l2_dev); 151 + err_vpu_deinit: 152 + err_runtime_disable: 153 + pm_runtime_set_suspended(dev); 154 + pm_runtime_disable(dev); 155 + 156 + return ret; 157 + } 158 + 159 + static int vpu_remove(struct platform_device *pdev) 160 + { 161 + struct vpu_dev *vpu = platform_get_drvdata(pdev); 162 + struct device *dev = &pdev->dev; 163 + 164 + debugfs_remove_recursive(vpu->debugfs); 165 + vpu->debugfs = NULL; 166 + 167 + pm_runtime_disable(dev); 168 + 169 + media_device_unregister(&vpu->mdev); 170 + vpu_remove_func(&vpu->decoder); 171 + vpu_remove_func(&vpu->encoder); 172 + media_device_cleanup(&vpu->mdev); 173 + v4l2_device_unregister(&vpu->v4l2_dev); 174 + mutex_destroy(&vpu->lock); 175 + 176 + return 0; 177 + } 178 + 179 + static int __maybe_unused vpu_runtime_resume(struct device *dev) 180 + { 181 + return 0; 182 + } 183 + 184 + static int __maybe_unused vpu_runtime_suspend(struct device *dev) 185 + { 186 + return 0; 187 + } 188 + 189 + static int __maybe_unused vpu_resume(struct device *dev) 190 + { 191 + return 0; 192 + } 193 + 194 + static int __maybe_unused vpu_suspend(struct device *dev) 195 + { 196 + return 0; 197 + } 198 + 199 + static const struct dev_pm_ops vpu_pm_ops = { 200 + SET_RUNTIME_PM_OPS(vpu_runtime_suspend, vpu_runtime_resume, NULL) 201 + SET_SYSTEM_SLEEP_PM_OPS(vpu_suspend, vpu_resume) 202 + }; 203 + 204 + static struct vpu_resources imx8qxp_res = { 205 + .plat_type = IMX8QXP, 206 + .mreg_base = 0x40000000, 207 + .setup = vpu_imx8q_setup, 208 + .setup_encoder = vpu_imx8q_setup_enc, 209 + .setup_decoder = vpu_imx8q_setup_dec, 210 + .reset = vpu_imx8q_reset 211 + }; 212 + 213 + static struct vpu_resources imx8qm_res = { 214 + .plat_type = IMX8QM, 215 + .mreg_base = 0x40000000, 216 + .setup = vpu_imx8q_setup, 217 + .setup_encoder = vpu_imx8q_setup_enc, 218 + .setup_decoder = vpu_imx8q_setup_dec, 219 + .reset = vpu_imx8q_reset 220 + }; 221 + 222 + static const struct of_device_id vpu_dt_match[] = { 223 + { .compatible = "nxp,imx8qxp-vpu", .data = &imx8qxp_res }, 224 + { .compatible = "nxp,imx8qm-vpu", .data = &imx8qm_res }, 225 + {} 226 + }; 227 + MODULE_DEVICE_TABLE(of, vpu_dt_match); 228 + 229 + static struct platform_driver amphion_vpu_driver = { 230 + .probe = vpu_probe, 231 + .remove = vpu_remove, 232 + .driver = { 233 + .name = "amphion-vpu", 234 + .of_match_table = vpu_dt_match, 235 + .pm = &vpu_pm_ops, 236 + }, 237 + }; 238 + 239 + static int __init vpu_driver_init(void) 240 + { 241 + int ret; 242 + 243 + ret = platform_driver_register(&amphion_vpu_driver); 244 + if (ret) 245 + return ret; 246 + 247 + return vpu_core_driver_init(); 248 + } 249 + 250 + static void __exit vpu_driver_exit(void) 251 + { 252 + vpu_core_driver_exit(); 253 + platform_driver_unregister(&amphion_vpu_driver); 254 + } 255 + module_init(vpu_driver_init); 256 + module_exit(vpu_driver_exit); 257 + 258 + MODULE_AUTHOR("Freescale Semiconductor, Inc."); 259 + MODULE_DESCRIPTION("Linux VPU driver for Freescale i.MX8Q"); 260 + MODULE_LICENSE("GPL v2");
+413
drivers/media/platform/amphion/vpu_helpers.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright 2020-2021 NXP 4 + */ 5 + 6 + #include <linux/init.h> 7 + #include <linux/interconnect.h> 8 + #include <linux/ioctl.h> 9 + #include <linux/list.h> 10 + #include <linux/kernel.h> 11 + #include <linux/module.h> 12 + #include <linux/platform_device.h> 13 + #include "vpu.h" 14 + #include "vpu_core.h" 15 + #include "vpu_rpc.h" 16 + #include "vpu_helpers.h" 17 + 18 + int vpu_helper_find_in_array_u8(const u8 *array, u32 size, u32 x) 19 + { 20 + int i; 21 + 22 + for (i = 0; i < size; i++) { 23 + if (array[i] == x) 24 + return i; 25 + } 26 + 27 + return 0; 28 + } 29 + 30 + bool vpu_helper_check_type(struct vpu_inst *inst, u32 type) 31 + { 32 + const struct vpu_format *pfmt; 33 + 34 + for (pfmt = inst->formats; pfmt->pixfmt; pfmt++) { 35 + if (!vpu_iface_check_format(inst, pfmt->pixfmt)) 36 + continue; 37 + if (pfmt->type == type) 38 + return true; 39 + } 40 + 41 + return false; 42 + } 43 + 44 + const struct vpu_format *vpu_helper_find_format(struct vpu_inst *inst, u32 type, u32 pixelfmt) 45 + { 46 + const struct vpu_format *pfmt; 47 + 48 + if (!inst || !inst->formats) 49 + return NULL; 50 + 51 + if (!vpu_iface_check_format(inst, pixelfmt)) 52 + return NULL; 53 + 54 + for (pfmt = inst->formats; pfmt->pixfmt; pfmt++) { 55 + if (pfmt->pixfmt == pixelfmt && (!type || type == pfmt->type)) 56 + return pfmt; 57 + } 58 + 59 + return NULL; 60 + } 61 + 62 + const struct vpu_format *vpu_helper_enum_format(struct vpu_inst *inst, u32 type, int index) 63 + { 64 + const struct vpu_format *pfmt; 65 + int i = 0; 66 + 67 + if (!inst || !inst->formats) 68 + return NULL; 69 + 70 + for (pfmt = inst->formats; pfmt->pixfmt; pfmt++) { 71 + if (!vpu_iface_check_format(inst, pfmt->pixfmt)) 72 + continue; 73 + 74 + if (pfmt->type == type) { 75 + if (index == i) 76 + return pfmt; 77 + i++; 78 + } 79 + } 80 + 81 + return NULL; 82 + } 83 + 84 + u32 vpu_helper_valid_frame_width(struct vpu_inst *inst, u32 width) 85 + { 86 + const struct vpu_core_resources *res; 87 + 88 + if (!inst) 89 + return width; 90 + 91 + res = vpu_get_resource(inst); 92 + if (!res) 93 + return width; 94 + if (res->max_width) 95 + width = clamp(width, res->min_width, res->max_width); 96 + if (res->step_width) 97 + width = ALIGN(width, res->step_width); 98 + 99 + return width; 100 + } 101 + 102 + u32 vpu_helper_valid_frame_height(struct vpu_inst *inst, u32 height) 103 + { 104 + const struct vpu_core_resources *res; 105 + 106 + if (!inst) 107 + return height; 108 + 109 + res = vpu_get_resource(inst); 110 + if (!res) 111 + return height; 112 + if (res->max_height) 113 + height = clamp(height, res->min_height, res->max_height); 114 + if (res->step_height) 115 + height = ALIGN(height, res->step_height); 116 + 117 + return height; 118 + } 119 + 120 + static u32 get_nv12_plane_size(u32 width, u32 height, int plane_no, 121 + u32 stride, u32 interlaced, u32 *pbl) 122 + { 123 + u32 bytesperline; 124 + u32 size = 0; 125 + 126 + bytesperline = ALIGN(width, stride); 127 + if (pbl) 128 + bytesperline = max(bytesperline, *pbl); 129 + height = ALIGN(height, 2); 130 + if (plane_no == 0) 131 + size = bytesperline * height; 132 + else if (plane_no == 1) 133 + size = bytesperline * height >> 1; 134 + if (pbl) 135 + *pbl = bytesperline; 136 + 137 + return size; 138 + } 139 + 140 + static u32 get_tiled_8l128_plane_size(u32 fmt, u32 width, u32 height, int plane_no, 141 + u32 stride, u32 interlaced, u32 *pbl) 142 + { 143 + u32 ws = 3; 144 + u32 hs = 7; 145 + u32 bitdepth = 8; 146 + u32 bytesperline; 147 + u32 size = 0; 148 + 149 + if (interlaced) 150 + hs++; 151 + if (fmt == V4L2_PIX_FMT_NV12M_10BE_8L128) 152 + bitdepth = 10; 153 + bytesperline = DIV_ROUND_UP(width * bitdepth, BITS_PER_BYTE); 154 + bytesperline = ALIGN(bytesperline, 1 << ws); 155 + bytesperline = ALIGN(bytesperline, stride); 156 + if (pbl) 157 + bytesperline = max(bytesperline, *pbl); 158 + height = ALIGN(height, 1 << hs); 159 + if (plane_no == 0) 160 + size = bytesperline * height; 161 + else if (plane_no == 1) 162 + size = (bytesperline * ALIGN(height, 1 << (hs + 1))) >> 1; 163 + if (pbl) 164 + *pbl = bytesperline; 165 + 166 + return size; 167 + } 168 + 169 + static u32 get_default_plane_size(u32 width, u32 height, int plane_no, 170 + u32 stride, u32 interlaced, u32 *pbl) 171 + { 172 + u32 bytesperline; 173 + u32 size = 0; 174 + 175 + bytesperline = ALIGN(width, stride); 176 + if (pbl) 177 + bytesperline = max(bytesperline, *pbl); 178 + if (plane_no == 0) 179 + size = bytesperline * height; 180 + if (pbl) 181 + *pbl = bytesperline; 182 + 183 + return size; 184 + } 185 + 186 + u32 vpu_helper_get_plane_size(u32 fmt, u32 w, u32 h, int plane_no, 187 + u32 stride, u32 interlaced, u32 *pbl) 188 + { 189 + switch (fmt) { 190 + case V4L2_PIX_FMT_NV12M: 191 + return get_nv12_plane_size(w, h, plane_no, stride, interlaced, pbl); 192 + case V4L2_PIX_FMT_NV12M_8L128: 193 + case V4L2_PIX_FMT_NV12M_10BE_8L128: 194 + return get_tiled_8l128_plane_size(fmt, w, h, plane_no, stride, interlaced, pbl); 195 + default: 196 + return get_default_plane_size(w, h, plane_no, stride, interlaced, pbl); 197 + } 198 + } 199 + 200 + u32 vpu_helper_copy_from_stream_buffer(struct vpu_buffer *stream_buffer, 201 + u32 *rptr, u32 size, void *dst) 202 + { 203 + u32 offset; 204 + u32 start; 205 + u32 end; 206 + void *virt; 207 + 208 + if (!stream_buffer || !rptr || !dst) 209 + return -EINVAL; 210 + 211 + if (!size) 212 + return 0; 213 + 214 + offset = *rptr; 215 + start = stream_buffer->phys; 216 + end = start + stream_buffer->length; 217 + virt = stream_buffer->virt; 218 + 219 + if (offset < start || offset > end) 220 + return -EINVAL; 221 + 222 + if (offset + size <= end) { 223 + memcpy(dst, virt + (offset - start), size); 224 + } else { 225 + memcpy(dst, virt + (offset - start), end - offset); 226 + memcpy(dst + end - offset, virt, size + offset - end); 227 + } 228 + 229 + *rptr = vpu_helper_step_walk(stream_buffer, offset, size); 230 + return size; 231 + } 232 + 233 + u32 vpu_helper_copy_to_stream_buffer(struct vpu_buffer *stream_buffer, 234 + u32 *wptr, u32 size, void *src) 235 + { 236 + u32 offset; 237 + u32 start; 238 + u32 end; 239 + void *virt; 240 + 241 + if (!stream_buffer || !wptr || !src) 242 + return -EINVAL; 243 + 244 + if (!size) 245 + return 0; 246 + 247 + offset = *wptr; 248 + start = stream_buffer->phys; 249 + end = start + stream_buffer->length; 250 + virt = stream_buffer->virt; 251 + if (offset < start || offset > end) 252 + return -EINVAL; 253 + 254 + if (offset + size <= end) { 255 + memcpy(virt + (offset - start), src, size); 256 + } else { 257 + memcpy(virt + (offset - start), src, end - offset); 258 + memcpy(virt, src + end - offset, size + offset - end); 259 + } 260 + 261 + *wptr = vpu_helper_step_walk(stream_buffer, offset, size); 262 + 263 + return size; 264 + } 265 + 266 + u32 vpu_helper_memset_stream_buffer(struct vpu_buffer *stream_buffer, 267 + u32 *wptr, u8 val, u32 size) 268 + { 269 + u32 offset; 270 + u32 start; 271 + u32 end; 272 + void *virt; 273 + 274 + if (!stream_buffer || !wptr) 275 + return -EINVAL; 276 + 277 + if (!size) 278 + return 0; 279 + 280 + offset = *wptr; 281 + start = stream_buffer->phys; 282 + end = start + stream_buffer->length; 283 + virt = stream_buffer->virt; 284 + if (offset < start || offset > end) 285 + return -EINVAL; 286 + 287 + if (offset + size <= end) { 288 + memset(virt + (offset - start), val, size); 289 + } else { 290 + memset(virt + (offset - start), val, end - offset); 291 + memset(virt, val, size + offset - end); 292 + } 293 + 294 + offset += size; 295 + if (offset >= end) 296 + offset -= stream_buffer->length; 297 + 298 + *wptr = offset; 299 + 300 + return size; 301 + } 302 + 303 + u32 vpu_helper_get_free_space(struct vpu_inst *inst) 304 + { 305 + struct vpu_rpc_buffer_desc desc; 306 + 307 + if (vpu_iface_get_stream_buffer_desc(inst, &desc)) 308 + return 0; 309 + 310 + if (desc.rptr > desc.wptr) 311 + return desc.rptr - desc.wptr; 312 + else if (desc.rptr < desc.wptr) 313 + return (desc.end - desc.start + desc.rptr - desc.wptr); 314 + else 315 + return desc.end - desc.start; 316 + } 317 + 318 + u32 vpu_helper_get_used_space(struct vpu_inst *inst) 319 + { 320 + struct vpu_rpc_buffer_desc desc; 321 + 322 + if (vpu_iface_get_stream_buffer_desc(inst, &desc)) 323 + return 0; 324 + 325 + if (desc.wptr > desc.rptr) 326 + return desc.wptr - desc.rptr; 327 + else if (desc.wptr < desc.rptr) 328 + return (desc.end - desc.start + desc.wptr - desc.rptr); 329 + else 330 + return 0; 331 + } 332 + 333 + int vpu_helper_g_volatile_ctrl(struct v4l2_ctrl *ctrl) 334 + { 335 + struct vpu_inst *inst = ctrl_to_inst(ctrl); 336 + 337 + switch (ctrl->id) { 338 + case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: 339 + ctrl->val = inst->min_buffer_cap; 340 + break; 341 + case V4L2_CID_MIN_BUFFERS_FOR_OUTPUT: 342 + ctrl->val = inst->min_buffer_out; 343 + break; 344 + default: 345 + return -EINVAL; 346 + } 347 + 348 + return 0; 349 + } 350 + 351 + int vpu_helper_find_startcode(struct vpu_buffer *stream_buffer, 352 + u32 pixelformat, u32 offset, u32 bytesused) 353 + { 354 + u32 start_code; 355 + int start_code_size; 356 + u32 val = 0; 357 + int i; 358 + int ret = -EINVAL; 359 + 360 + if (!stream_buffer || !stream_buffer->virt) 361 + return -EINVAL; 362 + 363 + switch (pixelformat) { 364 + case V4L2_PIX_FMT_H264: 365 + start_code_size = 4; 366 + start_code = 0x00000001; 367 + break; 368 + default: 369 + return 0; 370 + } 371 + 372 + for (i = 0; i < bytesused; i++) { 373 + val = (val << 8) | vpu_helper_read_byte(stream_buffer, offset + i); 374 + if (i < start_code_size - 1) 375 + continue; 376 + if (val == start_code) { 377 + ret = i + 1 - start_code_size; 378 + break; 379 + } 380 + } 381 + 382 + return ret; 383 + } 384 + 385 + int vpu_find_dst_by_src(struct vpu_pair *pairs, u32 cnt, u32 src) 386 + { 387 + u32 i; 388 + 389 + if (!pairs || !cnt) 390 + return -EINVAL; 391 + 392 + for (i = 0; i < cnt; i++) { 393 + if (pairs[i].src == src) 394 + return pairs[i].dst; 395 + } 396 + 397 + return -EINVAL; 398 + } 399 + 400 + int vpu_find_src_by_dst(struct vpu_pair *pairs, u32 cnt, u32 dst) 401 + { 402 + u32 i; 403 + 404 + if (!pairs || !cnt) 405 + return -EINVAL; 406 + 407 + for (i = 0; i < cnt; i++) { 408 + if (pairs[i].dst == dst) 409 + return pairs[i].src; 410 + } 411 + 412 + return -EINVAL; 413 + }
+74
drivers/media/platform/amphion/vpu_helpers.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Copyright 2020-2021 NXP 4 + */ 5 + 6 + #ifndef _AMPHION_VPU_HELPERS_H 7 + #define _AMPHION_VPU_HELPERS_H 8 + 9 + struct vpu_pair { 10 + u32 src; 11 + u32 dst; 12 + }; 13 + 14 + #define MAKE_TIMESTAMP(s, ns) (((s32)(s) * NSEC_PER_SEC) + (ns)) 15 + #define VPU_INVALID_TIMESTAMP MAKE_TIMESTAMP(-1, 0) 16 + 17 + int vpu_helper_find_in_array_u8(const u8 *array, u32 size, u32 x); 18 + bool vpu_helper_check_type(struct vpu_inst *inst, u32 type); 19 + const struct vpu_format *vpu_helper_find_format(struct vpu_inst *inst, u32 type, u32 pixelfmt); 20 + const struct vpu_format *vpu_helper_enum_format(struct vpu_inst *inst, u32 type, int index); 21 + u32 vpu_helper_valid_frame_width(struct vpu_inst *inst, u32 width); 22 + u32 vpu_helper_valid_frame_height(struct vpu_inst *inst, u32 height); 23 + u32 vpu_helper_get_plane_size(u32 fmt, u32 width, u32 height, int plane_no, 24 + u32 stride, u32 interlaced, u32 *pbl); 25 + u32 vpu_helper_copy_from_stream_buffer(struct vpu_buffer *stream_buffer, 26 + u32 *rptr, u32 size, void *dst); 27 + u32 vpu_helper_copy_to_stream_buffer(struct vpu_buffer *stream_buffer, 28 + u32 *wptr, u32 size, void *src); 29 + u32 vpu_helper_memset_stream_buffer(struct vpu_buffer *stream_buffer, 30 + u32 *wptr, u8 val, u32 size); 31 + u32 vpu_helper_get_free_space(struct vpu_inst *inst); 32 + u32 vpu_helper_get_used_space(struct vpu_inst *inst); 33 + int vpu_helper_g_volatile_ctrl(struct v4l2_ctrl *ctrl); 34 + void vpu_helper_get_kmp_next(const u8 *pattern, int *next, int size); 35 + int vpu_helper_kmp_search(u8 *s, int s_len, const u8 *p, int p_len, int *next); 36 + int vpu_helper_kmp_search_in_stream_buffer(struct vpu_buffer *stream_buffer, 37 + u32 offset, int bytesused, 38 + const u8 *p, int p_len, int *next); 39 + int vpu_helper_find_startcode(struct vpu_buffer *stream_buffer, 40 + u32 pixelformat, u32 offset, u32 bytesused); 41 + 42 + static inline u32 vpu_helper_step_walk(struct vpu_buffer *stream_buffer, u32 pos, u32 step) 43 + { 44 + pos += step; 45 + if (pos > stream_buffer->phys + stream_buffer->length) 46 + pos -= stream_buffer->length; 47 + 48 + return pos; 49 + } 50 + 51 + static inline u8 vpu_helper_read_byte(struct vpu_buffer *stream_buffer, u32 pos) 52 + { 53 + u8 *pdata = (u8 *)stream_buffer->virt; 54 + 55 + return pdata[pos % stream_buffer->length]; 56 + } 57 + 58 + int vpu_color_check_primaries(u32 primaries); 59 + int vpu_color_check_transfers(u32 transfers); 60 + int vpu_color_check_matrix(u32 matrix); 61 + int vpu_color_check_full_range(u32 full_range); 62 + u32 vpu_color_cvrt_primaries_v2i(u32 primaries); 63 + u32 vpu_color_cvrt_primaries_i2v(u32 primaries); 64 + u32 vpu_color_cvrt_transfers_v2i(u32 transfers); 65 + u32 vpu_color_cvrt_transfers_i2v(u32 transfers); 66 + u32 vpu_color_cvrt_matrix_v2i(u32 matrix); 67 + u32 vpu_color_cvrt_matrix_i2v(u32 matrix); 68 + u32 vpu_color_cvrt_full_range_v2i(u32 full_range); 69 + u32 vpu_color_cvrt_full_range_i2v(u32 full_range); 70 + int vpu_color_get_default(u32 primaries, u32 *ptransfers, u32 *pmatrix, u32 *pfull_range); 71 + 72 + int vpu_find_dst_by_src(struct vpu_pair *pairs, u32 cnt, u32 src); 73 + int vpu_find_src_by_dst(struct vpu_pair *pairs, u32 cnt, u32 dst); 74 + #endif
+271
drivers/media/platform/amphion/vpu_imx8q.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright 2020-2021 NXP 4 + */ 5 + 6 + #include <linux/init.h> 7 + #include <linux/device.h> 8 + #include <linux/ioctl.h> 9 + #include <linux/list.h> 10 + #include <linux/module.h> 11 + #include <linux/kernel.h> 12 + #include <linux/slab.h> 13 + #include <linux/delay.h> 14 + #include <linux/types.h> 15 + #include "vpu.h" 16 + #include "vpu_core.h" 17 + #include "vpu_imx8q.h" 18 + #include "vpu_rpc.h" 19 + 20 + #define IMX8Q_CSR_CM0Px_ADDR_OFFSET 0x00000000 21 + #define IMX8Q_CSR_CM0Px_CPUWAIT 0x00000004 22 + 23 + #ifdef CONFIG_IMX_SCU 24 + #include <linux/firmware/imx/ipc.h> 25 + #include <linux/firmware/imx/svc/misc.h> 26 + 27 + #define VPU_DISABLE_BITS 0x7 28 + #define VPU_IMX_DECODER_FUSE_OFFSET 14 29 + #define VPU_ENCODER_MASK 0x1 30 + #define VPU_DECODER_MASK 0x3UL 31 + #define VPU_DECODER_H264_MASK 0x2UL 32 + #define VPU_DECODER_HEVC_MASK 0x1UL 33 + 34 + static u32 imx8q_fuse; 35 + 36 + struct vpu_sc_msg_misc { 37 + struct imx_sc_rpc_msg hdr; 38 + u32 word; 39 + } __packed; 40 + #endif 41 + 42 + int vpu_imx8q_setup_dec(struct vpu_dev *vpu) 43 + { 44 + const off_t offset = DEC_MFD_XREG_SLV_BASE + MFD_BLK_CTRL; 45 + 46 + vpu_writel(vpu, offset + MFD_BLK_CTRL_MFD_SYS_CLOCK_ENABLE_SET, 0x1f); 47 + vpu_writel(vpu, offset + MFD_BLK_CTRL_MFD_SYS_RESET_SET, 0xffffffff); 48 + 49 + return 0; 50 + } 51 + 52 + int vpu_imx8q_setup_enc(struct vpu_dev *vpu) 53 + { 54 + return 0; 55 + } 56 + 57 + int vpu_imx8q_setup(struct vpu_dev *vpu) 58 + { 59 + const off_t offset = SCB_XREG_SLV_BASE + SCB_SCB_BLK_CTRL; 60 + 61 + vpu_readl(vpu, offset + 0x108); 62 + 63 + vpu_writel(vpu, offset + SCB_BLK_CTRL_SCB_CLK_ENABLE_SET, 0x1); 64 + vpu_writel(vpu, offset + 0x190, 0xffffffff); 65 + vpu_writel(vpu, offset + SCB_BLK_CTRL_XMEM_RESET_SET, 0xffffffff); 66 + vpu_writel(vpu, offset + SCB_BLK_CTRL_SCB_CLK_ENABLE_SET, 0xE); 67 + vpu_writel(vpu, offset + SCB_BLK_CTRL_CACHE_RESET_SET, 0x7); 68 + vpu_writel(vpu, XMEM_CONTROL, 0x102); 69 + 70 + vpu_readl(vpu, offset + 0x108); 71 + 72 + return 0; 73 + } 74 + 75 + static int vpu_imx8q_reset_enc(struct vpu_dev *vpu) 76 + { 77 + return 0; 78 + } 79 + 80 + static int vpu_imx8q_reset_dec(struct vpu_dev *vpu) 81 + { 82 + const off_t offset = DEC_MFD_XREG_SLV_BASE + MFD_BLK_CTRL; 83 + 84 + vpu_writel(vpu, offset + MFD_BLK_CTRL_MFD_SYS_RESET_CLR, 0xffffffff); 85 + 86 + return 0; 87 + } 88 + 89 + int vpu_imx8q_reset(struct vpu_dev *vpu) 90 + { 91 + const off_t offset = SCB_XREG_SLV_BASE + SCB_SCB_BLK_CTRL; 92 + 93 + vpu_writel(vpu, offset + SCB_BLK_CTRL_CACHE_RESET_CLR, 0x7); 94 + vpu_imx8q_reset_enc(vpu); 95 + vpu_imx8q_reset_dec(vpu); 96 + 97 + return 0; 98 + } 99 + 100 + int vpu_imx8q_set_system_cfg_common(struct vpu_rpc_system_config *config, u32 regs, u32 core_id) 101 + { 102 + if (!config) 103 + return -EINVAL; 104 + 105 + switch (core_id) { 106 + case 0: 107 + config->malone_base_addr[0] = regs + DEC_MFD_XREG_SLV_BASE; 108 + config->num_malones = 1; 109 + config->num_windsors = 0; 110 + break; 111 + case 1: 112 + config->windsor_base_addr[0] = regs + ENC_MFD_XREG_SLV_0_BASE; 113 + config->num_windsors = 1; 114 + config->num_malones = 0; 115 + break; 116 + case 2: 117 + config->windsor_base_addr[0] = regs + ENC_MFD_XREG_SLV_1_BASE; 118 + config->num_windsors = 1; 119 + config->num_malones = 0; 120 + break; 121 + default: 122 + return -EINVAL; 123 + } 124 + if (config->num_windsors) { 125 + config->windsor_irq_pin[0x0][0x0] = WINDSOR_PAL_IRQ_PIN_L; 126 + config->windsor_irq_pin[0x0][0x1] = WINDSOR_PAL_IRQ_PIN_H; 127 + } 128 + 129 + config->malone_base_addr[0x1] = 0x0; 130 + config->hif_offset[0x0] = MFD_HIF; 131 + config->hif_offset[0x1] = 0x0; 132 + 133 + config->dpv_base_addr = 0x0; 134 + config->dpv_irq_pin = 0x0; 135 + config->pixif_base_addr = regs + DEC_MFD_XREG_SLV_BASE + MFD_PIX_IF; 136 + config->cache_base_addr[0] = regs + MC_CACHE_0_BASE; 137 + config->cache_base_addr[1] = regs + MC_CACHE_1_BASE; 138 + 139 + return 0; 140 + } 141 + 142 + int vpu_imx8q_boot_core(struct vpu_core *core) 143 + { 144 + csr_writel(core, IMX8Q_CSR_CM0Px_ADDR_OFFSET, core->fw.phys); 145 + csr_writel(core, IMX8Q_CSR_CM0Px_CPUWAIT, 0); 146 + return 0; 147 + } 148 + 149 + int vpu_imx8q_get_power_state(struct vpu_core *core) 150 + { 151 + if (csr_readl(core, IMX8Q_CSR_CM0Px_CPUWAIT) == 1) 152 + return 0; 153 + return 1; 154 + } 155 + 156 + int vpu_imx8q_on_firmware_loaded(struct vpu_core *core) 157 + { 158 + u8 *p; 159 + 160 + p = core->fw.virt; 161 + p[16] = core->vpu->res->plat_type; 162 + p[17] = core->id; 163 + p[18] = 1; 164 + 165 + return 0; 166 + } 167 + 168 + u32 vpu_imx8q_check_memory_region(dma_addr_t base, dma_addr_t addr, u32 size) 169 + { 170 + const struct vpu_rpc_region_t imx8q_regions[] = { 171 + {0x00000000, 0x08000000, VPU_CORE_MEMORY_CACHED}, 172 + {0x08000000, 0x10000000, VPU_CORE_MEMORY_UNCACHED}, 173 + {0x10000000, 0x20000000, VPU_CORE_MEMORY_CACHED}, 174 + {0x20000000, 0x40000000, VPU_CORE_MEMORY_UNCACHED} 175 + }; 176 + int i; 177 + 178 + if (addr < base) 179 + return VPU_CORE_MEMORY_INVALID; 180 + 181 + addr -= base; 182 + for (i = 0; i < ARRAY_SIZE(imx8q_regions); i++) { 183 + const struct vpu_rpc_region_t *region = &imx8q_regions[i]; 184 + 185 + if (addr >= region->start && addr + size < region->end) 186 + return region->type; 187 + } 188 + 189 + return VPU_CORE_MEMORY_INVALID; 190 + } 191 + 192 + #ifdef CONFIG_IMX_SCU 193 + static u32 vpu_imx8q_get_fuse(void) 194 + { 195 + static u32 fuse_got; 196 + struct imx_sc_ipc *ipc; 197 + struct vpu_sc_msg_misc msg; 198 + struct imx_sc_rpc_msg *hdr = &msg.hdr; 199 + int ret; 200 + 201 + if (fuse_got) 202 + return imx8q_fuse; 203 + 204 + ret = imx_scu_get_handle(&ipc); 205 + if (ret) { 206 + pr_err("error: get sct handle fail: %d\n", ret); 207 + return 0; 208 + } 209 + 210 + hdr->ver = IMX_SC_RPC_VERSION; 211 + hdr->svc = IMX_SC_RPC_SVC_MISC; 212 + hdr->func = IMX_SC_MISC_FUNC_OTP_FUSE_READ; 213 + hdr->size = 2; 214 + 215 + msg.word = VPU_DISABLE_BITS; 216 + 217 + ret = imx_scu_call_rpc(ipc, &msg, true); 218 + if (ret) 219 + return 0; 220 + 221 + imx8q_fuse = msg.word; 222 + fuse_got = 1; 223 + return imx8q_fuse; 224 + } 225 + 226 + bool vpu_imx8q_check_codec(enum vpu_core_type type) 227 + { 228 + u32 fuse = vpu_imx8q_get_fuse(); 229 + 230 + if (type == VPU_CORE_TYPE_ENC) { 231 + if (fuse & VPU_ENCODER_MASK) 232 + return false; 233 + } else if (type == VPU_CORE_TYPE_DEC) { 234 + fuse >>= VPU_IMX_DECODER_FUSE_OFFSET; 235 + fuse &= VPU_DECODER_MASK; 236 + 237 + if (fuse == VPU_DECODER_MASK) 238 + return false; 239 + } 240 + return true; 241 + } 242 + 243 + bool vpu_imx8q_check_fmt(enum vpu_core_type type, u32 pixelfmt) 244 + { 245 + u32 fuse = vpu_imx8q_get_fuse(); 246 + 247 + if (type == VPU_CORE_TYPE_DEC) { 248 + fuse >>= VPU_IMX_DECODER_FUSE_OFFSET; 249 + fuse &= VPU_DECODER_MASK; 250 + 251 + if (fuse == VPU_DECODER_HEVC_MASK && pixelfmt == V4L2_PIX_FMT_HEVC) 252 + return false; 253 + if (fuse == VPU_DECODER_H264_MASK && pixelfmt == V4L2_PIX_FMT_H264) 254 + return false; 255 + if (fuse == VPU_DECODER_MASK) 256 + return false; 257 + } 258 + 259 + return true; 260 + } 261 + #else 262 + bool vpu_imx8q_check_codec(enum vpu_core_type type) 263 + { 264 + return true; 265 + } 266 + 267 + bool vpu_imx8q_check_fmt(enum vpu_core_type type, u32 pixelfmt) 268 + { 269 + return true; 270 + } 271 + #endif
+115
drivers/media/platform/amphion/vpu_imx8q.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Copyright 2020-2021 NXP 4 + */ 5 + 6 + #ifndef _AMPHION_VPU_IMX8Q_H 7 + #define _AMPHION_VPU_IMX8Q_H 8 + 9 + #define SCB_XREG_SLV_BASE 0x00000000 10 + #define SCB_SCB_BLK_CTRL 0x00070000 11 + #define SCB_BLK_CTRL_XMEM_RESET_SET 0x00000090 12 + #define SCB_BLK_CTRL_CACHE_RESET_SET 0x000000A0 13 + #define SCB_BLK_CTRL_CACHE_RESET_CLR 0x000000A4 14 + #define SCB_BLK_CTRL_SCB_CLK_ENABLE_SET 0x00000100 15 + 16 + #define XMEM_CONTROL 0x00041000 17 + 18 + #define MC_CACHE_0_BASE 0x00060000 19 + #define MC_CACHE_1_BASE 0x00068000 20 + 21 + #define DEC_MFD_XREG_SLV_BASE 0x00180000 22 + #define ENC_MFD_XREG_SLV_0_BASE 0x00800000 23 + #define ENC_MFD_XREG_SLV_1_BASE 0x00A00000 24 + 25 + #define MFD_HIF 0x0001C000 26 + #define MFD_HIF_MSD_REG_INTERRUPT_STATUS 0x00000018 27 + #define MFD_SIF 0x0001D000 28 + #define MFD_SIF_CTRL_STATUS 0x000000F0 29 + #define MFD_SIF_INTR_STATUS 0x000000F4 30 + #define MFD_MCX 0x00020800 31 + #define MFD_MCX_OFF 0x00000020 32 + #define MFD_PIX_IF 0x00020000 33 + 34 + #define MFD_BLK_CTRL 0x00030000 35 + #define MFD_BLK_CTRL_MFD_SYS_RESET_SET 0x00000000 36 + #define MFD_BLK_CTRL_MFD_SYS_RESET_CLR 0x00000004 37 + #define MFD_BLK_CTRL_MFD_SYS_CLOCK_ENABLE_SET 0x00000100 38 + #define MFD_BLK_CTRL_MFD_SYS_CLOCK_ENABLE_CLR 0x00000104 39 + 40 + #define VID_API_NUM_STREAMS 8 41 + #define VID_API_MAX_BUF_PER_STR 3 42 + #define VID_API_MAX_NUM_MVC_VIEWS 4 43 + #define MEDIAIP_MAX_NUM_MALONES 2 44 + #define MEDIAIP_MAX_NUM_MALONE_IRQ_PINS 2 45 + #define MEDIAIP_MAX_NUM_WINDSORS 1 46 + #define MEDIAIP_MAX_NUM_WINDSOR_IRQ_PINS 2 47 + #define MEDIAIP_MAX_NUM_CMD_IRQ_PINS 2 48 + #define MEDIAIP_MAX_NUM_MSG_IRQ_PINS 1 49 + #define MEDIAIP_MAX_NUM_TIMER_IRQ_PINS 4 50 + #define MEDIAIP_MAX_NUM_TIMER_IRQ_SLOTS 4 51 + 52 + #define WINDSOR_PAL_IRQ_PIN_L 0x4 53 + #define WINDSOR_PAL_IRQ_PIN_H 0x5 54 + 55 + struct vpu_rpc_system_config { 56 + u32 cfg_cookie; 57 + 58 + u32 num_malones; 59 + u32 malone_base_addr[MEDIAIP_MAX_NUM_MALONES]; 60 + u32 hif_offset[MEDIAIP_MAX_NUM_MALONES]; 61 + u32 malone_irq_pin[MEDIAIP_MAX_NUM_MALONES][MEDIAIP_MAX_NUM_MALONE_IRQ_PINS]; 62 + u32 malone_irq_target[MEDIAIP_MAX_NUM_MALONES][MEDIAIP_MAX_NUM_MALONE_IRQ_PINS]; 63 + 64 + u32 num_windsors; 65 + u32 windsor_base_addr[MEDIAIP_MAX_NUM_WINDSORS]; 66 + u32 windsor_irq_pin[MEDIAIP_MAX_NUM_WINDSORS][MEDIAIP_MAX_NUM_WINDSOR_IRQ_PINS]; 67 + u32 windsor_irq_target[MEDIAIP_MAX_NUM_WINDSORS][MEDIAIP_MAX_NUM_WINDSOR_IRQ_PINS]; 68 + 69 + u32 cmd_irq_pin[MEDIAIP_MAX_NUM_CMD_IRQ_PINS]; 70 + u32 cmd_irq_target[MEDIAIP_MAX_NUM_CMD_IRQ_PINS]; 71 + 72 + u32 msg_irq_pin[MEDIAIP_MAX_NUM_MSG_IRQ_PINS]; 73 + u32 msg_irq_target[MEDIAIP_MAX_NUM_MSG_IRQ_PINS]; 74 + 75 + u32 sys_clk_freq; 76 + u32 num_timers; 77 + u32 timer_base_addr; 78 + u32 timer_irq_pin[MEDIAIP_MAX_NUM_TIMER_IRQ_PINS]; 79 + u32 timer_irq_target[MEDIAIP_MAX_NUM_TIMER_IRQ_PINS]; 80 + u32 timer_slots[MEDIAIP_MAX_NUM_TIMER_IRQ_SLOTS]; 81 + 82 + u32 gic_base_addr; 83 + u32 uart_base_addr; 84 + 85 + u32 dpv_base_addr; 86 + u32 dpv_irq_pin; 87 + u32 dpv_irq_target; 88 + 89 + u32 pixif_base_addr; 90 + 91 + u32 pal_trace_level; 92 + u32 pal_trace_destination; 93 + 94 + u32 pal_trace_level1; 95 + u32 pal_trace_destination1; 96 + 97 + u32 heap_base; 98 + u32 heap_size; 99 + 100 + u32 cache_base_addr[2]; 101 + }; 102 + 103 + int vpu_imx8q_setup_dec(struct vpu_dev *vpu); 104 + int vpu_imx8q_setup_enc(struct vpu_dev *vpu); 105 + int vpu_imx8q_setup(struct vpu_dev *vpu); 106 + int vpu_imx8q_reset(struct vpu_dev *vpu); 107 + int vpu_imx8q_set_system_cfg_common(struct vpu_rpc_system_config *config, u32 regs, u32 core_id); 108 + int vpu_imx8q_boot_core(struct vpu_core *core); 109 + int vpu_imx8q_get_power_state(struct vpu_core *core); 110 + int vpu_imx8q_on_firmware_loaded(struct vpu_core *core); 111 + u32 vpu_imx8q_check_memory_region(dma_addr_t base, dma_addr_t addr, u32 size); 112 + bool vpu_imx8q_check_codec(enum vpu_core_type type); 113 + bool vpu_imx8q_check_fmt(enum vpu_core_type type, u32 pixelfmt); 114 + 115 + #endif
+1625
drivers/media/platform/amphion/vpu_malone.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright 2020-2021 NXP 4 + */ 5 + 6 + #include <linux/init.h> 7 + #include <linux/interconnect.h> 8 + #include <linux/ioctl.h> 9 + #include <linux/list.h> 10 + #include <linux/kernel.h> 11 + #include <linux/module.h> 12 + #include <linux/of_device.h> 13 + #include <linux/of_address.h> 14 + #include <linux/platform_device.h> 15 + #include <linux/delay.h> 16 + #include <linux/rational.h> 17 + #include <media/videobuf2-v4l2.h> 18 + #include <media/videobuf2-dma-contig.h> 19 + #include <linux/videodev2.h> 20 + #include "vpu.h" 21 + #include "vpu_rpc.h" 22 + #include "vpu_defs.h" 23 + #include "vpu_helpers.h" 24 + #include "vpu_v4l2.h" 25 + #include "vpu_cmds.h" 26 + #include "vpu_imx8q.h" 27 + #include "vpu_malone.h" 28 + 29 + #define CMD_SIZE 25600 30 + #define MSG_SIZE 25600 31 + #define CODEC_SIZE 0x1000 32 + #define JPEG_SIZE 0x1000 33 + #define SEQ_SIZE 0x1000 34 + #define GOP_SIZE 0x1000 35 + #define PIC_SIZE 0x1000 36 + #define QMETER_SIZE 0x1000 37 + #define DBGLOG_SIZE 0x10000 38 + #define DEBUG_SIZE 0x80000 39 + #define ENG_SIZE 0x1000 40 + #define MALONE_SKIPPED_FRAME_ID 0x555 41 + 42 + #define MALONE_ALIGN_MBI 0x800 43 + #define MALONE_DCP_CHUNK_BIT 16 44 + #define MALONE_DCP_SIZE_MAX 0x3000000 45 + #define MALONE_DCP_SIZE_MIN 0x100000 46 + #define MALONE_DCP_FIXED_MB_ALLOC 250 47 + 48 + #define CONFIG_SET(val, cfg, pos, mask) \ 49 + (*(cfg) |= (((val) << (pos)) & (mask))) 50 + //x means source data , y means destination data 51 + #define STREAM_CONFIG_FORMAT_SET(x, y) CONFIG_SET(x, y, 0, 0x0000000F) 52 + #define STREAM_CONFIG_STRBUFIDX_SET(x, y) CONFIG_SET(x, y, 8, 0x00000300) 53 + #define STREAM_CONFIG_NOSEQ_SET(x, y) CONFIG_SET(x, y, 10, 0x00000400) 54 + #define STREAM_CONFIG_DEBLOCK_SET(x, y) CONFIG_SET(x, y, 11, 0x00000800) 55 + #define STREAM_CONFIG_DERING_SET(x, y) CONFIG_SET(x, y, 12, 0x00001000) 56 + #define STREAM_CONFIG_IBWAIT_SET(x, y) CONFIG_SET(x, y, 13, 0x00002000) 57 + #define STREAM_CONFIG_FBC_SET(x, y) CONFIG_SET(x, y, 14, 0x00004000) 58 + #define STREAM_CONFIG_PLAY_MODE_SET(x, y) CONFIG_SET(x, y, 16, 0x00030000) 59 + #define STREAM_CONFIG_ENABLE_DCP_SET(x, y) CONFIG_SET(x, y, 20, 0x00100000) 60 + #define STREAM_CONFIG_NUM_STR_BUF_SET(x, y) CONFIG_SET(x, y, 21, 0x00600000) 61 + #define STREAM_CONFIG_MALONE_USAGE_SET(x, y) CONFIG_SET(x, y, 23, 0x01800000) 62 + #define STREAM_CONFIG_MULTI_VID_SET(x, y) CONFIG_SET(x, y, 25, 0x02000000) 63 + #define STREAM_CONFIG_OBFUSC_EN_SET(x, y) CONFIG_SET(x, y, 26, 0x04000000) 64 + #define STREAM_CONFIG_RC4_EN_SET(x, y) CONFIG_SET(x, y, 27, 0x08000000) 65 + #define STREAM_CONFIG_MCX_SET(x, y) CONFIG_SET(x, y, 28, 0x10000000) 66 + #define STREAM_CONFIG_PES_SET(x, y) CONFIG_SET(x, y, 29, 0x20000000) 67 + #define STREAM_CONFIG_NUM_DBE_SET(x, y) CONFIG_SET(x, y, 30, 0x40000000) 68 + #define STREAM_CONFIG_FS_CTRL_MODE_SET(x, y) CONFIG_SET(x, y, 31, 0x80000000) 69 + 70 + enum vpu_malone_stream_input_mode { 71 + INVALID_MODE = 0, 72 + FRAME_LVL, 73 + NON_FRAME_LVL 74 + }; 75 + 76 + enum vpu_malone_format { 77 + MALONE_FMT_NULL = 0x0, 78 + MALONE_FMT_AVC = 0x1, 79 + MALONE_FMT_MP2 = 0x2, 80 + MALONE_FMT_VC1 = 0x3, 81 + MALONE_FMT_AVS = 0x4, 82 + MALONE_FMT_ASP = 0x5, 83 + MALONE_FMT_JPG = 0x6, 84 + MALONE_FMT_RV = 0x7, 85 + MALONE_FMT_VP6 = 0x8, 86 + MALONE_FMT_SPK = 0x9, 87 + MALONE_FMT_VP8 = 0xA, 88 + MALONE_FMT_HEVC = 0xB, 89 + MALONE_FMT_LAST = MALONE_FMT_HEVC 90 + }; 91 + 92 + enum { 93 + VID_API_CMD_NULL = 0x00, 94 + VID_API_CMD_PARSE_NEXT_SEQ = 0x01, 95 + VID_API_CMD_PARSE_NEXT_I = 0x02, 96 + VID_API_CMD_PARSE_NEXT_IP = 0x03, 97 + VID_API_CMD_PARSE_NEXT_ANY = 0x04, 98 + VID_API_CMD_DEC_PIC = 0x05, 99 + VID_API_CMD_UPDATE_ES_WR_PTR = 0x06, 100 + VID_API_CMD_UPDATE_ES_RD_PTR = 0x07, 101 + VID_API_CMD_UPDATE_UDATA = 0x08, 102 + VID_API_CMD_GET_FSINFO = 0x09, 103 + VID_API_CMD_SKIP_PIC = 0x0a, 104 + VID_API_CMD_DEC_CHUNK = 0x0b, 105 + VID_API_CMD_START = 0x10, 106 + VID_API_CMD_STOP = 0x11, 107 + VID_API_CMD_ABORT = 0x12, 108 + VID_API_CMD_RST_BUF = 0x13, 109 + VID_API_CMD_FS_RELEASE = 0x15, 110 + VID_API_CMD_MEM_REGION_ATTACH = 0x16, 111 + VID_API_CMD_MEM_REGION_DETACH = 0x17, 112 + VID_API_CMD_MVC_VIEW_SELECT = 0x18, 113 + VID_API_CMD_FS_ALLOC = 0x19, 114 + VID_API_CMD_DBG_GET_STATUS = 0x1C, 115 + VID_API_CMD_DBG_START_LOG = 0x1D, 116 + VID_API_CMD_DBG_STOP_LOG = 0x1E, 117 + VID_API_CMD_DBG_DUMP_LOG = 0x1F, 118 + VID_API_CMD_YUV_READY = 0x20, 119 + VID_API_CMD_TS = 0x21, 120 + 121 + VID_API_CMD_FIRM_RESET = 0x40, 122 + 123 + VID_API_CMD_SNAPSHOT = 0xAA, 124 + VID_API_CMD_ROLL_SNAPSHOT = 0xAB, 125 + VID_API_CMD_LOCK_SCHEDULER = 0xAC, 126 + VID_API_CMD_UNLOCK_SCHEDULER = 0xAD, 127 + VID_API_CMD_CQ_FIFO_DUMP = 0xAE, 128 + VID_API_CMD_DBG_FIFO_DUMP = 0xAF, 129 + VID_API_CMD_SVC_ILP = 0xBB, 130 + VID_API_CMD_FW_STATUS = 0xF0, 131 + VID_API_CMD_INVALID = 0xFF 132 + }; 133 + 134 + enum { 135 + VID_API_EVENT_NULL = 0x00, 136 + VID_API_EVENT_RESET_DONE = 0x01, 137 + VID_API_EVENT_SEQ_HDR_FOUND = 0x02, 138 + VID_API_EVENT_PIC_HDR_FOUND = 0x03, 139 + VID_API_EVENT_PIC_DECODED = 0x04, 140 + VID_API_EVENT_FIFO_LOW = 0x05, 141 + VID_API_EVENT_FIFO_HIGH = 0x06, 142 + VID_API_EVENT_FIFO_EMPTY = 0x07, 143 + VID_API_EVENT_FIFO_FULL = 0x08, 144 + VID_API_EVENT_BS_ERROR = 0x09, 145 + VID_API_EVENT_UDATA_FIFO_UPTD = 0x0A, 146 + VID_API_EVENT_RES_CHANGE = 0x0B, 147 + VID_API_EVENT_FIFO_OVF = 0x0C, 148 + VID_API_EVENT_CHUNK_DECODED = 0x0D, 149 + VID_API_EVENT_REQ_FRAME_BUFF = 0x10, 150 + VID_API_EVENT_FRAME_BUFF_RDY = 0x11, 151 + VID_API_EVENT_REL_FRAME_BUFF = 0x12, 152 + VID_API_EVENT_STR_BUF_RST = 0x13, 153 + VID_API_EVENT_RET_PING = 0x14, 154 + VID_API_EVENT_QMETER = 0x15, 155 + VID_API_EVENT_STR_FMT_CHANGE = 0x16, 156 + VID_API_EVENT_FIRMWARE_XCPT = 0x17, 157 + VID_API_EVENT_START_DONE = 0x18, 158 + VID_API_EVENT_STOPPED = 0x19, 159 + VID_API_EVENT_ABORT_DONE = 0x1A, 160 + VID_API_EVENT_FINISHED = 0x1B, 161 + VID_API_EVENT_DBG_STAT_UPDATE = 0x1C, 162 + VID_API_EVENT_DBG_LOG_STARTED = 0x1D, 163 + VID_API_EVENT_DBG_LOG_STOPPED = 0x1E, 164 + VID_API_EVENT_DBG_LOG_UPDATED = 0x1F, 165 + VID_API_EVENT_DBG_MSG_DEC = 0x20, 166 + VID_API_EVENT_DEC_SC_ERR = 0x21, 167 + VID_API_EVENT_CQ_FIFO_DUMP = 0x22, 168 + VID_API_EVENT_DBG_FIFO_DUMP = 0x23, 169 + VID_API_EVENT_DEC_CHECK_RES = 0x24, 170 + VID_API_EVENT_DEC_CFG_INFO = 0x25, 171 + VID_API_EVENT_UNSUPPORTED_STREAM = 0x26, 172 + VID_API_EVENT_STR_SUSPENDED = 0x30, 173 + VID_API_EVENT_SNAPSHOT_DONE = 0x40, 174 + VID_API_EVENT_FW_STATUS = 0xF0, 175 + VID_API_EVENT_INVALID = 0xFF 176 + }; 177 + 178 + struct vpu_malone_buffer_desc { 179 + struct vpu_rpc_buffer_desc buffer; 180 + u32 low; 181 + u32 high; 182 + }; 183 + 184 + struct vpu_malone_str_buffer { 185 + u32 wptr; 186 + u32 rptr; 187 + u32 start; 188 + u32 end; 189 + u32 lwm; 190 + }; 191 + 192 + struct vpu_malone_picth_info { 193 + u32 frame_pitch; 194 + }; 195 + 196 + struct vpu_malone_table_desc { 197 + u32 array_base; 198 + u32 size; 199 + }; 200 + 201 + struct vpu_malone_dbglog_desc { 202 + u32 addr; 203 + u32 size; 204 + u32 level; 205 + u32 reserved; 206 + }; 207 + 208 + struct vpu_malone_frame_buffer { 209 + u32 addr; 210 + u32 size; 211 + }; 212 + 213 + struct vpu_malone_udata { 214 + u32 base; 215 + u32 total_size; 216 + u32 slot_size; 217 + }; 218 + 219 + struct vpu_malone_buffer_info { 220 + u32 stream_input_mode; 221 + u32 stream_pic_input_count; 222 + u32 stream_pic_parsed_count; 223 + u32 stream_buffer_threshold; 224 + u32 stream_pic_end_flag; 225 + }; 226 + 227 + struct vpu_malone_encrypt_info { 228 + u32 rec4key[8]; 229 + u32 obfusc; 230 + }; 231 + 232 + struct malone_iface { 233 + u32 exec_base_addr; 234 + u32 exec_area_size; 235 + struct vpu_malone_buffer_desc cmd_buffer_desc; 236 + struct vpu_malone_buffer_desc msg_buffer_desc; 237 + u32 cmd_int_enable[VID_API_NUM_STREAMS]; 238 + struct vpu_malone_picth_info stream_pitch_info[VID_API_NUM_STREAMS]; 239 + u32 stream_config[VID_API_NUM_STREAMS]; 240 + struct vpu_malone_table_desc codec_param_tab_desc; 241 + struct vpu_malone_table_desc jpeg_param_tab_desc; 242 + u32 stream_buffer_desc[VID_API_NUM_STREAMS][VID_API_MAX_BUF_PER_STR]; 243 + struct vpu_malone_table_desc seq_info_tab_desc; 244 + struct vpu_malone_table_desc pic_info_tab_desc; 245 + struct vpu_malone_table_desc gop_info_tab_desc; 246 + struct vpu_malone_table_desc qmeter_info_tab_desc; 247 + u32 stream_error[VID_API_NUM_STREAMS]; 248 + u32 fw_version; 249 + u32 fw_offset; 250 + u32 max_streams; 251 + struct vpu_malone_dbglog_desc dbglog_desc; 252 + struct vpu_rpc_buffer_desc api_cmd_buffer_desc[VID_API_NUM_STREAMS]; 253 + struct vpu_malone_udata udata_buffer[VID_API_NUM_STREAMS]; 254 + struct vpu_malone_buffer_desc debug_buffer_desc; 255 + struct vpu_malone_buffer_desc eng_access_buff_desc[VID_API_NUM_STREAMS]; 256 + u32 encrypt_info[VID_API_NUM_STREAMS]; 257 + struct vpu_rpc_system_config system_cfg; 258 + u32 api_version; 259 + struct vpu_malone_buffer_info stream_buff_info[VID_API_NUM_STREAMS]; 260 + }; 261 + 262 + struct malone_jpg_params { 263 + u32 rotation_angle; 264 + u32 horiz_scale_factor; 265 + u32 vert_scale_factor; 266 + u32 rotation_mode; 267 + u32 rgb_mode; 268 + u32 chunk_mode; /* 0 ~ 1 */ 269 + u32 last_chunk; /* 0 ~ 1 */ 270 + u32 chunk_rows; /* 0 ~ 255 */ 271 + u32 num_bytes; 272 + u32 jpg_crop_x; 273 + u32 jpg_crop_y; 274 + u32 jpg_crop_width; 275 + u32 jpg_crop_height; 276 + u32 jpg_mjpeg_mode; 277 + u32 jpg_mjpeg_interlaced; 278 + }; 279 + 280 + struct malone_codec_params { 281 + u32 disp_imm; 282 + u32 fourcc; 283 + u32 codec_version; 284 + u32 frame_rate; 285 + u32 dbglog_enable; 286 + u32 bsdma_lwm; 287 + u32 bbd_coring; 288 + u32 bbd_s_thr_row; 289 + u32 bbd_p_thr_row; 290 + u32 bbd_s_thr_logo_row; 291 + u32 bbd_p_thr_logo_row; 292 + u32 bbd_s_thr_col; 293 + u32 bbd_p_thr_col; 294 + u32 bbd_chr_thr_row; 295 + u32 bbd_chr_thr_col; 296 + u32 bbd_uv_mid_level; 297 + u32 bbd_excl_win_mb_left; 298 + u32 bbd_excl_win_mb_right; 299 + }; 300 + 301 + struct malone_padding_scode { 302 + u32 scode_type; 303 + u32 pixelformat; 304 + u32 data[2]; 305 + }; 306 + 307 + struct malone_fmt_mapping { 308 + u32 pixelformat; 309 + enum vpu_malone_format malone_format; 310 + }; 311 + 312 + struct malone_scode_t { 313 + struct vpu_inst *inst; 314 + struct vb2_buffer *vb; 315 + u32 wptr; 316 + u32 need_data; 317 + }; 318 + 319 + struct malone_scode_handler { 320 + u32 pixelformat; 321 + int (*insert_scode_seq)(struct malone_scode_t *scode); 322 + int (*insert_scode_pic)(struct malone_scode_t *scode); 323 + }; 324 + 325 + struct vpu_dec_ctrl { 326 + struct malone_codec_params *codec_param; 327 + struct malone_jpg_params *jpg; 328 + void *seq_mem; 329 + void *pic_mem; 330 + void *gop_mem; 331 + void *qmeter_mem; 332 + void *dbglog_mem; 333 + struct vpu_malone_str_buffer __iomem *str_buf[VID_API_NUM_STREAMS]; 334 + u32 buf_addr[VID_API_NUM_STREAMS]; 335 + }; 336 + 337 + u32 vpu_malone_get_data_size(void) 338 + { 339 + return sizeof(struct vpu_dec_ctrl); 340 + } 341 + 342 + void vpu_malone_init_rpc(struct vpu_shared_addr *shared, 343 + struct vpu_buffer *rpc, dma_addr_t boot_addr) 344 + { 345 + struct malone_iface *iface; 346 + struct vpu_dec_ctrl *hc; 347 + unsigned long base_phy_addr; 348 + unsigned long phy_addr; 349 + unsigned long offset; 350 + unsigned int i; 351 + 352 + if (rpc->phys < boot_addr) 353 + return; 354 + 355 + iface = rpc->virt; 356 + base_phy_addr = rpc->phys - boot_addr; 357 + hc = shared->priv; 358 + 359 + shared->iface = iface; 360 + shared->boot_addr = boot_addr; 361 + 362 + iface->exec_base_addr = base_phy_addr; 363 + iface->exec_area_size = rpc->length; 364 + 365 + offset = sizeof(struct malone_iface); 366 + phy_addr = base_phy_addr + offset; 367 + 368 + shared->cmd_desc = &iface->cmd_buffer_desc.buffer; 369 + shared->cmd_mem_vir = rpc->virt + offset; 370 + iface->cmd_buffer_desc.buffer.start = 371 + iface->cmd_buffer_desc.buffer.rptr = 372 + iface->cmd_buffer_desc.buffer.wptr = phy_addr; 373 + iface->cmd_buffer_desc.buffer.end = iface->cmd_buffer_desc.buffer.start + CMD_SIZE; 374 + offset += CMD_SIZE; 375 + phy_addr = base_phy_addr + offset; 376 + 377 + shared->msg_desc = &iface->msg_buffer_desc.buffer; 378 + shared->msg_mem_vir = rpc->virt + offset; 379 + iface->msg_buffer_desc.buffer.start = 380 + iface->msg_buffer_desc.buffer.wptr = 381 + iface->msg_buffer_desc.buffer.rptr = phy_addr; 382 + iface->msg_buffer_desc.buffer.end = iface->msg_buffer_desc.buffer.start + MSG_SIZE; 383 + offset += MSG_SIZE; 384 + phy_addr = base_phy_addr + offset; 385 + 386 + iface->codec_param_tab_desc.array_base = phy_addr; 387 + hc->codec_param = rpc->virt + offset; 388 + offset += CODEC_SIZE; 389 + phy_addr = base_phy_addr + offset; 390 + 391 + iface->jpeg_param_tab_desc.array_base = phy_addr; 392 + hc->jpg = rpc->virt + offset; 393 + offset += JPEG_SIZE; 394 + phy_addr = base_phy_addr + offset; 395 + 396 + iface->seq_info_tab_desc.array_base = phy_addr; 397 + hc->seq_mem = rpc->virt + offset; 398 + offset += SEQ_SIZE; 399 + phy_addr = base_phy_addr + offset; 400 + 401 + iface->pic_info_tab_desc.array_base = phy_addr; 402 + hc->pic_mem = rpc->virt + offset; 403 + offset += PIC_SIZE; 404 + phy_addr = base_phy_addr + offset; 405 + 406 + iface->gop_info_tab_desc.array_base = phy_addr; 407 + hc->gop_mem = rpc->virt + offset; 408 + offset += GOP_SIZE; 409 + phy_addr = base_phy_addr + offset; 410 + 411 + iface->qmeter_info_tab_desc.array_base = phy_addr; 412 + hc->qmeter_mem = rpc->virt + offset; 413 + offset += QMETER_SIZE; 414 + phy_addr = base_phy_addr + offset; 415 + 416 + iface->dbglog_desc.addr = phy_addr; 417 + iface->dbglog_desc.size = DBGLOG_SIZE; 418 + hc->dbglog_mem = rpc->virt + offset; 419 + offset += DBGLOG_SIZE; 420 + phy_addr = base_phy_addr + offset; 421 + 422 + for (i = 0; i < VID_API_NUM_STREAMS; i++) { 423 + iface->eng_access_buff_desc[i].buffer.start = 424 + iface->eng_access_buff_desc[i].buffer.wptr = 425 + iface->eng_access_buff_desc[i].buffer.rptr = phy_addr; 426 + iface->eng_access_buff_desc[i].buffer.end = 427 + iface->eng_access_buff_desc[i].buffer.start + ENG_SIZE; 428 + offset += ENG_SIZE; 429 + phy_addr = base_phy_addr + offset; 430 + } 431 + 432 + for (i = 0; i < VID_API_NUM_STREAMS; i++) { 433 + iface->encrypt_info[i] = phy_addr; 434 + offset += sizeof(struct vpu_malone_encrypt_info); 435 + phy_addr = base_phy_addr + offset; 436 + } 437 + 438 + rpc->bytesused = offset; 439 + } 440 + 441 + void vpu_malone_set_log_buf(struct vpu_shared_addr *shared, 442 + struct vpu_buffer *log) 443 + { 444 + struct malone_iface *iface = shared->iface; 445 + 446 + iface->debug_buffer_desc.buffer.start = 447 + iface->debug_buffer_desc.buffer.wptr = 448 + iface->debug_buffer_desc.buffer.rptr = log->phys - shared->boot_addr; 449 + iface->debug_buffer_desc.buffer.end = iface->debug_buffer_desc.buffer.start + log->length; 450 + } 451 + 452 + static u32 get_str_buffer_offset(u32 instance) 453 + { 454 + return DEC_MFD_XREG_SLV_BASE + MFD_MCX + MFD_MCX_OFF * instance; 455 + } 456 + 457 + void vpu_malone_set_system_cfg(struct vpu_shared_addr *shared, 458 + u32 regs_base, void __iomem *regs, u32 core_id) 459 + { 460 + struct malone_iface *iface = shared->iface; 461 + struct vpu_rpc_system_config *config = &iface->system_cfg; 462 + struct vpu_dec_ctrl *hc = shared->priv; 463 + int i; 464 + 465 + vpu_imx8q_set_system_cfg_common(config, regs_base, core_id); 466 + for (i = 0; i < VID_API_NUM_STREAMS; i++) { 467 + u32 offset = get_str_buffer_offset(i); 468 + 469 + hc->buf_addr[i] = regs_base + offset; 470 + hc->str_buf[i] = regs + offset; 471 + } 472 + } 473 + 474 + u32 vpu_malone_get_version(struct vpu_shared_addr *shared) 475 + { 476 + struct malone_iface *iface = shared->iface; 477 + 478 + return iface->fw_version; 479 + } 480 + 481 + int vpu_malone_get_stream_buffer_size(struct vpu_shared_addr *shared) 482 + { 483 + return 0xc00000; 484 + } 485 + 486 + int vpu_malone_config_stream_buffer(struct vpu_shared_addr *shared, 487 + u32 instance, 488 + struct vpu_buffer *buf) 489 + { 490 + struct malone_iface *iface = shared->iface; 491 + struct vpu_dec_ctrl *hc = shared->priv; 492 + struct vpu_malone_str_buffer __iomem *str_buf = hc->str_buf[instance]; 493 + 494 + writel(buf->phys, &str_buf->start); 495 + writel(buf->phys, &str_buf->rptr); 496 + writel(buf->phys, &str_buf->wptr); 497 + writel(buf->phys + buf->length, &str_buf->end); 498 + writel(0x1, &str_buf->lwm); 499 + 500 + iface->stream_buffer_desc[instance][0] = hc->buf_addr[instance]; 501 + 502 + return 0; 503 + } 504 + 505 + int vpu_malone_get_stream_buffer_desc(struct vpu_shared_addr *shared, 506 + u32 instance, 507 + struct vpu_rpc_buffer_desc *desc) 508 + { 509 + struct vpu_dec_ctrl *hc = shared->priv; 510 + struct vpu_malone_str_buffer __iomem *str_buf = hc->str_buf[instance]; 511 + 512 + if (desc) { 513 + desc->wptr = readl(&str_buf->wptr); 514 + desc->rptr = readl(&str_buf->rptr); 515 + desc->start = readl(&str_buf->start); 516 + desc->end = readl(&str_buf->end); 517 + } 518 + 519 + return 0; 520 + } 521 + 522 + static void vpu_malone_update_wptr(struct vpu_malone_str_buffer __iomem *str_buf, u32 wptr) 523 + { 524 + /*update wptr after data is written*/ 525 + mb(); 526 + writel(wptr, &str_buf->wptr); 527 + } 528 + 529 + static void vpu_malone_update_rptr(struct vpu_malone_str_buffer __iomem *str_buf, u32 rptr) 530 + { 531 + /*update rptr after data is read*/ 532 + mb(); 533 + writel(rptr, &str_buf->rptr); 534 + } 535 + 536 + int vpu_malone_update_stream_buffer(struct vpu_shared_addr *shared, 537 + u32 instance, u32 ptr, bool write) 538 + { 539 + struct vpu_dec_ctrl *hc = shared->priv; 540 + struct vpu_malone_str_buffer __iomem *str_buf = hc->str_buf[instance]; 541 + 542 + if (write) 543 + vpu_malone_update_wptr(str_buf, ptr); 544 + else 545 + vpu_malone_update_rptr(str_buf, ptr); 546 + 547 + return 0; 548 + } 549 + 550 + static struct malone_fmt_mapping fmt_mappings[] = { 551 + {V4L2_PIX_FMT_H264, MALONE_FMT_AVC}, 552 + {V4L2_PIX_FMT_H264_MVC, MALONE_FMT_AVC}, 553 + {V4L2_PIX_FMT_HEVC, MALONE_FMT_HEVC}, 554 + {V4L2_PIX_FMT_VC1_ANNEX_G, MALONE_FMT_VC1}, 555 + {V4L2_PIX_FMT_VC1_ANNEX_L, MALONE_FMT_VC1}, 556 + {V4L2_PIX_FMT_MPEG2, MALONE_FMT_MP2}, 557 + {V4L2_PIX_FMT_MPEG4, MALONE_FMT_ASP}, 558 + {V4L2_PIX_FMT_XVID, MALONE_FMT_ASP}, 559 + {V4L2_PIX_FMT_H263, MALONE_FMT_ASP}, 560 + {V4L2_PIX_FMT_JPEG, MALONE_FMT_JPG}, 561 + {V4L2_PIX_FMT_VP8, MALONE_FMT_VP8}, 562 + }; 563 + 564 + static enum vpu_malone_format vpu_malone_format_remap(u32 pixelformat) 565 + { 566 + u32 i; 567 + 568 + for (i = 0; i < ARRAY_SIZE(fmt_mappings); i++) { 569 + if (pixelformat == fmt_mappings[i].pixelformat) 570 + return fmt_mappings[i].malone_format; 571 + } 572 + 573 + return MALONE_FMT_NULL; 574 + } 575 + 576 + static void vpu_malone_set_stream_cfg(struct vpu_shared_addr *shared, 577 + u32 instance, 578 + enum vpu_malone_format malone_format) 579 + { 580 + struct malone_iface *iface = shared->iface; 581 + u32 *curr_str_cfg = &iface->stream_config[instance]; 582 + 583 + *curr_str_cfg = 0; 584 + STREAM_CONFIG_FORMAT_SET(malone_format, curr_str_cfg); 585 + STREAM_CONFIG_STRBUFIDX_SET(0, curr_str_cfg); 586 + STREAM_CONFIG_NOSEQ_SET(0, curr_str_cfg); 587 + STREAM_CONFIG_DEBLOCK_SET(0, curr_str_cfg); 588 + STREAM_CONFIG_DERING_SET(0, curr_str_cfg); 589 + STREAM_CONFIG_PLAY_MODE_SET(0x3, curr_str_cfg); 590 + STREAM_CONFIG_FS_CTRL_MODE_SET(0x1, curr_str_cfg); 591 + STREAM_CONFIG_ENABLE_DCP_SET(1, curr_str_cfg); 592 + STREAM_CONFIG_NUM_STR_BUF_SET(1, curr_str_cfg); 593 + STREAM_CONFIG_MALONE_USAGE_SET(1, curr_str_cfg); 594 + STREAM_CONFIG_MULTI_VID_SET(0, curr_str_cfg); 595 + STREAM_CONFIG_OBFUSC_EN_SET(0, curr_str_cfg); 596 + STREAM_CONFIG_RC4_EN_SET(0, curr_str_cfg); 597 + STREAM_CONFIG_MCX_SET(1, curr_str_cfg); 598 + STREAM_CONFIG_PES_SET(0, curr_str_cfg); 599 + STREAM_CONFIG_NUM_DBE_SET(1, curr_str_cfg); 600 + } 601 + 602 + static int vpu_malone_set_params(struct vpu_shared_addr *shared, 603 + u32 instance, 604 + struct vpu_decode_params *params) 605 + { 606 + struct malone_iface *iface = shared->iface; 607 + struct vpu_dec_ctrl *hc = shared->priv; 608 + enum vpu_malone_format malone_format; 609 + 610 + malone_format = vpu_malone_format_remap(params->codec_format); 611 + iface->udata_buffer[instance].base = params->udata.base; 612 + iface->udata_buffer[instance].slot_size = params->udata.size; 613 + 614 + vpu_malone_set_stream_cfg(shared, instance, malone_format); 615 + 616 + if (malone_format == MALONE_FMT_JPG) { 617 + //1:JPGD_MJPEG_MODE_A; 2:JPGD_MJPEG_MODE_B 618 + hc->jpg[instance].jpg_mjpeg_mode = 1; 619 + //0: JPGD_MJPEG_PROGRESSIVE 620 + hc->jpg[instance].jpg_mjpeg_interlaced = 0; 621 + } 622 + 623 + hc->codec_param[instance].disp_imm = params->b_dis_reorder ? 1 : 0; 624 + hc->codec_param[instance].dbglog_enable = 0; 625 + iface->dbglog_desc.level = 0; 626 + 627 + if (params->b_non_frame) 628 + iface->stream_buff_info[instance].stream_input_mode = NON_FRAME_LVL; 629 + else 630 + iface->stream_buff_info[instance].stream_input_mode = FRAME_LVL; 631 + iface->stream_buff_info[instance].stream_buffer_threshold = 0; 632 + iface->stream_buff_info[instance].stream_pic_input_count = 0; 633 + 634 + return 0; 635 + } 636 + 637 + static bool vpu_malone_is_non_frame_mode(struct vpu_shared_addr *shared, u32 instance) 638 + { 639 + struct malone_iface *iface = shared->iface; 640 + 641 + if (iface->stream_buff_info[instance].stream_input_mode == NON_FRAME_LVL) 642 + return true; 643 + 644 + return false; 645 + } 646 + 647 + static int vpu_malone_update_params(struct vpu_shared_addr *shared, 648 + u32 instance, 649 + struct vpu_decode_params *params) 650 + { 651 + struct malone_iface *iface = shared->iface; 652 + 653 + if (params->end_flag) 654 + iface->stream_buff_info[instance].stream_pic_end_flag = params->end_flag; 655 + params->end_flag = 0; 656 + 657 + return 0; 658 + } 659 + 660 + int vpu_malone_set_decode_params(struct vpu_shared_addr *shared, 661 + u32 instance, 662 + struct vpu_decode_params *params, 663 + u32 update) 664 + { 665 + if (!params) 666 + return -EINVAL; 667 + 668 + if (!update) 669 + return vpu_malone_set_params(shared, instance, params); 670 + else 671 + return vpu_malone_update_params(shared, instance, params); 672 + } 673 + 674 + static struct vpu_pair malone_cmds[] = { 675 + {VPU_CMD_ID_START, VID_API_CMD_START}, 676 + {VPU_CMD_ID_STOP, VID_API_CMD_STOP}, 677 + {VPU_CMD_ID_ABORT, VID_API_CMD_ABORT}, 678 + {VPU_CMD_ID_RST_BUF, VID_API_CMD_RST_BUF}, 679 + {VPU_CMD_ID_SNAPSHOT, VID_API_CMD_SNAPSHOT}, 680 + {VPU_CMD_ID_FIRM_RESET, VID_API_CMD_FIRM_RESET}, 681 + {VPU_CMD_ID_FS_ALLOC, VID_API_CMD_FS_ALLOC}, 682 + {VPU_CMD_ID_FS_RELEASE, VID_API_CMD_FS_RELEASE}, 683 + {VPU_CMD_ID_TIMESTAMP, VID_API_CMD_TS}, 684 + {VPU_CMD_ID_DEBUG, VID_API_CMD_FW_STATUS}, 685 + }; 686 + 687 + static struct vpu_pair malone_msgs[] = { 688 + {VPU_MSG_ID_RESET_DONE, VID_API_EVENT_RESET_DONE}, 689 + {VPU_MSG_ID_START_DONE, VID_API_EVENT_START_DONE}, 690 + {VPU_MSG_ID_STOP_DONE, VID_API_EVENT_STOPPED}, 691 + {VPU_MSG_ID_ABORT_DONE, VID_API_EVENT_ABORT_DONE}, 692 + {VPU_MSG_ID_BUF_RST, VID_API_EVENT_STR_BUF_RST}, 693 + {VPU_MSG_ID_PIC_EOS, VID_API_EVENT_FINISHED}, 694 + {VPU_MSG_ID_SEQ_HDR_FOUND, VID_API_EVENT_SEQ_HDR_FOUND}, 695 + {VPU_MSG_ID_RES_CHANGE, VID_API_EVENT_RES_CHANGE}, 696 + {VPU_MSG_ID_PIC_HDR_FOUND, VID_API_EVENT_PIC_HDR_FOUND}, 697 + {VPU_MSG_ID_PIC_DECODED, VID_API_EVENT_PIC_DECODED}, 698 + {VPU_MSG_ID_DEC_DONE, VID_API_EVENT_FRAME_BUFF_RDY}, 699 + {VPU_MSG_ID_FRAME_REQ, VID_API_EVENT_REQ_FRAME_BUFF}, 700 + {VPU_MSG_ID_FRAME_RELEASE, VID_API_EVENT_REL_FRAME_BUFF}, 701 + {VPU_MSG_ID_FIFO_LOW, VID_API_EVENT_FIFO_LOW}, 702 + {VPU_MSG_ID_BS_ERROR, VID_API_EVENT_BS_ERROR}, 703 + {VPU_MSG_ID_UNSUPPORTED, VID_API_EVENT_UNSUPPORTED_STREAM}, 704 + {VPU_MSG_ID_FIRMWARE_XCPT, VID_API_EVENT_FIRMWARE_XCPT}, 705 + }; 706 + 707 + static void vpu_malone_pack_fs_alloc(struct vpu_rpc_event *pkt, 708 + struct vpu_fs_info *fs) 709 + { 710 + const u32 fs_type[] = { 711 + [MEM_RES_FRAME] = 0, 712 + [MEM_RES_MBI] = 1, 713 + [MEM_RES_DCP] = 2, 714 + }; 715 + 716 + pkt->hdr.num = 7; 717 + pkt->data[0] = fs->id | (fs->tag << 24); 718 + pkt->data[1] = fs->luma_addr; 719 + if (fs->type == MEM_RES_FRAME) { 720 + /* 721 + * if luma_addr equal to chroma_addr, 722 + * means luma(plane[0]) and chromau(plane[1]) used the 723 + * same fd -- usage of NXP codec2. Need to manually 724 + * offset chroma addr. 725 + */ 726 + if (fs->luma_addr == fs->chroma_addr) 727 + fs->chroma_addr = fs->luma_addr + fs->luma_size; 728 + pkt->data[2] = fs->luma_addr + fs->luma_size / 2; 729 + pkt->data[3] = fs->chroma_addr; 730 + pkt->data[4] = fs->chroma_addr + fs->chromau_size / 2; 731 + pkt->data[5] = fs->bytesperline; 732 + } else { 733 + pkt->data[2] = fs->luma_size; 734 + pkt->data[3] = 0; 735 + pkt->data[4] = 0; 736 + pkt->data[5] = 0; 737 + } 738 + pkt->data[6] = fs_type[fs->type]; 739 + } 740 + 741 + static void vpu_malone_pack_fs_release(struct vpu_rpc_event *pkt, 742 + struct vpu_fs_info *fs) 743 + { 744 + pkt->hdr.num = 1; 745 + pkt->data[0] = fs->id | (fs->tag << 24); 746 + } 747 + 748 + static void vpu_malone_pack_timestamp(struct vpu_rpc_event *pkt, 749 + struct vpu_ts_info *info) 750 + { 751 + pkt->hdr.num = 3; 752 + if (info->timestamp < 0) { 753 + pkt->data[0] = (u32)-1; 754 + pkt->data[1] = 0; 755 + } else { 756 + pkt->data[0] = info->timestamp / NSEC_PER_SEC; 757 + pkt->data[1] = info->timestamp % NSEC_PER_SEC; 758 + } 759 + pkt->data[2] = info->size; 760 + } 761 + 762 + int vpu_malone_pack_cmd(struct vpu_rpc_event *pkt, u32 index, u32 id, void *data) 763 + { 764 + int ret; 765 + 766 + ret = vpu_find_dst_by_src(malone_cmds, ARRAY_SIZE(malone_cmds), id); 767 + if (ret < 0) 768 + return ret; 769 + 770 + pkt->hdr.id = ret; 771 + pkt->hdr.num = 0; 772 + pkt->hdr.index = index; 773 + 774 + switch (id) { 775 + case VPU_CMD_ID_FS_ALLOC: 776 + vpu_malone_pack_fs_alloc(pkt, data); 777 + break; 778 + case VPU_CMD_ID_FS_RELEASE: 779 + vpu_malone_pack_fs_release(pkt, data); 780 + break; 781 + case VPU_CMD_ID_TIMESTAMP: 782 + vpu_malone_pack_timestamp(pkt, data); 783 + break; 784 + } 785 + 786 + pkt->hdr.index = index; 787 + return 0; 788 + } 789 + 790 + int vpu_malone_convert_msg_id(u32 id) 791 + { 792 + return vpu_find_src_by_dst(malone_msgs, ARRAY_SIZE(malone_msgs), id); 793 + } 794 + 795 + static void vpu_malone_fill_planes(struct vpu_dec_codec_info *info) 796 + { 797 + u32 interlaced = info->progressive ? 0 : 1; 798 + 799 + info->bytesperline[0] = 0; 800 + info->sizeimage[0] = vpu_helper_get_plane_size(info->pixfmt, 801 + info->decoded_width, 802 + info->decoded_height, 803 + 0, 804 + info->stride, 805 + interlaced, 806 + &info->bytesperline[0]); 807 + info->bytesperline[1] = 0; 808 + info->sizeimage[1] = vpu_helper_get_plane_size(info->pixfmt, 809 + info->decoded_width, 810 + info->decoded_height, 811 + 1, 812 + info->stride, 813 + interlaced, 814 + &info->bytesperline[1]); 815 + } 816 + 817 + static void vpu_malone_init_seq_hdr(struct vpu_dec_codec_info *info) 818 + { 819 + u32 chunks = info->num_dfe_area >> MALONE_DCP_CHUNK_BIT; 820 + 821 + vpu_malone_fill_planes(info); 822 + 823 + info->mbi_size = (info->sizeimage[0] + info->sizeimage[1]) >> 2; 824 + info->mbi_size = ALIGN(info->mbi_size, MALONE_ALIGN_MBI); 825 + 826 + info->dcp_size = MALONE_DCP_SIZE_MAX; 827 + if (chunks) { 828 + u32 mb_num; 829 + u32 mb_w; 830 + u32 mb_h; 831 + 832 + mb_w = DIV_ROUND_UP(info->decoded_width, 16); 833 + mb_h = DIV_ROUND_UP(info->decoded_height, 16); 834 + mb_num = mb_w * mb_h; 835 + info->dcp_size = mb_num * MALONE_DCP_FIXED_MB_ALLOC * chunks; 836 + info->dcp_size = clamp_t(u32, info->dcp_size, 837 + MALONE_DCP_SIZE_MIN, MALONE_DCP_SIZE_MAX); 838 + } 839 + } 840 + 841 + static void vpu_malone_unpack_seq_hdr(struct vpu_rpc_event *pkt, 842 + struct vpu_dec_codec_info *info) 843 + { 844 + info->num_ref_frms = pkt->data[0]; 845 + info->num_dpb_frms = pkt->data[1]; 846 + info->num_dfe_area = pkt->data[2]; 847 + info->progressive = pkt->data[3]; 848 + info->width = pkt->data[5]; 849 + info->height = pkt->data[4]; 850 + info->decoded_width = pkt->data[12]; 851 + info->decoded_height = pkt->data[11]; 852 + info->frame_rate.numerator = 1000; 853 + info->frame_rate.denominator = pkt->data[8]; 854 + info->dsp_asp_ratio = pkt->data[9]; 855 + info->level_idc = pkt->data[10]; 856 + info->bit_depth_luma = pkt->data[13]; 857 + info->bit_depth_chroma = pkt->data[14]; 858 + info->chroma_fmt = pkt->data[15]; 859 + info->color_primaries = vpu_color_cvrt_primaries_i2v(pkt->data[16]); 860 + info->transfer_chars = vpu_color_cvrt_transfers_i2v(pkt->data[17]); 861 + info->matrix_coeffs = vpu_color_cvrt_matrix_i2v(pkt->data[18]); 862 + info->full_range = vpu_color_cvrt_full_range_i2v(pkt->data[19]); 863 + info->vui_present = pkt->data[20]; 864 + info->mvc_num_views = pkt->data[21]; 865 + info->offset_x = pkt->data[23]; 866 + info->offset_y = pkt->data[25]; 867 + info->tag = pkt->data[27]; 868 + if (info->bit_depth_luma > 8) 869 + info->pixfmt = V4L2_PIX_FMT_NV12M_10BE_8L128; 870 + else 871 + info->pixfmt = V4L2_PIX_FMT_NV12M_8L128; 872 + if (info->frame_rate.numerator && info->frame_rate.denominator) { 873 + unsigned long n, d; 874 + 875 + rational_best_approximation(info->frame_rate.numerator, 876 + info->frame_rate.denominator, 877 + info->frame_rate.numerator, 878 + info->frame_rate.denominator, 879 + &n, &d); 880 + info->frame_rate.numerator = n; 881 + info->frame_rate.denominator = d; 882 + } 883 + vpu_malone_init_seq_hdr(info); 884 + } 885 + 886 + static void vpu_malone_unpack_pic_info(struct vpu_rpc_event *pkt, 887 + struct vpu_dec_pic_info *info) 888 + { 889 + info->id = pkt->data[7]; 890 + info->luma = pkt->data[0]; 891 + info->start = pkt->data[10]; 892 + info->end = pkt->data[12]; 893 + info->pic_size = pkt->data[11]; 894 + info->stride = pkt->data[5]; 895 + info->consumed_count = pkt->data[13]; 896 + if (info->id == MALONE_SKIPPED_FRAME_ID) 897 + info->skipped = 1; 898 + else 899 + info->skipped = 0; 900 + } 901 + 902 + static void vpu_malone_unpack_req_frame(struct vpu_rpc_event *pkt, 903 + struct vpu_fs_info *info) 904 + { 905 + info->type = pkt->data[1]; 906 + } 907 + 908 + static void vpu_malone_unpack_rel_frame(struct vpu_rpc_event *pkt, 909 + struct vpu_fs_info *info) 910 + { 911 + info->id = pkt->data[0]; 912 + info->type = pkt->data[1]; 913 + info->not_displayed = pkt->data[2]; 914 + } 915 + 916 + static void vpu_malone_unpack_buff_rdy(struct vpu_rpc_event *pkt, 917 + struct vpu_dec_pic_info *info) 918 + { 919 + info->id = pkt->data[0]; 920 + info->luma = pkt->data[1]; 921 + info->stride = pkt->data[3]; 922 + if (info->id == MALONE_SKIPPED_FRAME_ID) 923 + info->skipped = 1; 924 + else 925 + info->skipped = 0; 926 + info->timestamp = MAKE_TIMESTAMP(pkt->data[9], pkt->data[10]); 927 + } 928 + 929 + int vpu_malone_unpack_msg_data(struct vpu_rpc_event *pkt, void *data) 930 + { 931 + if (!pkt || !data) 932 + return -EINVAL; 933 + 934 + switch (pkt->hdr.id) { 935 + case VID_API_EVENT_SEQ_HDR_FOUND: 936 + vpu_malone_unpack_seq_hdr(pkt, data); 937 + break; 938 + case VID_API_EVENT_PIC_DECODED: 939 + vpu_malone_unpack_pic_info(pkt, data); 940 + break; 941 + case VID_API_EVENT_REQ_FRAME_BUFF: 942 + vpu_malone_unpack_req_frame(pkt, data); 943 + break; 944 + case VID_API_EVENT_REL_FRAME_BUFF: 945 + vpu_malone_unpack_rel_frame(pkt, data); 946 + break; 947 + case VID_API_EVENT_FRAME_BUFF_RDY: 948 + vpu_malone_unpack_buff_rdy(pkt, data); 949 + break; 950 + } 951 + 952 + return 0; 953 + } 954 + 955 + static const struct malone_padding_scode padding_scodes[] = { 956 + {SCODE_PADDING_EOS, V4L2_PIX_FMT_H264, {0x0B010000, 0}}, 957 + {SCODE_PADDING_EOS, V4L2_PIX_FMT_H264_MVC, {0x0B010000, 0}}, 958 + {SCODE_PADDING_EOS, V4L2_PIX_FMT_HEVC, {0x4A010000, 0x20}}, 959 + {SCODE_PADDING_EOS, V4L2_PIX_FMT_VC1_ANNEX_G, {0x0a010000, 0x0}}, 960 + {SCODE_PADDING_EOS, V4L2_PIX_FMT_VC1_ANNEX_L, {0x0a010000, 0x0}}, 961 + {SCODE_PADDING_EOS, V4L2_PIX_FMT_MPEG2, {0xCC010000, 0x0}}, 962 + {SCODE_PADDING_EOS, V4L2_PIX_FMT_MPEG4, {0xb1010000, 0x0}}, 963 + {SCODE_PADDING_EOS, V4L2_PIX_FMT_XVID, {0xb1010000, 0x0}}, 964 + {SCODE_PADDING_EOS, V4L2_PIX_FMT_H263, {0xb1010000, 0x0}}, 965 + {SCODE_PADDING_EOS, V4L2_PIX_FMT_VP8, {0x34010000, 0x0}}, 966 + {SCODE_PADDING_EOS, V4L2_PIX_FMT_JPEG, {0xefff0000, 0x0}}, 967 + {SCODE_PADDING_ABORT, V4L2_PIX_FMT_H264, {0x0B010000, 0}}, 968 + {SCODE_PADDING_ABORT, V4L2_PIX_FMT_H264_MVC, {0x0B010000, 0}}, 969 + {SCODE_PADDING_ABORT, V4L2_PIX_FMT_HEVC, {0x4A010000, 0x20}}, 970 + {SCODE_PADDING_ABORT, V4L2_PIX_FMT_VC1_ANNEX_G, {0x0a010000, 0x0}}, 971 + {SCODE_PADDING_ABORT, V4L2_PIX_FMT_VC1_ANNEX_L, {0x0a010000, 0x0}}, 972 + {SCODE_PADDING_ABORT, V4L2_PIX_FMT_MPEG2, {0xb7010000, 0x0}}, 973 + {SCODE_PADDING_ABORT, V4L2_PIX_FMT_MPEG4, {0xb1010000, 0x0}}, 974 + {SCODE_PADDING_ABORT, V4L2_PIX_FMT_XVID, {0xb1010000, 0x0}}, 975 + {SCODE_PADDING_ABORT, V4L2_PIX_FMT_H263, {0xb1010000, 0x0}}, 976 + {SCODE_PADDING_ABORT, V4L2_PIX_FMT_VP8, {0x34010000, 0x0}}, 977 + {SCODE_PADDING_EOS, V4L2_PIX_FMT_JPEG, {0x0, 0x0}}, 978 + {SCODE_PADDING_BUFFLUSH, V4L2_PIX_FMT_H264, {0x15010000, 0x0}}, 979 + {SCODE_PADDING_BUFFLUSH, V4L2_PIX_FMT_H264_MVC, {0x15010000, 0x0}}, 980 + }; 981 + 982 + static const struct malone_padding_scode padding_scode_dft = {0x0, 0x0}; 983 + 984 + static const struct malone_padding_scode *get_padding_scode(u32 type, u32 fmt) 985 + { 986 + const struct malone_padding_scode *s; 987 + int i; 988 + 989 + for (i = 0; i < ARRAY_SIZE(padding_scodes); i++) { 990 + s = &padding_scodes[i]; 991 + 992 + if (s->scode_type == type && s->pixelformat == fmt) 993 + return s; 994 + } 995 + 996 + if (type != SCODE_PADDING_BUFFLUSH) 997 + return &padding_scode_dft; 998 + 999 + return NULL; 1000 + } 1001 + 1002 + static int vpu_malone_add_padding_scode(struct vpu_buffer *stream_buffer, 1003 + struct vpu_malone_str_buffer __iomem *str_buf, 1004 + u32 pixelformat, u32 scode_type) 1005 + { 1006 + u32 wptr; 1007 + u32 size; 1008 + u32 total_size = 0; 1009 + const struct malone_padding_scode *ps; 1010 + const u32 padding_size = 4096; 1011 + int ret; 1012 + 1013 + ps = get_padding_scode(scode_type, pixelformat); 1014 + if (!ps) 1015 + return -EINVAL; 1016 + 1017 + wptr = readl(&str_buf->wptr); 1018 + size = ALIGN(wptr, 4) - wptr; 1019 + if (size) 1020 + vpu_helper_memset_stream_buffer(stream_buffer, &wptr, 0, size); 1021 + total_size += size; 1022 + 1023 + size = sizeof(ps->data); 1024 + ret = vpu_helper_copy_to_stream_buffer(stream_buffer, &wptr, size, (void *)ps->data); 1025 + if (ret < size) 1026 + return -EINVAL; 1027 + total_size += size; 1028 + 1029 + size = padding_size - sizeof(ps->data); 1030 + vpu_helper_memset_stream_buffer(stream_buffer, &wptr, 0, size); 1031 + total_size += size; 1032 + 1033 + vpu_malone_update_wptr(str_buf, wptr); 1034 + return total_size; 1035 + } 1036 + 1037 + int vpu_malone_add_scode(struct vpu_shared_addr *shared, 1038 + u32 instance, 1039 + struct vpu_buffer *stream_buffer, 1040 + u32 pixelformat, 1041 + u32 scode_type) 1042 + { 1043 + struct vpu_dec_ctrl *hc = shared->priv; 1044 + struct vpu_malone_str_buffer __iomem *str_buf = hc->str_buf[instance]; 1045 + int ret = -EINVAL; 1046 + 1047 + switch (scode_type) { 1048 + case SCODE_PADDING_EOS: 1049 + case SCODE_PADDING_ABORT: 1050 + case SCODE_PADDING_BUFFLUSH: 1051 + ret = vpu_malone_add_padding_scode(stream_buffer, str_buf, pixelformat, scode_type); 1052 + break; 1053 + default: 1054 + break; 1055 + } 1056 + 1057 + return ret; 1058 + } 1059 + 1060 + #define MALONE_PAYLOAD_HEADER_SIZE 16 1061 + #define MALONE_CODEC_VERSION_ID 0x1 1062 + #define MALONE_CODEC_ID_VC1_SIMPLE 0x10 1063 + #define MALONE_CODEC_ID_VC1_MAIN 0x11 1064 + #define MALONE_CODEC_ID_ARV8 0x28 1065 + #define MALONE_CODEC_ID_ARV9 0x29 1066 + #define MALONE_CODEC_ID_VP6 0x36 1067 + #define MALONE_CODEC_ID_VP8 0x36 1068 + #define MALONE_CODEC_ID_DIVX3 0x38 1069 + #define MALONE_CODEC_ID_SPK 0x39 1070 + 1071 + #define MALONE_VP8_IVF_SEQ_HEADER_LEN 32 1072 + #define MALONE_VP8_IVF_FRAME_HEADER_LEN 8 1073 + 1074 + #define MALONE_VC1_RCV_CODEC_V1_VERSION 0x85 1075 + #define MALONE_VC1_RCV_CODEC_V2_VERSION 0xC5 1076 + #define MALONE_VC1_RCV_NUM_FRAMES 0xFF 1077 + #define MALONE_VC1_RCV_SEQ_EXT_DATA_SIZE 4 1078 + #define MALONE_VC1_RCV_SEQ_HEADER_LEN 20 1079 + #define MALONE_VC1_RCV_PIC_HEADER_LEN 4 1080 + #define MALONE_VC1_NAL_HEADER_LEN 4 1081 + #define MALONE_VC1_CONTAIN_NAL(data) (((data) & 0x00FFFFFF) == 0x00010000) 1082 + 1083 + static void set_payload_hdr(u8 *dst, u32 scd_type, u32 codec_id, 1084 + u32 buffer_size, u32 width, u32 height) 1085 + { 1086 + unsigned int payload_size; 1087 + /* payload_size = buffer_size + itself_size(16) - start_code(4) */ 1088 + payload_size = buffer_size + 12; 1089 + 1090 + dst[0] = 0x00; 1091 + dst[1] = 0x00; 1092 + dst[2] = 0x01; 1093 + dst[3] = scd_type; 1094 + 1095 + /* length */ 1096 + dst[4] = ((payload_size >> 16) & 0xff); 1097 + dst[5] = ((payload_size >> 8) & 0xff); 1098 + dst[6] = 0x4e; 1099 + dst[7] = ((payload_size >> 0) & 0xff); 1100 + 1101 + /* Codec ID and Version */ 1102 + dst[8] = codec_id; 1103 + dst[9] = MALONE_CODEC_VERSION_ID; 1104 + 1105 + /* width */ 1106 + dst[10] = ((width >> 8) & 0xff); 1107 + dst[11] = ((width >> 0) & 0xff); 1108 + dst[12] = 0x58; 1109 + 1110 + /* height */ 1111 + dst[13] = ((height >> 8) & 0xff); 1112 + dst[14] = ((height >> 0) & 0xff); 1113 + dst[15] = 0x50; 1114 + } 1115 + 1116 + static void set_vp8_ivf_seqhdr(u8 *dst, u32 width, u32 height) 1117 + { 1118 + /* 0-3byte signature "DKIF" */ 1119 + dst[0] = 0x44; 1120 + dst[1] = 0x4b; 1121 + dst[2] = 0x49; 1122 + dst[3] = 0x46; 1123 + /* 4-5byte version: should be 0*/ 1124 + dst[4] = 0x00; 1125 + dst[5] = 0x00; 1126 + /* 6-7 length of Header */ 1127 + dst[6] = MALONE_VP8_IVF_SEQ_HEADER_LEN; 1128 + dst[7] = MALONE_VP8_IVF_SEQ_HEADER_LEN >> 8; 1129 + /* 8-11 VP8 fourcc */ 1130 + dst[8] = 0x56; 1131 + dst[9] = 0x50; 1132 + dst[10] = 0x38; 1133 + dst[11] = 0x30; 1134 + /* 12-13 width in pixels */ 1135 + dst[12] = width; 1136 + dst[13] = width >> 8; 1137 + /* 14-15 height in pixels */ 1138 + dst[14] = height; 1139 + dst[15] = height >> 8; 1140 + /* 16-19 frame rate */ 1141 + dst[16] = 0xe8; 1142 + dst[17] = 0x03; 1143 + dst[18] = 0x00; 1144 + dst[19] = 0x00; 1145 + /* 20-23 time scale */ 1146 + dst[20] = 0x01; 1147 + dst[21] = 0x00; 1148 + dst[22] = 0x00; 1149 + dst[23] = 0x00; 1150 + /* 24-27 number frames */ 1151 + dst[24] = 0xdf; 1152 + dst[25] = 0xf9; 1153 + dst[26] = 0x09; 1154 + dst[27] = 0x00; 1155 + /* 28-31 reserved */ 1156 + } 1157 + 1158 + static void set_vp8_ivf_pichdr(u8 *dst, u32 frame_size) 1159 + { 1160 + /* 1161 + * firmware just parse 64-bit timestamp(8 bytes). 1162 + * As not transfer timestamp to firmware, use default value(ZERO). 1163 + * No need to do anything here 1164 + */ 1165 + } 1166 + 1167 + static void set_vc1_rcv_seqhdr(u8 *dst, u8 *src, u32 width, u32 height) 1168 + { 1169 + u32 frames = MALONE_VC1_RCV_NUM_FRAMES; 1170 + u32 ext_data_size = MALONE_VC1_RCV_SEQ_EXT_DATA_SIZE; 1171 + 1172 + /* 0-2 Number of frames, used default value 0xFF */ 1173 + dst[0] = frames; 1174 + dst[1] = frames >> 8; 1175 + dst[2] = frames >> 16; 1176 + 1177 + /* 3 RCV version, used V1 */ 1178 + dst[3] = MALONE_VC1_RCV_CODEC_V1_VERSION; 1179 + 1180 + /* 4-7 extension data size */ 1181 + dst[4] = ext_data_size; 1182 + dst[5] = ext_data_size >> 8; 1183 + dst[6] = ext_data_size >> 16; 1184 + dst[7] = ext_data_size >> 24; 1185 + /* 8-11 extension data */ 1186 + dst[8] = src[0]; 1187 + dst[9] = src[1]; 1188 + dst[10] = src[2]; 1189 + dst[11] = src[3]; 1190 + 1191 + /* height */ 1192 + dst[12] = height; 1193 + dst[13] = (height >> 8) & 0xff; 1194 + dst[14] = (height >> 16) & 0xff; 1195 + dst[15] = (height >> 24) & 0xff; 1196 + /* width */ 1197 + dst[16] = width; 1198 + dst[17] = (width >> 8) & 0xff; 1199 + dst[18] = (width >> 16) & 0xff; 1200 + dst[19] = (width >> 24) & 0xff; 1201 + } 1202 + 1203 + static void set_vc1_rcv_pichdr(u8 *dst, u32 buffer_size) 1204 + { 1205 + dst[0] = buffer_size; 1206 + dst[1] = buffer_size >> 8; 1207 + dst[2] = buffer_size >> 16; 1208 + dst[3] = buffer_size >> 24; 1209 + } 1210 + 1211 + static void create_vc1_nal_pichdr(u8 *dst) 1212 + { 1213 + /* need insert nal header: special ID */ 1214 + dst[0] = 0x0; 1215 + dst[1] = 0x0; 1216 + dst[2] = 0x01; 1217 + dst[3] = 0x0D; 1218 + } 1219 + 1220 + static int vpu_malone_insert_scode_seq(struct malone_scode_t *scode, u32 codec_id, u32 ext_size) 1221 + { 1222 + u8 hdr[MALONE_PAYLOAD_HEADER_SIZE]; 1223 + int ret; 1224 + 1225 + set_payload_hdr(hdr, 1226 + SCODE_SEQUENCE, 1227 + codec_id, 1228 + ext_size, 1229 + scode->inst->out_format.width, 1230 + scode->inst->out_format.height); 1231 + ret = vpu_helper_copy_to_stream_buffer(&scode->inst->stream_buffer, 1232 + &scode->wptr, 1233 + sizeof(hdr), 1234 + hdr); 1235 + return ret; 1236 + } 1237 + 1238 + static int vpu_malone_insert_scode_pic(struct malone_scode_t *scode, u32 codec_id, u32 ext_size) 1239 + { 1240 + u8 hdr[MALONE_PAYLOAD_HEADER_SIZE]; 1241 + 1242 + set_payload_hdr(hdr, 1243 + SCODE_PICTURE, 1244 + codec_id, 1245 + ext_size + vb2_get_plane_payload(scode->vb, 0), 1246 + scode->inst->out_format.width, 1247 + scode->inst->out_format.height); 1248 + return vpu_helper_copy_to_stream_buffer(&scode->inst->stream_buffer, 1249 + &scode->wptr, 1250 + sizeof(hdr), 1251 + hdr); 1252 + } 1253 + 1254 + static int vpu_malone_insert_scode_vc1_g_pic(struct malone_scode_t *scode) 1255 + { 1256 + struct vb2_v4l2_buffer *vbuf; 1257 + u8 nal_hdr[MALONE_VC1_NAL_HEADER_LEN]; 1258 + u32 *data = NULL; 1259 + 1260 + vbuf = to_vb2_v4l2_buffer(scode->vb); 1261 + data = vb2_plane_vaddr(scode->vb, 0); 1262 + 1263 + if (vbuf->sequence == 0 || vpu_vb_is_codecconfig(vbuf)) 1264 + return 0; 1265 + if (MALONE_VC1_CONTAIN_NAL(*data)) 1266 + return 0; 1267 + 1268 + create_vc1_nal_pichdr(nal_hdr); 1269 + return vpu_helper_copy_to_stream_buffer(&scode->inst->stream_buffer, 1270 + &scode->wptr, 1271 + sizeof(nal_hdr), 1272 + nal_hdr); 1273 + } 1274 + 1275 + static int vpu_malone_insert_scode_vc1_l_seq(struct malone_scode_t *scode) 1276 + { 1277 + int ret; 1278 + int size = 0; 1279 + u8 rcv_seqhdr[MALONE_VC1_RCV_SEQ_HEADER_LEN]; 1280 + 1281 + scode->need_data = 0; 1282 + 1283 + ret = vpu_malone_insert_scode_seq(scode, MALONE_CODEC_ID_VC1_SIMPLE, 1284 + sizeof(rcv_seqhdr)); 1285 + if (ret < 0) 1286 + return ret; 1287 + size = ret; 1288 + 1289 + set_vc1_rcv_seqhdr(rcv_seqhdr, 1290 + vb2_plane_vaddr(scode->vb, 0), 1291 + scode->inst->out_format.width, 1292 + scode->inst->out_format.height); 1293 + ret = vpu_helper_copy_to_stream_buffer(&scode->inst->stream_buffer, 1294 + &scode->wptr, 1295 + sizeof(rcv_seqhdr), 1296 + rcv_seqhdr); 1297 + 1298 + if (ret < 0) 1299 + return ret; 1300 + size += ret; 1301 + return size; 1302 + } 1303 + 1304 + static int vpu_malone_insert_scode_vc1_l_pic(struct malone_scode_t *scode) 1305 + { 1306 + int ret; 1307 + int size = 0; 1308 + u8 rcv_pichdr[MALONE_VC1_RCV_PIC_HEADER_LEN]; 1309 + 1310 + ret = vpu_malone_insert_scode_pic(scode, MALONE_CODEC_ID_VC1_SIMPLE, 1311 + sizeof(rcv_pichdr)); 1312 + if (ret < 0) 1313 + return ret; 1314 + size = ret; 1315 + 1316 + set_vc1_rcv_pichdr(rcv_pichdr, vb2_get_plane_payload(scode->vb, 0)); 1317 + ret = vpu_helper_copy_to_stream_buffer(&scode->inst->stream_buffer, 1318 + &scode->wptr, 1319 + sizeof(rcv_pichdr), 1320 + rcv_pichdr); 1321 + if (ret < 0) 1322 + return ret; 1323 + size += ret; 1324 + return size; 1325 + } 1326 + 1327 + static int vpu_malone_insert_scode_vp8_seq(struct malone_scode_t *scode) 1328 + { 1329 + int ret; 1330 + int size = 0; 1331 + u8 ivf_hdr[MALONE_VP8_IVF_SEQ_HEADER_LEN]; 1332 + 1333 + ret = vpu_malone_insert_scode_seq(scode, MALONE_CODEC_ID_VP8, sizeof(ivf_hdr)); 1334 + if (ret < 0) 1335 + return ret; 1336 + size = ret; 1337 + 1338 + set_vp8_ivf_seqhdr(ivf_hdr, 1339 + scode->inst->out_format.width, 1340 + scode->inst->out_format.height); 1341 + ret = vpu_helper_copy_to_stream_buffer(&scode->inst->stream_buffer, 1342 + &scode->wptr, 1343 + sizeof(ivf_hdr), 1344 + ivf_hdr); 1345 + if (ret < 0) 1346 + return ret; 1347 + size += ret; 1348 + 1349 + return size; 1350 + } 1351 + 1352 + static int vpu_malone_insert_scode_vp8_pic(struct malone_scode_t *scode) 1353 + { 1354 + int ret; 1355 + int size = 0; 1356 + u8 ivf_hdr[MALONE_VP8_IVF_FRAME_HEADER_LEN] = {0}; 1357 + 1358 + ret = vpu_malone_insert_scode_pic(scode, MALONE_CODEC_ID_VP8, sizeof(ivf_hdr)); 1359 + if (ret < 0) 1360 + return ret; 1361 + size = ret; 1362 + 1363 + set_vp8_ivf_pichdr(ivf_hdr, vb2_get_plane_payload(scode->vb, 0)); 1364 + ret = vpu_helper_copy_to_stream_buffer(&scode->inst->stream_buffer, 1365 + &scode->wptr, 1366 + sizeof(ivf_hdr), 1367 + ivf_hdr); 1368 + if (ret < 0) 1369 + return ret; 1370 + size += ret; 1371 + 1372 + return size; 1373 + } 1374 + 1375 + static const struct malone_scode_handler scode_handlers[] = { 1376 + { 1377 + /* fix me, need to swap return operation after gstreamer swap */ 1378 + .pixelformat = V4L2_PIX_FMT_VC1_ANNEX_L, 1379 + .insert_scode_seq = vpu_malone_insert_scode_vc1_l_seq, 1380 + .insert_scode_pic = vpu_malone_insert_scode_vc1_l_pic, 1381 + }, 1382 + { 1383 + .pixelformat = V4L2_PIX_FMT_VC1_ANNEX_G, 1384 + .insert_scode_pic = vpu_malone_insert_scode_vc1_g_pic, 1385 + }, 1386 + { 1387 + .pixelformat = V4L2_PIX_FMT_VP8, 1388 + .insert_scode_seq = vpu_malone_insert_scode_vp8_seq, 1389 + .insert_scode_pic = vpu_malone_insert_scode_vp8_pic, 1390 + }, 1391 + }; 1392 + 1393 + static const struct malone_scode_handler *get_scode_handler(u32 pixelformat) 1394 + { 1395 + int i; 1396 + 1397 + for (i = 0; i < ARRAY_SIZE(scode_handlers); i++) { 1398 + if (scode_handlers[i].pixelformat == pixelformat) 1399 + return &scode_handlers[i]; 1400 + } 1401 + 1402 + return NULL; 1403 + } 1404 + 1405 + static int vpu_malone_insert_scode(struct malone_scode_t *scode, u32 type) 1406 + { 1407 + const struct malone_scode_handler *handler; 1408 + int ret = 0; 1409 + 1410 + if (!scode || !scode->inst || !scode->vb) 1411 + return 0; 1412 + 1413 + scode->need_data = 1; 1414 + handler = get_scode_handler(scode->inst->out_format.pixfmt); 1415 + if (!handler) 1416 + return 0; 1417 + 1418 + switch (type) { 1419 + case SCODE_SEQUENCE: 1420 + if (handler->insert_scode_seq) 1421 + ret = handler->insert_scode_seq(scode); 1422 + break; 1423 + case SCODE_PICTURE: 1424 + if (handler->insert_scode_pic) 1425 + ret = handler->insert_scode_pic(scode); 1426 + break; 1427 + default: 1428 + break; 1429 + } 1430 + 1431 + return ret; 1432 + } 1433 + 1434 + static int vpu_malone_input_frame_data(struct vpu_malone_str_buffer __iomem *str_buf, 1435 + struct vpu_inst *inst, struct vb2_buffer *vb, 1436 + u32 disp_imm) 1437 + { 1438 + struct malone_scode_t scode; 1439 + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 1440 + u32 wptr = readl(&str_buf->wptr); 1441 + int size = 0; 1442 + int ret = 0; 1443 + 1444 + /*add scode: SCODE_SEQUENCE, SCODE_PICTURE, SCODE_SLICE*/ 1445 + scode.inst = inst; 1446 + scode.vb = vb; 1447 + scode.wptr = wptr; 1448 + scode.need_data = 1; 1449 + if (vbuf->sequence == 0 || vpu_vb_is_codecconfig(vbuf)) 1450 + ret = vpu_malone_insert_scode(&scode, SCODE_SEQUENCE); 1451 + 1452 + if (ret < 0) 1453 + return -ENOMEM; 1454 + size += ret; 1455 + wptr = scode.wptr; 1456 + if (!scode.need_data) { 1457 + vpu_malone_update_wptr(str_buf, wptr); 1458 + return size; 1459 + } 1460 + 1461 + ret = vpu_malone_insert_scode(&scode, SCODE_PICTURE); 1462 + if (ret < 0) 1463 + return -ENOMEM; 1464 + size += ret; 1465 + wptr = scode.wptr; 1466 + 1467 + ret = vpu_helper_copy_to_stream_buffer(&inst->stream_buffer, 1468 + &wptr, 1469 + vb2_get_plane_payload(vb, 0), 1470 + vb2_plane_vaddr(vb, 0)); 1471 + if (ret < vb2_get_plane_payload(vb, 0)) 1472 + return -ENOMEM; 1473 + size += ret; 1474 + 1475 + vpu_malone_update_wptr(str_buf, wptr); 1476 + 1477 + if (disp_imm && !vpu_vb_is_codecconfig(vbuf)) { 1478 + ret = vpu_malone_add_scode(inst->core->iface, 1479 + inst->id, 1480 + &inst->stream_buffer, 1481 + inst->out_format.pixfmt, 1482 + SCODE_PADDING_BUFFLUSH); 1483 + if (ret < 0) 1484 + return ret; 1485 + size += ret; 1486 + } 1487 + 1488 + return size; 1489 + } 1490 + 1491 + static int vpu_malone_input_stream_data(struct vpu_malone_str_buffer __iomem *str_buf, 1492 + struct vpu_inst *inst, struct vb2_buffer *vb) 1493 + { 1494 + u32 wptr = readl(&str_buf->wptr); 1495 + int ret = 0; 1496 + 1497 + ret = vpu_helper_copy_to_stream_buffer(&inst->stream_buffer, 1498 + &wptr, 1499 + vb2_get_plane_payload(vb, 0), 1500 + vb2_plane_vaddr(vb, 0)); 1501 + if (ret < vb2_get_plane_payload(vb, 0)) 1502 + return -ENOMEM; 1503 + 1504 + vpu_malone_update_wptr(str_buf, wptr); 1505 + 1506 + return ret; 1507 + } 1508 + 1509 + static int vpu_malone_input_ts(struct vpu_inst *inst, s64 timestamp, u32 size) 1510 + { 1511 + struct vpu_ts_info info; 1512 + 1513 + memset(&info, 0, sizeof(info)); 1514 + info.timestamp = timestamp; 1515 + info.size = size; 1516 + 1517 + return vpu_session_fill_timestamp(inst, &info); 1518 + } 1519 + 1520 + int vpu_malone_input_frame(struct vpu_shared_addr *shared, 1521 + struct vpu_inst *inst, struct vb2_buffer *vb) 1522 + { 1523 + struct vpu_dec_ctrl *hc = shared->priv; 1524 + struct vb2_v4l2_buffer *vbuf; 1525 + struct vpu_malone_str_buffer __iomem *str_buf = hc->str_buf[inst->id]; 1526 + u32 disp_imm = hc->codec_param[inst->id].disp_imm; 1527 + u32 size; 1528 + int ret; 1529 + 1530 + if (vpu_malone_is_non_frame_mode(shared, inst->id)) 1531 + ret = vpu_malone_input_stream_data(str_buf, inst, vb); 1532 + else 1533 + ret = vpu_malone_input_frame_data(str_buf, inst, vb, disp_imm); 1534 + if (ret < 0) 1535 + return ret; 1536 + size = ret; 1537 + 1538 + /* 1539 + * if buffer only contain codec data, and the timestamp is invalid, 1540 + * don't put the invalid timestamp to resync 1541 + * merge the data to next frame 1542 + */ 1543 + vbuf = to_vb2_v4l2_buffer(vb); 1544 + if (vpu_vb_is_codecconfig(vbuf) && (s64)vb->timestamp < 0) { 1545 + inst->extra_size += size; 1546 + return 0; 1547 + } 1548 + if (inst->extra_size) { 1549 + size += inst->extra_size; 1550 + inst->extra_size = 0; 1551 + } 1552 + 1553 + ret = vpu_malone_input_ts(inst, vb->timestamp, size); 1554 + if (ret) 1555 + return ret; 1556 + 1557 + return 0; 1558 + } 1559 + 1560 + static bool vpu_malone_check_ready(struct vpu_shared_addr *shared, u32 instance) 1561 + { 1562 + struct malone_iface *iface = shared->iface; 1563 + struct vpu_rpc_buffer_desc *desc = &iface->api_cmd_buffer_desc[instance]; 1564 + u32 size = desc->end - desc->start; 1565 + u32 rptr = desc->rptr; 1566 + u32 wptr = desc->wptr; 1567 + u32 used = (wptr + size - rptr) % size; 1568 + 1569 + if (!size || used < size / 2) 1570 + return true; 1571 + 1572 + return false; 1573 + } 1574 + 1575 + bool vpu_malone_is_ready(struct vpu_shared_addr *shared, u32 instance) 1576 + { 1577 + u32 cnt = 0; 1578 + 1579 + while (!vpu_malone_check_ready(shared, instance)) { 1580 + if (cnt > 30) 1581 + return false; 1582 + mdelay(1); 1583 + cnt++; 1584 + } 1585 + return true; 1586 + } 1587 + 1588 + int vpu_malone_pre_cmd(struct vpu_shared_addr *shared, u32 instance) 1589 + { 1590 + if (!vpu_malone_is_ready(shared, instance)) 1591 + return -EINVAL; 1592 + 1593 + return 0; 1594 + } 1595 + 1596 + int vpu_malone_post_cmd(struct vpu_shared_addr *shared, u32 instance) 1597 + { 1598 + struct malone_iface *iface = shared->iface; 1599 + struct vpu_rpc_buffer_desc *desc = &iface->api_cmd_buffer_desc[instance]; 1600 + 1601 + desc->wptr++; 1602 + if (desc->wptr == desc->end) 1603 + desc->wptr = desc->start; 1604 + 1605 + return 0; 1606 + } 1607 + 1608 + int vpu_malone_init_instance(struct vpu_shared_addr *shared, u32 instance) 1609 + { 1610 + struct malone_iface *iface = shared->iface; 1611 + struct vpu_rpc_buffer_desc *desc = &iface->api_cmd_buffer_desc[instance]; 1612 + 1613 + desc->wptr = desc->rptr; 1614 + if (desc->wptr == desc->end) 1615 + desc->wptr = desc->start; 1616 + 1617 + return 0; 1618 + } 1619 + 1620 + u32 vpu_malone_get_max_instance_count(struct vpu_shared_addr *shared) 1621 + { 1622 + struct malone_iface *iface = shared->iface; 1623 + 1624 + return iface->max_streams; 1625 + }
+44
drivers/media/platform/amphion/vpu_malone.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Copyright 2020-2021 NXP 4 + */ 5 + 6 + #ifndef _AMPHION_VPU_MALONE_H 7 + #define _AMPHION_VPU_MALONE_H 8 + 9 + u32 vpu_malone_get_data_size(void); 10 + void vpu_malone_init_rpc(struct vpu_shared_addr *shared, 11 + struct vpu_buffer *rpc, dma_addr_t boot_addr); 12 + void vpu_malone_set_log_buf(struct vpu_shared_addr *shared, 13 + struct vpu_buffer *log); 14 + void vpu_malone_set_system_cfg(struct vpu_shared_addr *shared, 15 + u32 regs_base, void __iomem *regs, u32 core_id); 16 + u32 vpu_malone_get_version(struct vpu_shared_addr *shared); 17 + int vpu_malone_get_stream_buffer_size(struct vpu_shared_addr *shared); 18 + int vpu_malone_config_stream_buffer(struct vpu_shared_addr *shared, 19 + u32 instance, struct vpu_buffer *buf); 20 + int vpu_malone_get_stream_buffer_desc(struct vpu_shared_addr *shared, 21 + u32 instance, 22 + struct vpu_rpc_buffer_desc *desc); 23 + int vpu_malone_update_stream_buffer(struct vpu_shared_addr *shared, 24 + u32 instance, u32 ptr, bool write); 25 + int vpu_malone_set_decode_params(struct vpu_shared_addr *shared, 26 + u32 instance, 27 + struct vpu_decode_params *params, u32 update); 28 + int vpu_malone_pack_cmd(struct vpu_rpc_event *pkt, u32 index, u32 id, void *data); 29 + int vpu_malone_convert_msg_id(u32 msg_id); 30 + int vpu_malone_unpack_msg_data(struct vpu_rpc_event *pkt, void *data); 31 + int vpu_malone_add_scode(struct vpu_shared_addr *shared, 32 + u32 instance, 33 + struct vpu_buffer *stream_buffer, 34 + u32 pixelformat, 35 + u32 scode_type); 36 + int vpu_malone_input_frame(struct vpu_shared_addr *shared, 37 + struct vpu_inst *inst, struct vb2_buffer *vb); 38 + bool vpu_malone_is_ready(struct vpu_shared_addr *shared, u32 instance); 39 + int vpu_malone_pre_cmd(struct vpu_shared_addr *shared, u32 instance); 40 + int vpu_malone_post_cmd(struct vpu_shared_addr *shared, u32 instance); 41 + int vpu_malone_init_instance(struct vpu_shared_addr *shared, u32 instance); 42 + u32 vpu_malone_get_max_instance_count(struct vpu_shared_addr *shared); 43 + 44 + #endif
+118
drivers/media/platform/amphion/vpu_mbox.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright 2020-2021 NXP 4 + */ 5 + 6 + #include <linux/init.h> 7 + #include <linux/interconnect.h> 8 + #include <linux/ioctl.h> 9 + #include <linux/list.h> 10 + #include <linux/kernel.h> 11 + #include <linux/module.h> 12 + #include <linux/of_device.h> 13 + #include <linux/of_address.h> 14 + #include <linux/platform_device.h> 15 + #include "vpu.h" 16 + #include "vpu_mbox.h" 17 + #include "vpu_msgs.h" 18 + 19 + static void vpu_mbox_rx_callback(struct mbox_client *cl, void *msg) 20 + { 21 + struct vpu_mbox *rx = container_of(cl, struct vpu_mbox, cl); 22 + struct vpu_core *core = container_of(rx, struct vpu_core, rx); 23 + 24 + vpu_isr(core, *(u32 *)msg); 25 + } 26 + 27 + static int vpu_mbox_request_channel(struct device *dev, struct vpu_mbox *mbox) 28 + { 29 + struct mbox_chan *ch; 30 + struct mbox_client *cl; 31 + 32 + if (!dev || !mbox) 33 + return -EINVAL; 34 + if (mbox->ch) 35 + return 0; 36 + 37 + cl = &mbox->cl; 38 + cl->dev = dev; 39 + if (mbox->block) { 40 + cl->tx_block = true; 41 + cl->tx_tout = 1000; 42 + } else { 43 + cl->tx_block = false; 44 + } 45 + cl->knows_txdone = false; 46 + cl->rx_callback = vpu_mbox_rx_callback; 47 + 48 + ch = mbox_request_channel_byname(cl, mbox->name); 49 + if (IS_ERR(ch)) { 50 + dev_err(dev, "Failed to request mbox chan %s, ret : %ld\n", 51 + mbox->name, PTR_ERR(ch)); 52 + return PTR_ERR(ch); 53 + } 54 + 55 + mbox->ch = ch; 56 + return 0; 57 + } 58 + 59 + int vpu_mbox_init(struct vpu_core *core) 60 + { 61 + scnprintf(core->tx_type.name, sizeof(core->tx_type.name) - 1, "tx0"); 62 + core->tx_type.block = true; 63 + 64 + scnprintf(core->tx_data.name, sizeof(core->tx_data.name) - 1, "tx1"); 65 + core->tx_data.block = false; 66 + 67 + scnprintf(core->rx.name, sizeof(core->rx.name) - 1, "rx"); 68 + core->rx.block = true; 69 + 70 + return 0; 71 + } 72 + 73 + int vpu_mbox_request(struct vpu_core *core) 74 + { 75 + int ret; 76 + 77 + ret = vpu_mbox_request_channel(core->dev, &core->tx_type); 78 + if (ret) 79 + goto error; 80 + ret = vpu_mbox_request_channel(core->dev, &core->tx_data); 81 + if (ret) 82 + goto error; 83 + ret = vpu_mbox_request_channel(core->dev, &core->rx); 84 + if (ret) 85 + goto error; 86 + 87 + dev_dbg(core->dev, "%s request mbox\n", vpu_core_type_desc(core->type)); 88 + return 0; 89 + error: 90 + vpu_mbox_free(core); 91 + return ret; 92 + } 93 + 94 + void vpu_mbox_free(struct vpu_core *core) 95 + { 96 + mbox_free_channel(core->tx_type.ch); 97 + mbox_free_channel(core->tx_data.ch); 98 + mbox_free_channel(core->rx.ch); 99 + core->tx_type.ch = NULL; 100 + core->tx_data.ch = NULL; 101 + core->rx.ch = NULL; 102 + dev_dbg(core->dev, "%s free mbox\n", vpu_core_type_desc(core->type)); 103 + } 104 + 105 + void vpu_mbox_send_type(struct vpu_core *core, u32 type) 106 + { 107 + mbox_send_message(core->tx_type.ch, &type); 108 + } 109 + 110 + void vpu_mbox_send_msg(struct vpu_core *core, u32 type, u32 data) 111 + { 112 + mbox_send_message(core->tx_data.ch, &data); 113 + mbox_send_message(core->tx_type.ch, &type); 114 + } 115 + 116 + void vpu_mbox_enable_rx(struct vpu_dev *dev) 117 + { 118 + }
+16
drivers/media/platform/amphion/vpu_mbox.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Copyright 2020-2021 NXP 4 + */ 5 + 6 + #ifndef _AMPHION_VPU_MBOX_H 7 + #define _AMPHION_VPU_MBOX_H 8 + 9 + int vpu_mbox_init(struct vpu_core *core); 10 + int vpu_mbox_request(struct vpu_core *core); 11 + void vpu_mbox_free(struct vpu_core *core); 12 + void vpu_mbox_send_msg(struct vpu_core *core, u32 type, u32 data); 13 + void vpu_mbox_send_type(struct vpu_core *core, u32 type); 14 + void vpu_mbox_enable_rx(struct vpu_dev *dev); 15 + 16 + #endif
+385
drivers/media/platform/amphion/vpu_msgs.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright 2020-2021 NXP 4 + */ 5 + 6 + #include <linux/init.h> 7 + #include <linux/interconnect.h> 8 + #include <linux/ioctl.h> 9 + #include <linux/list.h> 10 + #include <linux/kernel.h> 11 + #include <linux/module.h> 12 + #include "vpu.h" 13 + #include "vpu_core.h" 14 + #include "vpu_rpc.h" 15 + #include "vpu_mbox.h" 16 + #include "vpu_defs.h" 17 + #include "vpu_cmds.h" 18 + #include "vpu_msgs.h" 19 + #include "vpu_v4l2.h" 20 + 21 + #define VPU_PKT_HEADER_LENGTH 3 22 + 23 + struct vpu_msg_handler { 24 + u32 id; 25 + void (*done)(struct vpu_inst *inst, struct vpu_rpc_event *pkt); 26 + }; 27 + 28 + static void vpu_session_handle_start_done(struct vpu_inst *inst, struct vpu_rpc_event *pkt) 29 + { 30 + vpu_trace(inst->dev, "[%d]\n", inst->id); 31 + } 32 + 33 + static void vpu_session_handle_mem_request(struct vpu_inst *inst, struct vpu_rpc_event *pkt) 34 + { 35 + struct vpu_pkt_mem_req_data req_data; 36 + 37 + vpu_iface_unpack_msg_data(inst->core, pkt, (void *)&req_data); 38 + vpu_trace(inst->dev, "[%d] %d:%d %d:%d %d:%d\n", 39 + inst->id, 40 + req_data.enc_frame_size, 41 + req_data.enc_frame_num, 42 + req_data.ref_frame_size, 43 + req_data.ref_frame_num, 44 + req_data.act_buf_size, 45 + req_data.act_buf_num); 46 + call_void_vop(inst, mem_request, 47 + req_data.enc_frame_size, 48 + req_data.enc_frame_num, 49 + req_data.ref_frame_size, 50 + req_data.ref_frame_num, 51 + req_data.act_buf_size, 52 + req_data.act_buf_num); 53 + } 54 + 55 + static void vpu_session_handle_stop_done(struct vpu_inst *inst, struct vpu_rpc_event *pkt) 56 + { 57 + vpu_trace(inst->dev, "[%d]\n", inst->id); 58 + 59 + call_void_vop(inst, stop_done); 60 + } 61 + 62 + static void vpu_session_handle_seq_hdr(struct vpu_inst *inst, struct vpu_rpc_event *pkt) 63 + { 64 + struct vpu_dec_codec_info info; 65 + const struct vpu_core_resources *res; 66 + 67 + memset(&info, 0, sizeof(info)); 68 + res = vpu_get_resource(inst); 69 + info.stride = res ? res->stride : 1; 70 + vpu_iface_unpack_msg_data(inst->core, pkt, (void *)&info); 71 + call_void_vop(inst, event_notify, VPU_MSG_ID_SEQ_HDR_FOUND, &info); 72 + } 73 + 74 + static void vpu_session_handle_resolution_change(struct vpu_inst *inst, struct vpu_rpc_event *pkt) 75 + { 76 + call_void_vop(inst, event_notify, VPU_MSG_ID_RES_CHANGE, NULL); 77 + } 78 + 79 + static void vpu_session_handle_enc_frame_done(struct vpu_inst *inst, struct vpu_rpc_event *pkt) 80 + { 81 + struct vpu_enc_pic_info info; 82 + 83 + vpu_iface_unpack_msg_data(inst->core, pkt, (void *)&info); 84 + dev_dbg(inst->dev, "[%d] frame id = %d, wptr = 0x%x, size = %d\n", 85 + inst->id, info.frame_id, info.wptr, info.frame_size); 86 + call_void_vop(inst, get_one_frame, &info); 87 + } 88 + 89 + static void vpu_session_handle_frame_request(struct vpu_inst *inst, struct vpu_rpc_event *pkt) 90 + { 91 + struct vpu_fs_info fs; 92 + 93 + vpu_iface_unpack_msg_data(inst->core, pkt, &fs); 94 + call_void_vop(inst, event_notify, VPU_MSG_ID_FRAME_REQ, &fs); 95 + } 96 + 97 + static void vpu_session_handle_frame_release(struct vpu_inst *inst, struct vpu_rpc_event *pkt) 98 + { 99 + if (inst->core->type == VPU_CORE_TYPE_ENC) { 100 + struct vpu_frame_info info; 101 + 102 + memset(&info, 0, sizeof(info)); 103 + vpu_iface_unpack_msg_data(inst->core, pkt, (void *)&info.sequence); 104 + dev_dbg(inst->dev, "[%d] %d\n", inst->id, info.sequence); 105 + info.type = inst->out_format.type; 106 + call_void_vop(inst, buf_done, &info); 107 + } else if (inst->core->type == VPU_CORE_TYPE_DEC) { 108 + struct vpu_fs_info fs; 109 + 110 + vpu_iface_unpack_msg_data(inst->core, pkt, &fs); 111 + call_void_vop(inst, event_notify, VPU_MSG_ID_FRAME_RELEASE, &fs); 112 + } 113 + } 114 + 115 + static void vpu_session_handle_input_done(struct vpu_inst *inst, struct vpu_rpc_event *pkt) 116 + { 117 + dev_dbg(inst->dev, "[%d]\n", inst->id); 118 + call_void_vop(inst, input_done); 119 + } 120 + 121 + static void vpu_session_handle_pic_decoded(struct vpu_inst *inst, struct vpu_rpc_event *pkt) 122 + { 123 + struct vpu_dec_pic_info info; 124 + 125 + vpu_iface_unpack_msg_data(inst->core, pkt, (void *)&info); 126 + call_void_vop(inst, get_one_frame, &info); 127 + } 128 + 129 + static void vpu_session_handle_pic_done(struct vpu_inst *inst, struct vpu_rpc_event *pkt) 130 + { 131 + struct vpu_dec_pic_info info; 132 + struct vpu_frame_info frame; 133 + 134 + memset(&frame, 0, sizeof(frame)); 135 + vpu_iface_unpack_msg_data(inst->core, pkt, (void *)&info); 136 + if (inst->core->type == VPU_CORE_TYPE_DEC) 137 + frame.type = inst->cap_format.type; 138 + frame.id = info.id; 139 + frame.luma = info.luma; 140 + frame.skipped = info.skipped; 141 + frame.timestamp = info.timestamp; 142 + 143 + call_void_vop(inst, buf_done, &frame); 144 + } 145 + 146 + static void vpu_session_handle_eos(struct vpu_inst *inst, struct vpu_rpc_event *pkt) 147 + { 148 + call_void_vop(inst, event_notify, VPU_MSG_ID_PIC_EOS, NULL); 149 + } 150 + 151 + static void vpu_session_handle_error(struct vpu_inst *inst, struct vpu_rpc_event *pkt) 152 + { 153 + dev_err(inst->dev, "unsupported stream\n"); 154 + call_void_vop(inst, event_notify, VPU_MSG_ID_UNSUPPORTED, NULL); 155 + vpu_v4l2_set_error(inst); 156 + } 157 + 158 + static void vpu_session_handle_firmware_xcpt(struct vpu_inst *inst, struct vpu_rpc_event *pkt) 159 + { 160 + char *str = (char *)pkt->data; 161 + 162 + dev_err(inst->dev, "%s firmware xcpt: %s\n", 163 + vpu_core_type_desc(inst->core->type), str); 164 + call_void_vop(inst, event_notify, VPU_MSG_ID_FIRMWARE_XCPT, NULL); 165 + set_bit(inst->id, &inst->core->hang_mask); 166 + vpu_v4l2_set_error(inst); 167 + } 168 + 169 + static struct vpu_msg_handler handlers[] = { 170 + {VPU_MSG_ID_START_DONE, vpu_session_handle_start_done}, 171 + {VPU_MSG_ID_STOP_DONE, vpu_session_handle_stop_done}, 172 + {VPU_MSG_ID_MEM_REQUEST, vpu_session_handle_mem_request}, 173 + {VPU_MSG_ID_SEQ_HDR_FOUND, vpu_session_handle_seq_hdr}, 174 + {VPU_MSG_ID_RES_CHANGE, vpu_session_handle_resolution_change}, 175 + {VPU_MSG_ID_FRAME_INPUT_DONE, vpu_session_handle_input_done}, 176 + {VPU_MSG_ID_FRAME_REQ, vpu_session_handle_frame_request}, 177 + {VPU_MSG_ID_FRAME_RELEASE, vpu_session_handle_frame_release}, 178 + {VPU_MSG_ID_ENC_DONE, vpu_session_handle_enc_frame_done}, 179 + {VPU_MSG_ID_PIC_DECODED, vpu_session_handle_pic_decoded}, 180 + {VPU_MSG_ID_DEC_DONE, vpu_session_handle_pic_done}, 181 + {VPU_MSG_ID_PIC_EOS, vpu_session_handle_eos}, 182 + {VPU_MSG_ID_UNSUPPORTED, vpu_session_handle_error}, 183 + {VPU_MSG_ID_FIRMWARE_XCPT, vpu_session_handle_firmware_xcpt}, 184 + }; 185 + 186 + static int vpu_session_handle_msg(struct vpu_inst *inst, struct vpu_rpc_event *msg) 187 + { 188 + int ret; 189 + u32 msg_id; 190 + struct vpu_msg_handler *handler = NULL; 191 + unsigned int i; 192 + 193 + ret = vpu_iface_convert_msg_id(inst->core, msg->hdr.id); 194 + if (ret < 0) 195 + return -EINVAL; 196 + 197 + msg_id = ret; 198 + dev_dbg(inst->dev, "[%d] receive event(0x%x)\n", inst->id, msg_id); 199 + 200 + for (i = 0; i < ARRAY_SIZE(handlers); i++) { 201 + if (handlers[i].id == msg_id) { 202 + handler = &handlers[i]; 203 + break; 204 + } 205 + } 206 + 207 + if (handler && handler->done) 208 + handler->done(inst, msg); 209 + 210 + vpu_response_cmd(inst, msg_id, 1); 211 + 212 + return 0; 213 + } 214 + 215 + static bool vpu_inst_receive_msg(struct vpu_inst *inst, struct vpu_rpc_event *pkt) 216 + { 217 + u32 bytes = sizeof(struct vpu_rpc_event_header); 218 + u32 ret; 219 + 220 + memset(pkt, 0, sizeof(*pkt)); 221 + if (kfifo_len(&inst->msg_fifo) < bytes) 222 + return false; 223 + 224 + ret = kfifo_out(&inst->msg_fifo, pkt, bytes); 225 + if (ret != bytes) 226 + return false; 227 + 228 + if (pkt->hdr.num > 0) { 229 + bytes = pkt->hdr.num * sizeof(u32); 230 + ret = kfifo_out(&inst->msg_fifo, pkt->data, bytes); 231 + if (ret != bytes) 232 + return false; 233 + } 234 + 235 + return true; 236 + } 237 + 238 + void vpu_inst_run_work(struct work_struct *work) 239 + { 240 + struct vpu_inst *inst = container_of(work, struct vpu_inst, msg_work); 241 + struct vpu_rpc_event pkt; 242 + 243 + while (vpu_inst_receive_msg(inst, &pkt)) 244 + vpu_session_handle_msg(inst, &pkt); 245 + } 246 + 247 + static void vpu_inst_handle_msg(struct vpu_inst *inst, struct vpu_rpc_event *pkt) 248 + { 249 + u32 bytes; 250 + u32 id = pkt->hdr.id; 251 + int ret; 252 + 253 + if (!inst->workqueue) 254 + return; 255 + 256 + bytes = sizeof(pkt->hdr) + pkt->hdr.num * sizeof(u32); 257 + ret = kfifo_in(&inst->msg_fifo, pkt, bytes); 258 + if (ret != bytes) 259 + dev_err(inst->dev, "[%d:%d]overflow: %d\n", inst->core->id, inst->id, id); 260 + queue_work(inst->workqueue, &inst->msg_work); 261 + } 262 + 263 + static int vpu_handle_msg(struct vpu_core *core) 264 + { 265 + struct vpu_rpc_event pkt; 266 + struct vpu_inst *inst; 267 + int ret; 268 + 269 + memset(&pkt, 0, sizeof(pkt)); 270 + while (!vpu_iface_receive_msg(core, &pkt)) { 271 + dev_dbg(core->dev, "event index = %d, id = %d, num = %d\n", 272 + pkt.hdr.index, pkt.hdr.id, pkt.hdr.num); 273 + 274 + ret = vpu_iface_convert_msg_id(core, pkt.hdr.id); 275 + if (ret < 0) 276 + continue; 277 + 278 + inst = vpu_core_find_instance(core, pkt.hdr.index); 279 + if (inst) { 280 + vpu_response_cmd(inst, ret, 0); 281 + mutex_lock(&core->cmd_lock); 282 + vpu_inst_record_flow(inst, ret); 283 + mutex_unlock(&core->cmd_lock); 284 + 285 + vpu_inst_handle_msg(inst, &pkt); 286 + vpu_inst_put(inst); 287 + } 288 + memset(&pkt, 0, sizeof(pkt)); 289 + } 290 + 291 + return 0; 292 + } 293 + 294 + static int vpu_isr_thread(struct vpu_core *core, u32 irq_code) 295 + { 296 + dev_dbg(core->dev, "irq code = 0x%x\n", irq_code); 297 + switch (irq_code) { 298 + case VPU_IRQ_CODE_SYNC: 299 + vpu_mbox_send_msg(core, PRC_BUF_OFFSET, core->rpc.phys - core->fw.phys); 300 + vpu_mbox_send_msg(core, BOOT_ADDRESS, core->fw.phys); 301 + vpu_mbox_send_msg(core, INIT_DONE, 2); 302 + break; 303 + case VPU_IRQ_CODE_BOOT_DONE: 304 + break; 305 + case VPU_IRQ_CODE_SNAPSHOT_DONE: 306 + break; 307 + default: 308 + vpu_handle_msg(core); 309 + break; 310 + } 311 + 312 + return 0; 313 + } 314 + 315 + static void vpu_core_run_msg_work(struct vpu_core *core) 316 + { 317 + const unsigned int SIZE = sizeof(u32); 318 + 319 + while (kfifo_len(&core->msg_fifo) >= SIZE) { 320 + u32 data = 0; 321 + 322 + if (kfifo_out(&core->msg_fifo, &data, SIZE) == SIZE) 323 + vpu_isr_thread(core, data); 324 + } 325 + } 326 + 327 + void vpu_msg_run_work(struct work_struct *work) 328 + { 329 + struct vpu_core *core = container_of(work, struct vpu_core, msg_work); 330 + unsigned long delay = msecs_to_jiffies(10); 331 + 332 + vpu_core_run_msg_work(core); 333 + queue_delayed_work(core->workqueue, &core->msg_delayed_work, delay); 334 + } 335 + 336 + void vpu_msg_delayed_work(struct work_struct *work) 337 + { 338 + struct vpu_core *core; 339 + struct delayed_work *dwork; 340 + u32 bytes = sizeof(bytes); 341 + u32 i; 342 + 343 + if (!work) 344 + return; 345 + 346 + dwork = to_delayed_work(work); 347 + core = container_of(dwork, struct vpu_core, msg_delayed_work); 348 + if (kfifo_len(&core->msg_fifo) >= bytes) 349 + vpu_core_run_msg_work(core); 350 + 351 + bytes = sizeof(struct vpu_rpc_event_header); 352 + for (i = 0; i < core->supported_instance_count; i++) { 353 + struct vpu_inst *inst = vpu_core_find_instance(core, i); 354 + 355 + if (!inst) 356 + continue; 357 + 358 + if (inst->workqueue && kfifo_len(&inst->msg_fifo) >= bytes) 359 + queue_work(inst->workqueue, &inst->msg_work); 360 + 361 + vpu_inst_put(inst); 362 + } 363 + } 364 + 365 + int vpu_isr(struct vpu_core *core, u32 irq) 366 + { 367 + switch (irq) { 368 + case VPU_IRQ_CODE_SYNC: 369 + break; 370 + case VPU_IRQ_CODE_BOOT_DONE: 371 + complete(&core->cmp); 372 + break; 373 + case VPU_IRQ_CODE_SNAPSHOT_DONE: 374 + complete(&core->cmp); 375 + break; 376 + default: 377 + break; 378 + } 379 + 380 + if (kfifo_in(&core->msg_fifo, &irq, sizeof(irq)) != sizeof(irq)) 381 + dev_err(core->dev, "[%d]overflow: %d\n", core->id, irq); 382 + queue_work(core->workqueue, &core->msg_work); 383 + 384 + return 0; 385 + }
+14
drivers/media/platform/amphion/vpu_msgs.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Copyright 2020-2021 NXP 4 + */ 5 + 6 + #ifndef _AMPHION_VPU_MSGS_H 7 + #define _AMPHION_VPU_MSGS_H 8 + 9 + int vpu_isr(struct vpu_core *core, u32 irq); 10 + void vpu_inst_run_work(struct work_struct *work); 11 + void vpu_msg_run_work(struct work_struct *work); 12 + void vpu_msg_delayed_work(struct work_struct *work); 13 + 14 + #endif
+257
drivers/media/platform/amphion/vpu_rpc.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright 2020-2021 NXP 4 + */ 5 + 6 + #include <linux/init.h> 7 + #include <linux/interconnect.h> 8 + #include <linux/ioctl.h> 9 + #include <linux/list.h> 10 + #include <linux/kernel.h> 11 + #include <linux/module.h> 12 + #include <linux/of_device.h> 13 + #include <linux/of_address.h> 14 + #include <linux/platform_device.h> 15 + #include <linux/firmware/imx/ipc.h> 16 + #include <linux/firmware/imx/svc/misc.h> 17 + #include "vpu.h" 18 + #include "vpu_rpc.h" 19 + #include "vpu_imx8q.h" 20 + #include "vpu_windsor.h" 21 + #include "vpu_malone.h" 22 + 23 + u32 vpu_iface_check_memory_region(struct vpu_core *core, dma_addr_t addr, u32 size) 24 + { 25 + struct vpu_iface_ops *ops = vpu_core_get_iface(core); 26 + 27 + if (!ops || !ops->check_memory_region) 28 + return VPU_CORE_MEMORY_INVALID; 29 + 30 + return ops->check_memory_region(core->fw.phys, addr, size); 31 + } 32 + 33 + static u32 vpu_rpc_check_buffer_space(struct vpu_rpc_buffer_desc *desc, bool write) 34 + { 35 + u32 ptr1; 36 + u32 ptr2; 37 + u32 size; 38 + 39 + size = desc->end - desc->start; 40 + if (write) { 41 + ptr1 = desc->wptr; 42 + ptr2 = desc->rptr; 43 + } else { 44 + ptr1 = desc->rptr; 45 + ptr2 = desc->wptr; 46 + } 47 + 48 + if (ptr1 == ptr2) { 49 + if (!write) 50 + return 0; 51 + else 52 + return size; 53 + } 54 + 55 + return (ptr2 + size - ptr1) % size; 56 + } 57 + 58 + static int vpu_rpc_send_cmd_buf(struct vpu_shared_addr *shared, struct vpu_rpc_event *cmd) 59 + { 60 + struct vpu_rpc_buffer_desc *desc; 61 + u32 space = 0; 62 + u32 *data; 63 + u32 wptr; 64 + u32 i; 65 + 66 + desc = shared->cmd_desc; 67 + space = vpu_rpc_check_buffer_space(desc, true); 68 + if (space < (((cmd->hdr.num + 1) << 2) + 16)) 69 + return -EINVAL; 70 + wptr = desc->wptr; 71 + data = (u32 *)(shared->cmd_mem_vir + desc->wptr - desc->start); 72 + *data = 0; 73 + *data |= ((cmd->hdr.index & 0xff) << 24); 74 + *data |= ((cmd->hdr.num & 0xff) << 16); 75 + *data |= (cmd->hdr.id & 0x3fff); 76 + wptr += 4; 77 + data++; 78 + if (wptr >= desc->end) { 79 + wptr = desc->start; 80 + data = shared->cmd_mem_vir; 81 + } 82 + 83 + for (i = 0; i < cmd->hdr.num; i++) { 84 + *data = cmd->data[i]; 85 + wptr += 4; 86 + data++; 87 + if (wptr >= desc->end) { 88 + wptr = desc->start; 89 + data = shared->cmd_mem_vir; 90 + } 91 + } 92 + 93 + /*update wptr after data is written*/ 94 + mb(); 95 + desc->wptr = wptr; 96 + 97 + return 0; 98 + } 99 + 100 + static bool vpu_rpc_check_msg(struct vpu_shared_addr *shared) 101 + { 102 + struct vpu_rpc_buffer_desc *desc; 103 + u32 space = 0; 104 + u32 msgword; 105 + u32 msgnum; 106 + 107 + desc = shared->msg_desc; 108 + space = vpu_rpc_check_buffer_space(desc, 0); 109 + space = (space >> 2); 110 + 111 + if (space) { 112 + msgword = *(u32 *)(shared->msg_mem_vir + desc->rptr - desc->start); 113 + msgnum = (msgword & 0xff0000) >> 16; 114 + if (msgnum <= space) 115 + return true; 116 + } 117 + 118 + return false; 119 + } 120 + 121 + static int vpu_rpc_receive_msg_buf(struct vpu_shared_addr *shared, struct vpu_rpc_event *msg) 122 + { 123 + struct vpu_rpc_buffer_desc *desc; 124 + u32 *data; 125 + u32 msgword; 126 + u32 rptr; 127 + u32 i; 128 + 129 + if (!vpu_rpc_check_msg(shared)) 130 + return -EINVAL; 131 + 132 + desc = shared->msg_desc; 133 + data = (u32 *)(shared->msg_mem_vir + desc->rptr - desc->start); 134 + rptr = desc->rptr; 135 + msgword = *data; 136 + data++; 137 + rptr += 4; 138 + if (rptr >= desc->end) { 139 + rptr = desc->start; 140 + data = shared->msg_mem_vir; 141 + } 142 + 143 + msg->hdr.index = (msgword >> 24) & 0xff; 144 + msg->hdr.num = (msgword >> 16) & 0xff; 145 + msg->hdr.id = msgword & 0x3fff; 146 + 147 + if (msg->hdr.num > ARRAY_SIZE(msg->data)) 148 + return -EINVAL; 149 + 150 + for (i = 0; i < msg->hdr.num; i++) { 151 + msg->data[i] = *data; 152 + data++; 153 + rptr += 4; 154 + if (rptr >= desc->end) { 155 + rptr = desc->start; 156 + data = shared->msg_mem_vir; 157 + } 158 + } 159 + 160 + /*update rptr after data is read*/ 161 + mb(); 162 + desc->rptr = rptr; 163 + 164 + return 0; 165 + } 166 + 167 + static struct vpu_iface_ops imx8q_rpc_ops[] = { 168 + [VPU_CORE_TYPE_ENC] = { 169 + .check_codec = vpu_imx8q_check_codec, 170 + .check_fmt = vpu_imx8q_check_fmt, 171 + .boot_core = vpu_imx8q_boot_core, 172 + .get_power_state = vpu_imx8q_get_power_state, 173 + .on_firmware_loaded = vpu_imx8q_on_firmware_loaded, 174 + .get_data_size = vpu_windsor_get_data_size, 175 + .check_memory_region = vpu_imx8q_check_memory_region, 176 + .init_rpc = vpu_windsor_init_rpc, 177 + .set_log_buf = vpu_windsor_set_log_buf, 178 + .set_system_cfg = vpu_windsor_set_system_cfg, 179 + .get_version = vpu_windsor_get_version, 180 + .send_cmd_buf = vpu_rpc_send_cmd_buf, 181 + .receive_msg_buf = vpu_rpc_receive_msg_buf, 182 + .pack_cmd = vpu_windsor_pack_cmd, 183 + .convert_msg_id = vpu_windsor_convert_msg_id, 184 + .unpack_msg_data = vpu_windsor_unpack_msg_data, 185 + .config_memory_resource = vpu_windsor_config_memory_resource, 186 + .get_stream_buffer_size = vpu_windsor_get_stream_buffer_size, 187 + .config_stream_buffer = vpu_windsor_config_stream_buffer, 188 + .get_stream_buffer_desc = vpu_windsor_get_stream_buffer_desc, 189 + .update_stream_buffer = vpu_windsor_update_stream_buffer, 190 + .set_encode_params = vpu_windsor_set_encode_params, 191 + .input_frame = vpu_windsor_input_frame, 192 + .get_max_instance_count = vpu_windsor_get_max_instance_count, 193 + }, 194 + [VPU_CORE_TYPE_DEC] = { 195 + .check_codec = vpu_imx8q_check_codec, 196 + .check_fmt = vpu_imx8q_check_fmt, 197 + .boot_core = vpu_imx8q_boot_core, 198 + .get_power_state = vpu_imx8q_get_power_state, 199 + .on_firmware_loaded = vpu_imx8q_on_firmware_loaded, 200 + .get_data_size = vpu_malone_get_data_size, 201 + .check_memory_region = vpu_imx8q_check_memory_region, 202 + .init_rpc = vpu_malone_init_rpc, 203 + .set_log_buf = vpu_malone_set_log_buf, 204 + .set_system_cfg = vpu_malone_set_system_cfg, 205 + .get_version = vpu_malone_get_version, 206 + .send_cmd_buf = vpu_rpc_send_cmd_buf, 207 + .receive_msg_buf = vpu_rpc_receive_msg_buf, 208 + .get_stream_buffer_size = vpu_malone_get_stream_buffer_size, 209 + .config_stream_buffer = vpu_malone_config_stream_buffer, 210 + .set_decode_params = vpu_malone_set_decode_params, 211 + .pack_cmd = vpu_malone_pack_cmd, 212 + .convert_msg_id = vpu_malone_convert_msg_id, 213 + .unpack_msg_data = vpu_malone_unpack_msg_data, 214 + .get_stream_buffer_desc = vpu_malone_get_stream_buffer_desc, 215 + .update_stream_buffer = vpu_malone_update_stream_buffer, 216 + .add_scode = vpu_malone_add_scode, 217 + .input_frame = vpu_malone_input_frame, 218 + .pre_send_cmd = vpu_malone_pre_cmd, 219 + .post_send_cmd = vpu_malone_post_cmd, 220 + .init_instance = vpu_malone_init_instance, 221 + .get_max_instance_count = vpu_malone_get_max_instance_count, 222 + }, 223 + }; 224 + 225 + static struct vpu_iface_ops *vpu_get_iface(struct vpu_dev *vpu, enum vpu_core_type type) 226 + { 227 + struct vpu_iface_ops *rpc_ops = NULL; 228 + u32 size = 0; 229 + 230 + switch (vpu->res->plat_type) { 231 + case IMX8QXP: 232 + case IMX8QM: 233 + rpc_ops = imx8q_rpc_ops; 234 + size = ARRAY_SIZE(imx8q_rpc_ops); 235 + break; 236 + default: 237 + return NULL; 238 + } 239 + 240 + if (type >= size) 241 + return NULL; 242 + 243 + return &rpc_ops[type]; 244 + } 245 + 246 + struct vpu_iface_ops *vpu_core_get_iface(struct vpu_core *core) 247 + { 248 + return vpu_get_iface(core->vpu, core->type); 249 + } 250 + 251 + struct vpu_iface_ops *vpu_inst_get_iface(struct vpu_inst *inst) 252 + { 253 + if (inst->core) 254 + return vpu_core_get_iface(inst->core); 255 + 256 + return vpu_get_iface(inst->vpu, inst->type); 257 + }
+456
drivers/media/platform/amphion/vpu_rpc.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Copyright 2020-2021 NXP 4 + */ 5 + 6 + #ifndef _AMPHION_VPU_RPC_H 7 + #define _AMPHION_VPU_RPC_H 8 + 9 + #include <media/videobuf2-core.h> 10 + #include "vpu_codec.h" 11 + 12 + struct vpu_rpc_buffer_desc { 13 + u32 wptr; 14 + u32 rptr; 15 + u32 start; 16 + u32 end; 17 + }; 18 + 19 + struct vpu_shared_addr { 20 + void *iface; 21 + struct vpu_rpc_buffer_desc *cmd_desc; 22 + void *cmd_mem_vir; 23 + struct vpu_rpc_buffer_desc *msg_desc; 24 + void *msg_mem_vir; 25 + 26 + unsigned long boot_addr; 27 + struct vpu_core *core; 28 + void *priv; 29 + }; 30 + 31 + struct vpu_rpc_event_header { 32 + u32 index; 33 + u32 id; 34 + u32 num; 35 + }; 36 + 37 + struct vpu_rpc_event { 38 + struct vpu_rpc_event_header hdr; 39 + u32 data[128]; 40 + }; 41 + 42 + struct vpu_iface_ops { 43 + bool (*check_codec)(enum vpu_core_type type); 44 + bool (*check_fmt)(enum vpu_core_type type, u32 pixelfmt); 45 + u32 (*get_data_size)(void); 46 + u32 (*check_memory_region)(dma_addr_t base, dma_addr_t addr, u32 size); 47 + int (*boot_core)(struct vpu_core *core); 48 + int (*shutdown_core)(struct vpu_core *core); 49 + int (*restore_core)(struct vpu_core *core); 50 + int (*get_power_state)(struct vpu_core *core); 51 + int (*on_firmware_loaded)(struct vpu_core *core); 52 + void (*init_rpc)(struct vpu_shared_addr *shared, 53 + struct vpu_buffer *rpc, dma_addr_t boot_addr); 54 + void (*set_log_buf)(struct vpu_shared_addr *shared, 55 + struct vpu_buffer *log); 56 + void (*set_system_cfg)(struct vpu_shared_addr *shared, 57 + u32 regs_base, void __iomem *regs, u32 index); 58 + void (*set_stream_cfg)(struct vpu_shared_addr *shared, u32 index); 59 + u32 (*get_version)(struct vpu_shared_addr *shared); 60 + u32 (*get_max_instance_count)(struct vpu_shared_addr *shared); 61 + int (*get_stream_buffer_size)(struct vpu_shared_addr *shared); 62 + int (*send_cmd_buf)(struct vpu_shared_addr *shared, 63 + struct vpu_rpc_event *cmd); 64 + int (*receive_msg_buf)(struct vpu_shared_addr *shared, 65 + struct vpu_rpc_event *msg); 66 + int (*pack_cmd)(struct vpu_rpc_event *pkt, u32 index, u32 id, void *data); 67 + int (*convert_msg_id)(u32 msg_id); 68 + int (*unpack_msg_data)(struct vpu_rpc_event *pkt, void *data); 69 + int (*input_frame)(struct vpu_shared_addr *shared, 70 + struct vpu_inst *inst, struct vb2_buffer *vb); 71 + int (*config_memory_resource)(struct vpu_shared_addr *shared, 72 + u32 instance, 73 + u32 type, 74 + u32 index, 75 + struct vpu_buffer *buf); 76 + int (*config_stream_buffer)(struct vpu_shared_addr *shared, 77 + u32 instance, 78 + struct vpu_buffer *buf); 79 + int (*update_stream_buffer)(struct vpu_shared_addr *shared, 80 + u32 instance, u32 ptr, bool write); 81 + int (*get_stream_buffer_desc)(struct vpu_shared_addr *shared, 82 + u32 instance, 83 + struct vpu_rpc_buffer_desc *desc); 84 + int (*set_encode_params)(struct vpu_shared_addr *shared, 85 + u32 instance, 86 + struct vpu_encode_params *params, 87 + u32 update); 88 + int (*set_decode_params)(struct vpu_shared_addr *shared, 89 + u32 instance, 90 + struct vpu_decode_params *params, 91 + u32 update); 92 + int (*add_scode)(struct vpu_shared_addr *shared, 93 + u32 instance, 94 + struct vpu_buffer *stream_buffer, 95 + u32 pixelformat, 96 + u32 scode_type); 97 + int (*pre_send_cmd)(struct vpu_shared_addr *shared, u32 instance); 98 + int (*post_send_cmd)(struct vpu_shared_addr *shared, u32 instance); 99 + int (*init_instance)(struct vpu_shared_addr *shared, u32 instance); 100 + }; 101 + 102 + enum { 103 + VPU_CORE_MEMORY_INVALID = 0, 104 + VPU_CORE_MEMORY_CACHED, 105 + VPU_CORE_MEMORY_UNCACHED 106 + }; 107 + 108 + struct vpu_rpc_region_t { 109 + dma_addr_t start; 110 + dma_addr_t end; 111 + dma_addr_t type; 112 + }; 113 + 114 + struct vpu_iface_ops *vpu_core_get_iface(struct vpu_core *core); 115 + struct vpu_iface_ops *vpu_inst_get_iface(struct vpu_inst *inst); 116 + u32 vpu_iface_check_memory_region(struct vpu_core *core, dma_addr_t addr, u32 size); 117 + 118 + static inline bool vpu_iface_check_codec(struct vpu_core *core) 119 + { 120 + struct vpu_iface_ops *ops = vpu_core_get_iface(core); 121 + 122 + if (ops && ops->check_codec) 123 + return ops->check_codec(core->type); 124 + 125 + return true; 126 + } 127 + 128 + static inline bool vpu_iface_check_format(struct vpu_inst *inst, u32 pixelfmt) 129 + { 130 + struct vpu_iface_ops *ops = vpu_inst_get_iface(inst); 131 + 132 + if (ops && ops->check_fmt) 133 + return ops->check_fmt(inst->type, pixelfmt); 134 + 135 + return true; 136 + } 137 + 138 + static inline int vpu_iface_boot_core(struct vpu_core *core) 139 + { 140 + struct vpu_iface_ops *ops = vpu_core_get_iface(core); 141 + 142 + if (ops && ops->boot_core) 143 + return ops->boot_core(core); 144 + return 0; 145 + } 146 + 147 + static inline int vpu_iface_get_power_state(struct vpu_core *core) 148 + { 149 + struct vpu_iface_ops *ops = vpu_core_get_iface(core); 150 + 151 + if (ops && ops->get_power_state) 152 + return ops->get_power_state(core); 153 + return 1; 154 + } 155 + 156 + static inline int vpu_iface_shutdown_core(struct vpu_core *core) 157 + { 158 + struct vpu_iface_ops *ops = vpu_core_get_iface(core); 159 + 160 + if (ops && ops->shutdown_core) 161 + return ops->shutdown_core(core); 162 + return 0; 163 + } 164 + 165 + static inline int vpu_iface_restore_core(struct vpu_core *core) 166 + { 167 + struct vpu_iface_ops *ops = vpu_core_get_iface(core); 168 + 169 + if (ops && ops->restore_core) 170 + return ops->restore_core(core); 171 + return 0; 172 + } 173 + 174 + static inline int vpu_iface_on_firmware_loaded(struct vpu_core *core) 175 + { 176 + struct vpu_iface_ops *ops = vpu_core_get_iface(core); 177 + 178 + if (ops && ops->on_firmware_loaded) 179 + return ops->on_firmware_loaded(core); 180 + 181 + return 0; 182 + } 183 + 184 + static inline u32 vpu_iface_get_data_size(struct vpu_core *core) 185 + { 186 + struct vpu_iface_ops *ops = vpu_core_get_iface(core); 187 + 188 + if (!ops || !ops->get_data_size) 189 + return 0; 190 + 191 + return ops->get_data_size(); 192 + } 193 + 194 + static inline int vpu_iface_init(struct vpu_core *core, 195 + struct vpu_shared_addr *shared, 196 + struct vpu_buffer *rpc, 197 + dma_addr_t boot_addr) 198 + { 199 + struct vpu_iface_ops *ops = vpu_core_get_iface(core); 200 + 201 + if (!ops || !ops->init_rpc) 202 + return -EINVAL; 203 + 204 + ops->init_rpc(shared, rpc, boot_addr); 205 + core->iface = shared; 206 + shared->core = core; 207 + if (rpc->bytesused > rpc->length) 208 + return -ENOSPC; 209 + return 0; 210 + } 211 + 212 + static inline int vpu_iface_set_log_buf(struct vpu_core *core, 213 + struct vpu_buffer *log) 214 + { 215 + struct vpu_iface_ops *ops = vpu_core_get_iface(core); 216 + 217 + if (!ops) 218 + return -EINVAL; 219 + 220 + if (ops->set_log_buf) 221 + ops->set_log_buf(core->iface, log); 222 + 223 + return 0; 224 + } 225 + 226 + static inline int vpu_iface_config_system(struct vpu_core *core, u32 regs_base, void __iomem *regs) 227 + { 228 + struct vpu_iface_ops *ops = vpu_core_get_iface(core); 229 + 230 + if (!ops) 231 + return -EINVAL; 232 + if (ops->set_system_cfg) 233 + ops->set_system_cfg(core->iface, regs_base, regs, core->id); 234 + 235 + return 0; 236 + } 237 + 238 + static inline int vpu_iface_get_stream_buffer_size(struct vpu_core *core) 239 + { 240 + struct vpu_iface_ops *ops = vpu_core_get_iface(core); 241 + 242 + if (!ops || !ops->get_stream_buffer_size) 243 + return 0; 244 + 245 + return ops->get_stream_buffer_size(core->iface); 246 + } 247 + 248 + static inline int vpu_iface_config_stream(struct vpu_inst *inst) 249 + { 250 + struct vpu_iface_ops *ops = vpu_core_get_iface(inst->core); 251 + 252 + if (!ops || inst->id < 0) 253 + return -EINVAL; 254 + if (ops->set_stream_cfg) 255 + ops->set_stream_cfg(inst->core->iface, inst->id); 256 + return 0; 257 + } 258 + 259 + static inline int vpu_iface_send_cmd(struct vpu_core *core, struct vpu_rpc_event *cmd) 260 + { 261 + struct vpu_iface_ops *ops = vpu_core_get_iface(core); 262 + 263 + if (!ops || !ops->send_cmd_buf) 264 + return -EINVAL; 265 + 266 + return ops->send_cmd_buf(core->iface, cmd); 267 + } 268 + 269 + static inline int vpu_iface_receive_msg(struct vpu_core *core, struct vpu_rpc_event *msg) 270 + { 271 + struct vpu_iface_ops *ops = vpu_core_get_iface(core); 272 + 273 + if (!ops || !ops->receive_msg_buf) 274 + return -EINVAL; 275 + 276 + return ops->receive_msg_buf(core->iface, msg); 277 + } 278 + 279 + static inline int vpu_iface_pack_cmd(struct vpu_core *core, 280 + struct vpu_rpc_event *pkt, 281 + u32 index, u32 id, void *data) 282 + { 283 + struct vpu_iface_ops *ops = vpu_core_get_iface(core); 284 + 285 + if (!ops || !ops->pack_cmd) 286 + return -EINVAL; 287 + return ops->pack_cmd(pkt, index, id, data); 288 + } 289 + 290 + static inline int vpu_iface_convert_msg_id(struct vpu_core *core, u32 msg_id) 291 + { 292 + struct vpu_iface_ops *ops = vpu_core_get_iface(core); 293 + 294 + if (!ops || !ops->convert_msg_id) 295 + return -EINVAL; 296 + 297 + return ops->convert_msg_id(msg_id); 298 + } 299 + 300 + static inline int vpu_iface_unpack_msg_data(struct vpu_core *core, 301 + struct vpu_rpc_event *pkt, void *data) 302 + { 303 + struct vpu_iface_ops *ops = vpu_core_get_iface(core); 304 + 305 + if (!ops || !ops->unpack_msg_data) 306 + return -EINVAL; 307 + 308 + return ops->unpack_msg_data(pkt, data); 309 + } 310 + 311 + static inline int vpu_iface_input_frame(struct vpu_inst *inst, 312 + struct vb2_buffer *vb) 313 + { 314 + struct vpu_iface_ops *ops = vpu_core_get_iface(inst->core); 315 + 316 + if (!ops || !ops->input_frame) 317 + return -EINVAL; 318 + 319 + return ops->input_frame(inst->core->iface, inst, vb); 320 + } 321 + 322 + static inline int vpu_iface_config_memory_resource(struct vpu_inst *inst, 323 + u32 type, 324 + u32 index, 325 + struct vpu_buffer *buf) 326 + { 327 + struct vpu_iface_ops *ops = vpu_core_get_iface(inst->core); 328 + 329 + if (!ops || !ops->config_memory_resource || inst->id < 0) 330 + return -EINVAL; 331 + 332 + return ops->config_memory_resource(inst->core->iface, 333 + inst->id, 334 + type, index, buf); 335 + } 336 + 337 + static inline int vpu_iface_config_stream_buffer(struct vpu_inst *inst, 338 + struct vpu_buffer *buf) 339 + { 340 + struct vpu_iface_ops *ops = vpu_core_get_iface(inst->core); 341 + 342 + if (!ops || !ops->config_stream_buffer || inst->id < 0) 343 + return -EINVAL; 344 + 345 + return ops->config_stream_buffer(inst->core->iface, inst->id, buf); 346 + } 347 + 348 + static inline int vpu_iface_update_stream_buffer(struct vpu_inst *inst, 349 + u32 ptr, bool write) 350 + { 351 + struct vpu_iface_ops *ops = vpu_core_get_iface(inst->core); 352 + 353 + if (!ops || !ops->update_stream_buffer || inst->id < 0) 354 + return -EINVAL; 355 + 356 + return ops->update_stream_buffer(inst->core->iface, inst->id, ptr, write); 357 + } 358 + 359 + static inline int vpu_iface_get_stream_buffer_desc(struct vpu_inst *inst, 360 + struct vpu_rpc_buffer_desc *desc) 361 + { 362 + struct vpu_iface_ops *ops = vpu_core_get_iface(inst->core); 363 + 364 + if (!ops || !ops->get_stream_buffer_desc || inst->id < 0) 365 + return -EINVAL; 366 + 367 + if (!desc) 368 + return 0; 369 + 370 + return ops->get_stream_buffer_desc(inst->core->iface, inst->id, desc); 371 + } 372 + 373 + static inline u32 vpu_iface_get_version(struct vpu_core *core) 374 + { 375 + struct vpu_iface_ops *ops = vpu_core_get_iface(core); 376 + 377 + if (!ops || !ops->get_version) 378 + return 0; 379 + 380 + return ops->get_version(core->iface); 381 + } 382 + 383 + static inline u32 vpu_iface_get_max_instance_count(struct vpu_core *core) 384 + { 385 + struct vpu_iface_ops *ops = vpu_core_get_iface(core); 386 + 387 + if (!ops || !ops->get_max_instance_count) 388 + return 0; 389 + 390 + return ops->get_max_instance_count(core->iface); 391 + } 392 + 393 + static inline int vpu_iface_set_encode_params(struct vpu_inst *inst, 394 + struct vpu_encode_params *params, u32 update) 395 + { 396 + struct vpu_iface_ops *ops = vpu_core_get_iface(inst->core); 397 + 398 + if (!ops || !ops->set_encode_params || inst->id < 0) 399 + return -EINVAL; 400 + 401 + return ops->set_encode_params(inst->core->iface, inst->id, params, update); 402 + } 403 + 404 + static inline int vpu_iface_set_decode_params(struct vpu_inst *inst, 405 + struct vpu_decode_params *params, u32 update) 406 + { 407 + struct vpu_iface_ops *ops = vpu_core_get_iface(inst->core); 408 + 409 + if (!ops || !ops->set_decode_params || inst->id < 0) 410 + return -EINVAL; 411 + 412 + return ops->set_decode_params(inst->core->iface, inst->id, params, update); 413 + } 414 + 415 + static inline int vpu_iface_add_scode(struct vpu_inst *inst, u32 scode_type) 416 + { 417 + struct vpu_iface_ops *ops = vpu_core_get_iface(inst->core); 418 + 419 + if (!ops || !ops->add_scode || inst->id < 0) 420 + return -EINVAL; 421 + 422 + return ops->add_scode(inst->core->iface, inst->id, 423 + &inst->stream_buffer, 424 + inst->out_format.pixfmt, 425 + scode_type); 426 + } 427 + 428 + static inline int vpu_iface_pre_send_cmd(struct vpu_inst *inst) 429 + { 430 + struct vpu_iface_ops *ops = vpu_core_get_iface(inst->core); 431 + 432 + if (ops && ops->pre_send_cmd && inst->id >= 0) 433 + return ops->pre_send_cmd(inst->core->iface, inst->id); 434 + return 0; 435 + } 436 + 437 + static inline int vpu_iface_post_send_cmd(struct vpu_inst *inst) 438 + { 439 + struct vpu_iface_ops *ops = vpu_core_get_iface(inst->core); 440 + 441 + if (ops && ops->post_send_cmd && inst->id >= 0) 442 + return ops->post_send_cmd(inst->core->iface, inst->id); 443 + return 0; 444 + } 445 + 446 + static inline int vpu_iface_init_instance(struct vpu_inst *inst) 447 + { 448 + struct vpu_iface_ops *ops = vpu_core_get_iface(inst->core); 449 + 450 + if (ops && ops->init_instance && inst->id >= 0) 451 + return ops->init_instance(inst->core->iface, inst->id); 452 + 453 + return 0; 454 + } 455 + 456 + #endif
+712
drivers/media/platform/amphion/vpu_v4l2.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright 2020-2021 NXP 4 + */ 5 + 6 + #include <linux/init.h> 7 + #include <linux/interconnect.h> 8 + #include <linux/ioctl.h> 9 + #include <linux/list.h> 10 + #include <linux/kernel.h> 11 + #include <linux/module.h> 12 + #include <linux/pm_runtime.h> 13 + #include <linux/videodev2.h> 14 + #include <media/v4l2-device.h> 15 + #include <media/v4l2-event.h> 16 + #include <media/v4l2-mem2mem.h> 17 + #include <media/v4l2-ioctl.h> 18 + #include <media/videobuf2-v4l2.h> 19 + #include <media/videobuf2-dma-contig.h> 20 + #include <media/videobuf2-vmalloc.h> 21 + #include "vpu.h" 22 + #include "vpu_core.h" 23 + #include "vpu_v4l2.h" 24 + #include "vpu_msgs.h" 25 + #include "vpu_helpers.h" 26 + 27 + void vpu_inst_lock(struct vpu_inst *inst) 28 + { 29 + mutex_lock(&inst->lock); 30 + } 31 + 32 + void vpu_inst_unlock(struct vpu_inst *inst) 33 + { 34 + mutex_unlock(&inst->lock); 35 + } 36 + 37 + dma_addr_t vpu_get_vb_phy_addr(struct vb2_buffer *vb, u32 plane_no) 38 + { 39 + if (plane_no >= vb->num_planes) 40 + return 0; 41 + return vb2_dma_contig_plane_dma_addr(vb, plane_no) + 42 + vb->planes[plane_no].data_offset; 43 + } 44 + 45 + unsigned int vpu_get_vb_length(struct vb2_buffer *vb, u32 plane_no) 46 + { 47 + if (plane_no >= vb->num_planes) 48 + return 0; 49 + return vb2_plane_size(vb, plane_no) - vb->planes[plane_no].data_offset; 50 + } 51 + 52 + void vpu_set_buffer_state(struct vb2_v4l2_buffer *vbuf, unsigned int state) 53 + { 54 + struct vpu_vb2_buffer *vpu_buf = to_vpu_vb2_buffer(vbuf); 55 + 56 + vpu_buf->state = state; 57 + } 58 + 59 + unsigned int vpu_get_buffer_state(struct vb2_v4l2_buffer *vbuf) 60 + { 61 + struct vpu_vb2_buffer *vpu_buf = to_vpu_vb2_buffer(vbuf); 62 + 63 + return vpu_buf->state; 64 + } 65 + 66 + void vpu_v4l2_set_error(struct vpu_inst *inst) 67 + { 68 + struct vb2_queue *src_q; 69 + struct vb2_queue *dst_q; 70 + 71 + vpu_inst_lock(inst); 72 + dev_err(inst->dev, "some error occurs in codec\n"); 73 + if (inst->fh.m2m_ctx) { 74 + src_q = v4l2_m2m_get_src_vq(inst->fh.m2m_ctx); 75 + dst_q = v4l2_m2m_get_dst_vq(inst->fh.m2m_ctx); 76 + if (src_q) 77 + src_q->error = 1; 78 + if (dst_q) 79 + dst_q->error = 1; 80 + } 81 + vpu_inst_unlock(inst); 82 + } 83 + 84 + int vpu_notify_eos(struct vpu_inst *inst) 85 + { 86 + static const struct v4l2_event ev = { 87 + .id = 0, 88 + .type = V4L2_EVENT_EOS 89 + }; 90 + 91 + vpu_trace(inst->dev, "[%d]\n", inst->id); 92 + v4l2_event_queue_fh(&inst->fh, &ev); 93 + 94 + return 0; 95 + } 96 + 97 + int vpu_notify_source_change(struct vpu_inst *inst) 98 + { 99 + static const struct v4l2_event ev = { 100 + .id = 0, 101 + .type = V4L2_EVENT_SOURCE_CHANGE, 102 + .u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION 103 + }; 104 + 105 + vpu_trace(inst->dev, "[%d]\n", inst->id); 106 + v4l2_event_queue_fh(&inst->fh, &ev); 107 + return 0; 108 + } 109 + 110 + int vpu_set_last_buffer_dequeued(struct vpu_inst *inst) 111 + { 112 + struct vb2_queue *q; 113 + 114 + if (!inst || !inst->fh.m2m_ctx) 115 + return -EINVAL; 116 + 117 + q = v4l2_m2m_get_dst_vq(inst->fh.m2m_ctx); 118 + if (!list_empty(&q->done_list)) 119 + return -EINVAL; 120 + 121 + if (q->last_buffer_dequeued) 122 + return 0; 123 + vpu_trace(inst->dev, "last buffer dequeued\n"); 124 + q->last_buffer_dequeued = true; 125 + wake_up(&q->done_wq); 126 + vpu_notify_eos(inst); 127 + return 0; 128 + } 129 + 130 + const struct vpu_format *vpu_try_fmt_common(struct vpu_inst *inst, struct v4l2_format *f) 131 + { 132 + struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp; 133 + u32 type = f->type; 134 + u32 stride = 1; 135 + u32 bytesperline; 136 + u32 sizeimage; 137 + const struct vpu_format *fmt; 138 + const struct vpu_core_resources *res; 139 + int i; 140 + 141 + fmt = vpu_helper_find_format(inst, type, pixmp->pixelformat); 142 + if (!fmt) { 143 + fmt = vpu_helper_enum_format(inst, type, 0); 144 + if (!fmt) 145 + return NULL; 146 + pixmp->pixelformat = fmt->pixfmt; 147 + } 148 + 149 + res = vpu_get_resource(inst); 150 + if (res) 151 + stride = res->stride; 152 + if (pixmp->width) 153 + pixmp->width = vpu_helper_valid_frame_width(inst, pixmp->width); 154 + if (pixmp->height) 155 + pixmp->height = vpu_helper_valid_frame_height(inst, pixmp->height); 156 + pixmp->flags = fmt->flags; 157 + pixmp->num_planes = fmt->num_planes; 158 + if (pixmp->field == V4L2_FIELD_ANY) 159 + pixmp->field = V4L2_FIELD_NONE; 160 + for (i = 0; i < pixmp->num_planes; i++) { 161 + bytesperline = max_t(s32, pixmp->plane_fmt[i].bytesperline, 0); 162 + sizeimage = vpu_helper_get_plane_size(pixmp->pixelformat, 163 + pixmp->width, 164 + pixmp->height, 165 + i, 166 + stride, 167 + pixmp->field > V4L2_FIELD_NONE ? 1 : 0, 168 + &bytesperline); 169 + sizeimage = max_t(s32, pixmp->plane_fmt[i].sizeimage, sizeimage); 170 + pixmp->plane_fmt[i].bytesperline = bytesperline; 171 + pixmp->plane_fmt[i].sizeimage = sizeimage; 172 + } 173 + 174 + return fmt; 175 + } 176 + 177 + static bool vpu_check_ready(struct vpu_inst *inst, u32 type) 178 + { 179 + if (!inst) 180 + return false; 181 + if (inst->state == VPU_CODEC_STATE_DEINIT || inst->id < 0) 182 + return false; 183 + if (!inst->ops->check_ready) 184 + return true; 185 + return call_vop(inst, check_ready, type); 186 + } 187 + 188 + int vpu_process_output_buffer(struct vpu_inst *inst) 189 + { 190 + struct v4l2_m2m_buffer *buf = NULL; 191 + struct vb2_v4l2_buffer *vbuf = NULL; 192 + 193 + if (!inst || !inst->fh.m2m_ctx) 194 + return -EINVAL; 195 + 196 + if (!vpu_check_ready(inst, inst->out_format.type)) 197 + return -EINVAL; 198 + 199 + v4l2_m2m_for_each_src_buf(inst->fh.m2m_ctx, buf) { 200 + vbuf = &buf->vb; 201 + if (vpu_get_buffer_state(vbuf) == VPU_BUF_STATE_IDLE) 202 + break; 203 + vbuf = NULL; 204 + } 205 + 206 + if (!vbuf) 207 + return -EINVAL; 208 + 209 + dev_dbg(inst->dev, "[%d]frame id = %d / %d\n", 210 + inst->id, vbuf->sequence, inst->sequence); 211 + return call_vop(inst, process_output, &vbuf->vb2_buf); 212 + } 213 + 214 + int vpu_process_capture_buffer(struct vpu_inst *inst) 215 + { 216 + struct v4l2_m2m_buffer *buf = NULL; 217 + struct vb2_v4l2_buffer *vbuf = NULL; 218 + 219 + if (!inst || !inst->fh.m2m_ctx) 220 + return -EINVAL; 221 + 222 + if (!vpu_check_ready(inst, inst->cap_format.type)) 223 + return -EINVAL; 224 + 225 + v4l2_m2m_for_each_dst_buf(inst->fh.m2m_ctx, buf) { 226 + vbuf = &buf->vb; 227 + if (vpu_get_buffer_state(vbuf) == VPU_BUF_STATE_IDLE) 228 + break; 229 + vbuf = NULL; 230 + } 231 + if (!vbuf) 232 + return -EINVAL; 233 + 234 + return call_vop(inst, process_capture, &vbuf->vb2_buf); 235 + } 236 + 237 + struct vb2_v4l2_buffer *vpu_find_buf_by_sequence(struct vpu_inst *inst, u32 type, u32 sequence) 238 + { 239 + struct v4l2_m2m_buffer *buf = NULL; 240 + struct vb2_v4l2_buffer *vbuf = NULL; 241 + 242 + if (!inst || !inst->fh.m2m_ctx) 243 + return NULL; 244 + 245 + if (V4L2_TYPE_IS_OUTPUT(type)) { 246 + v4l2_m2m_for_each_src_buf(inst->fh.m2m_ctx, buf) { 247 + vbuf = &buf->vb; 248 + if (vbuf->sequence == sequence) 249 + break; 250 + vbuf = NULL; 251 + } 252 + } else { 253 + v4l2_m2m_for_each_dst_buf(inst->fh.m2m_ctx, buf) { 254 + vbuf = &buf->vb; 255 + if (vbuf->sequence == sequence) 256 + break; 257 + vbuf = NULL; 258 + } 259 + } 260 + 261 + return vbuf; 262 + } 263 + 264 + struct vb2_v4l2_buffer *vpu_find_buf_by_idx(struct vpu_inst *inst, u32 type, u32 idx) 265 + { 266 + struct v4l2_m2m_buffer *buf = NULL; 267 + struct vb2_v4l2_buffer *vbuf = NULL; 268 + 269 + if (!inst || !inst->fh.m2m_ctx) 270 + return NULL; 271 + 272 + if (V4L2_TYPE_IS_OUTPUT(type)) { 273 + v4l2_m2m_for_each_src_buf(inst->fh.m2m_ctx, buf) { 274 + vbuf = &buf->vb; 275 + if (vbuf->vb2_buf.index == idx) 276 + break; 277 + vbuf = NULL; 278 + } 279 + } else { 280 + v4l2_m2m_for_each_dst_buf(inst->fh.m2m_ctx, buf) { 281 + vbuf = &buf->vb; 282 + if (vbuf->vb2_buf.index == idx) 283 + break; 284 + vbuf = NULL; 285 + } 286 + } 287 + 288 + return vbuf; 289 + } 290 + 291 + int vpu_get_num_buffers(struct vpu_inst *inst, u32 type) 292 + { 293 + struct vb2_queue *q; 294 + 295 + if (!inst || !inst->fh.m2m_ctx) 296 + return -EINVAL; 297 + 298 + if (V4L2_TYPE_IS_OUTPUT(type)) 299 + q = v4l2_m2m_get_src_vq(inst->fh.m2m_ctx); 300 + else 301 + q = v4l2_m2m_get_dst_vq(inst->fh.m2m_ctx); 302 + 303 + return q->num_buffers; 304 + } 305 + 306 + static void vpu_m2m_device_run(void *priv) 307 + { 308 + } 309 + 310 + static void vpu_m2m_job_abort(void *priv) 311 + { 312 + struct vpu_inst *inst = priv; 313 + struct v4l2_m2m_ctx *m2m_ctx = inst->fh.m2m_ctx; 314 + 315 + v4l2_m2m_job_finish(m2m_ctx->m2m_dev, m2m_ctx); 316 + } 317 + 318 + static const struct v4l2_m2m_ops vpu_m2m_ops = { 319 + .device_run = vpu_m2m_device_run, 320 + .job_abort = vpu_m2m_job_abort 321 + }; 322 + 323 + static int vpu_vb2_queue_setup(struct vb2_queue *vq, 324 + unsigned int *buf_count, 325 + unsigned int *plane_count, 326 + unsigned int psize[], 327 + struct device *allocators[]) 328 + { 329 + struct vpu_inst *inst = vb2_get_drv_priv(vq); 330 + struct vpu_format *cur_fmt; 331 + int i; 332 + 333 + cur_fmt = vpu_get_format(inst, vq->type); 334 + 335 + if (*plane_count) { 336 + if (*plane_count != cur_fmt->num_planes) 337 + return -EINVAL; 338 + for (i = 0; i < cur_fmt->num_planes; i++) { 339 + if (psize[i] < cur_fmt->sizeimage[i]) 340 + return -EINVAL; 341 + } 342 + return 0; 343 + } 344 + 345 + *plane_count = cur_fmt->num_planes; 346 + for (i = 0; i < cur_fmt->num_planes; i++) 347 + psize[i] = cur_fmt->sizeimage[i]; 348 + 349 + return 0; 350 + } 351 + 352 + static int vpu_vb2_buf_init(struct vb2_buffer *vb) 353 + { 354 + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 355 + 356 + vpu_set_buffer_state(vbuf, VPU_BUF_STATE_IDLE); 357 + return 0; 358 + } 359 + 360 + static int vpu_vb2_buf_out_validate(struct vb2_buffer *vb) 361 + { 362 + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 363 + 364 + vbuf->field = V4L2_FIELD_NONE; 365 + 366 + return 0; 367 + } 368 + 369 + static int vpu_vb2_buf_prepare(struct vb2_buffer *vb) 370 + { 371 + struct vpu_inst *inst = vb2_get_drv_priv(vb->vb2_queue); 372 + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 373 + struct vpu_format *cur_fmt; 374 + u32 i; 375 + 376 + cur_fmt = vpu_get_format(inst, vb->type); 377 + for (i = 0; i < cur_fmt->num_planes; i++) { 378 + if (vpu_get_vb_length(vb, i) < cur_fmt->sizeimage[i]) { 379 + dev_dbg(inst->dev, "[%d] %s buf[%d] is invalid\n", 380 + inst->id, vpu_type_name(vb->type), vb->index); 381 + vpu_set_buffer_state(vbuf, VPU_BUF_STATE_ERROR); 382 + } 383 + } 384 + 385 + return 0; 386 + } 387 + 388 + static void vpu_vb2_buf_finish(struct vb2_buffer *vb) 389 + { 390 + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 391 + struct vpu_inst *inst = vb2_get_drv_priv(vb->vb2_queue); 392 + struct vb2_queue *q = vb->vb2_queue; 393 + 394 + if (vbuf->flags & V4L2_BUF_FLAG_LAST) 395 + vpu_notify_eos(inst); 396 + 397 + if (list_empty(&q->done_list)) 398 + call_void_vop(inst, on_queue_empty, q->type); 399 + } 400 + 401 + void vpu_vb2_buffers_return(struct vpu_inst *inst, unsigned int type, enum vb2_buffer_state state) 402 + { 403 + struct vb2_v4l2_buffer *buf; 404 + 405 + if (V4L2_TYPE_IS_OUTPUT(type)) { 406 + while ((buf = v4l2_m2m_src_buf_remove(inst->fh.m2m_ctx))) 407 + v4l2_m2m_buf_done(buf, state); 408 + } else { 409 + while ((buf = v4l2_m2m_dst_buf_remove(inst->fh.m2m_ctx))) 410 + v4l2_m2m_buf_done(buf, state); 411 + } 412 + } 413 + 414 + static int vpu_vb2_start_streaming(struct vb2_queue *q, unsigned int count) 415 + { 416 + struct vpu_inst *inst = vb2_get_drv_priv(q); 417 + struct vpu_format *fmt = vpu_get_format(inst, q->type); 418 + int ret; 419 + 420 + vpu_inst_unlock(inst); 421 + ret = vpu_inst_register(inst); 422 + vpu_inst_lock(inst); 423 + if (ret) { 424 + vpu_vb2_buffers_return(inst, q->type, VB2_BUF_STATE_QUEUED); 425 + return ret; 426 + } 427 + 428 + vpu_trace(inst->dev, "[%d] %s %c%c%c%c %dx%d %u(%u) %u(%u) %u(%u) %d\n", 429 + inst->id, vpu_type_name(q->type), 430 + fmt->pixfmt, 431 + fmt->pixfmt >> 8, 432 + fmt->pixfmt >> 16, 433 + fmt->pixfmt >> 24, 434 + fmt->width, fmt->height, 435 + fmt->sizeimage[0], fmt->bytesperline[0], 436 + fmt->sizeimage[1], fmt->bytesperline[1], 437 + fmt->sizeimage[2], fmt->bytesperline[2], 438 + q->num_buffers); 439 + call_void_vop(inst, start, q->type); 440 + vb2_clear_last_buffer_dequeued(q); 441 + 442 + return 0; 443 + } 444 + 445 + static void vpu_vb2_stop_streaming(struct vb2_queue *q) 446 + { 447 + struct vpu_inst *inst = vb2_get_drv_priv(q); 448 + 449 + vpu_trace(inst->dev, "[%d] %s\n", inst->id, vpu_type_name(q->type)); 450 + 451 + call_void_vop(inst, stop, q->type); 452 + vpu_vb2_buffers_return(inst, q->type, VB2_BUF_STATE_ERROR); 453 + if (V4L2_TYPE_IS_OUTPUT(q->type)) 454 + inst->sequence = 0; 455 + } 456 + 457 + static void vpu_vb2_buf_queue(struct vb2_buffer *vb) 458 + { 459 + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 460 + struct vpu_inst *inst = vb2_get_drv_priv(vb->vb2_queue); 461 + 462 + if (V4L2_TYPE_IS_OUTPUT(vb->type)) { 463 + vbuf->sequence = inst->sequence++; 464 + if ((s64)vb->timestamp < 0) 465 + vb->timestamp = VPU_INVALID_TIMESTAMP; 466 + } 467 + 468 + v4l2_m2m_buf_queue(inst->fh.m2m_ctx, vbuf); 469 + vpu_process_output_buffer(inst); 470 + vpu_process_capture_buffer(inst); 471 + } 472 + 473 + static const struct vb2_ops vpu_vb2_ops = { 474 + .queue_setup = vpu_vb2_queue_setup, 475 + .buf_init = vpu_vb2_buf_init, 476 + .buf_out_validate = vpu_vb2_buf_out_validate, 477 + .buf_prepare = vpu_vb2_buf_prepare, 478 + .buf_finish = vpu_vb2_buf_finish, 479 + .start_streaming = vpu_vb2_start_streaming, 480 + .stop_streaming = vpu_vb2_stop_streaming, 481 + .buf_queue = vpu_vb2_buf_queue, 482 + .wait_prepare = vb2_ops_wait_prepare, 483 + .wait_finish = vb2_ops_wait_finish, 484 + }; 485 + 486 + static int vpu_m2m_queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq) 487 + { 488 + struct vpu_inst *inst = priv; 489 + int ret; 490 + 491 + src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 492 + inst->out_format.type = src_vq->type; 493 + src_vq->io_modes = VB2_MMAP | VB2_DMABUF; 494 + src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; 495 + src_vq->ops = &vpu_vb2_ops; 496 + src_vq->mem_ops = &vb2_dma_contig_memops; 497 + if (inst->type == VPU_CORE_TYPE_DEC && inst->use_stream_buffer) 498 + src_vq->mem_ops = &vb2_vmalloc_memops; 499 + src_vq->drv_priv = inst; 500 + src_vq->buf_struct_size = sizeof(struct vpu_vb2_buffer); 501 + src_vq->min_buffers_needed = 1; 502 + src_vq->dev = inst->vpu->dev; 503 + src_vq->lock = &inst->lock; 504 + ret = vb2_queue_init(src_vq); 505 + if (ret) 506 + return ret; 507 + 508 + dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 509 + inst->cap_format.type = dst_vq->type; 510 + dst_vq->io_modes = VB2_MMAP | VB2_DMABUF; 511 + dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; 512 + dst_vq->ops = &vpu_vb2_ops; 513 + dst_vq->mem_ops = &vb2_dma_contig_memops; 514 + if (inst->type == VPU_CORE_TYPE_ENC && inst->use_stream_buffer) 515 + dst_vq->mem_ops = &vb2_vmalloc_memops; 516 + dst_vq->drv_priv = inst; 517 + dst_vq->buf_struct_size = sizeof(struct vpu_vb2_buffer); 518 + dst_vq->min_buffers_needed = 1; 519 + dst_vq->dev = inst->vpu->dev; 520 + dst_vq->lock = &inst->lock; 521 + ret = vb2_queue_init(dst_vq); 522 + if (ret) { 523 + vb2_queue_release(src_vq); 524 + return ret; 525 + } 526 + 527 + return 0; 528 + } 529 + 530 + static int vpu_v4l2_release(struct vpu_inst *inst) 531 + { 532 + vpu_trace(inst->vpu->dev, "%p\n", inst); 533 + 534 + vpu_release_core(inst->core); 535 + put_device(inst->dev); 536 + 537 + if (inst->workqueue) { 538 + cancel_work_sync(&inst->msg_work); 539 + destroy_workqueue(inst->workqueue); 540 + inst->workqueue = NULL; 541 + } 542 + 543 + v4l2_ctrl_handler_free(&inst->ctrl_handler); 544 + mutex_destroy(&inst->lock); 545 + v4l2_fh_del(&inst->fh); 546 + v4l2_fh_exit(&inst->fh); 547 + 548 + call_void_vop(inst, cleanup); 549 + 550 + return 0; 551 + } 552 + 553 + int vpu_v4l2_open(struct file *file, struct vpu_inst *inst) 554 + { 555 + struct vpu_dev *vpu = video_drvdata(file); 556 + struct vpu_func *func; 557 + int ret = 0; 558 + 559 + if (!inst || !inst->ops) 560 + return -EINVAL; 561 + 562 + if (inst->type == VPU_CORE_TYPE_ENC) 563 + func = &vpu->encoder; 564 + else 565 + func = &vpu->decoder; 566 + 567 + atomic_set(&inst->ref_count, 0); 568 + vpu_inst_get(inst); 569 + inst->vpu = vpu; 570 + inst->core = vpu_request_core(vpu, inst->type); 571 + if (inst->core) 572 + inst->dev = get_device(inst->core->dev); 573 + mutex_init(&inst->lock); 574 + INIT_LIST_HEAD(&inst->cmd_q); 575 + inst->id = VPU_INST_NULL_ID; 576 + inst->release = vpu_v4l2_release; 577 + inst->pid = current->pid; 578 + inst->tgid = current->tgid; 579 + inst->min_buffer_cap = 2; 580 + inst->min_buffer_out = 2; 581 + v4l2_fh_init(&inst->fh, func->vfd); 582 + v4l2_fh_add(&inst->fh); 583 + 584 + ret = call_vop(inst, ctrl_init); 585 + if (ret) 586 + goto error; 587 + 588 + inst->fh.m2m_ctx = v4l2_m2m_ctx_init(func->m2m_dev, inst, vpu_m2m_queue_init); 589 + if (IS_ERR(inst->fh.m2m_ctx)) { 590 + dev_err(vpu->dev, "v4l2_m2m_ctx_init fail\n"); 591 + ret = PTR_ERR(inst->fh.m2m_ctx); 592 + goto error; 593 + } 594 + 595 + inst->fh.ctrl_handler = &inst->ctrl_handler; 596 + file->private_data = &inst->fh; 597 + inst->state = VPU_CODEC_STATE_DEINIT; 598 + inst->workqueue = alloc_workqueue("vpu_inst", WQ_UNBOUND | WQ_MEM_RECLAIM, 1); 599 + if (inst->workqueue) { 600 + INIT_WORK(&inst->msg_work, vpu_inst_run_work); 601 + ret = kfifo_init(&inst->msg_fifo, 602 + inst->msg_buffer, 603 + rounddown_pow_of_two(sizeof(inst->msg_buffer))); 604 + if (ret) { 605 + destroy_workqueue(inst->workqueue); 606 + inst->workqueue = NULL; 607 + } 608 + } 609 + vpu_trace(vpu->dev, "tgid = %d, pid = %d, type = %s, inst = %p\n", 610 + inst->tgid, inst->pid, vpu_core_type_desc(inst->type), inst); 611 + 612 + return 0; 613 + error: 614 + vpu_inst_put(inst); 615 + return ret; 616 + } 617 + 618 + int vpu_v4l2_close(struct file *file) 619 + { 620 + struct vpu_dev *vpu = video_drvdata(file); 621 + struct vpu_inst *inst = to_inst(file); 622 + 623 + vpu_trace(vpu->dev, "tgid = %d, pid = %d, inst = %p\n", inst->tgid, inst->pid, inst); 624 + 625 + vpu_inst_lock(inst); 626 + if (inst->fh.m2m_ctx) { 627 + v4l2_m2m_ctx_release(inst->fh.m2m_ctx); 628 + inst->fh.m2m_ctx = NULL; 629 + } 630 + vpu_inst_unlock(inst); 631 + 632 + call_void_vop(inst, release); 633 + vpu_inst_unregister(inst); 634 + vpu_inst_put(inst); 635 + 636 + return 0; 637 + } 638 + 639 + int vpu_add_func(struct vpu_dev *vpu, struct vpu_func *func) 640 + { 641 + struct video_device *vfd; 642 + int ret; 643 + 644 + if (!vpu || !func) 645 + return -EINVAL; 646 + 647 + if (func->vfd) 648 + return 0; 649 + 650 + func->m2m_dev = v4l2_m2m_init(&vpu_m2m_ops); 651 + if (IS_ERR(func->m2m_dev)) { 652 + dev_err(vpu->dev, "v4l2_m2m_init fail\n"); 653 + func->vfd = NULL; 654 + return PTR_ERR(func->m2m_dev); 655 + } 656 + 657 + vfd = video_device_alloc(); 658 + if (!vfd) { 659 + v4l2_m2m_release(func->m2m_dev); 660 + dev_err(vpu->dev, "alloc vpu decoder video device fail\n"); 661 + return -ENOMEM; 662 + } 663 + vfd->release = video_device_release; 664 + vfd->vfl_dir = VFL_DIR_M2M; 665 + vfd->v4l2_dev = &vpu->v4l2_dev; 666 + vfd->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING; 667 + if (func->type == VPU_CORE_TYPE_ENC) { 668 + strscpy(vfd->name, "amphion-vpu-encoder", sizeof(vfd->name)); 669 + vfd->fops = venc_get_fops(); 670 + vfd->ioctl_ops = venc_get_ioctl_ops(); 671 + } else { 672 + strscpy(vfd->name, "amphion-vpu-decoder", sizeof(vfd->name)); 673 + vfd->fops = vdec_get_fops(); 674 + vfd->ioctl_ops = vdec_get_ioctl_ops(); 675 + } 676 + 677 + ret = video_register_device(vfd, VFL_TYPE_VIDEO, -1); 678 + if (ret) { 679 + video_device_release(vfd); 680 + v4l2_m2m_release(func->m2m_dev); 681 + return ret; 682 + } 683 + video_set_drvdata(vfd, vpu); 684 + func->vfd = vfd; 685 + 686 + ret = v4l2_m2m_register_media_controller(func->m2m_dev, func->vfd, func->function); 687 + if (ret) { 688 + v4l2_m2m_release(func->m2m_dev); 689 + func->m2m_dev = NULL; 690 + video_unregister_device(func->vfd); 691 + func->vfd = NULL; 692 + return ret; 693 + } 694 + 695 + return 0; 696 + } 697 + 698 + void vpu_remove_func(struct vpu_func *func) 699 + { 700 + if (!func) 701 + return; 702 + 703 + if (func->m2m_dev) { 704 + v4l2_m2m_unregister_media_controller(func->m2m_dev); 705 + v4l2_m2m_release(func->m2m_dev); 706 + func->m2m_dev = NULL; 707 + } 708 + if (func->vfd) { 709 + video_unregister_device(func->vfd); 710 + func->vfd = NULL; 711 + } 712 + }
+55
drivers/media/platform/amphion/vpu_v4l2.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Copyright 2020-2021 NXP 4 + */ 5 + 6 + #ifndef _AMPHION_VPU_V4L2_H 7 + #define _AMPHION_VPU_V4L2_H 8 + 9 + #include <linux/videodev2.h> 10 + 11 + void vpu_inst_lock(struct vpu_inst *inst); 12 + void vpu_inst_unlock(struct vpu_inst *inst); 13 + void vpu_set_buffer_state(struct vb2_v4l2_buffer *vbuf, unsigned int state); 14 + unsigned int vpu_get_buffer_state(struct vb2_v4l2_buffer *vbuf); 15 + 16 + int vpu_v4l2_open(struct file *file, struct vpu_inst *inst); 17 + int vpu_v4l2_close(struct file *file); 18 + 19 + const struct vpu_format *vpu_try_fmt_common(struct vpu_inst *inst, struct v4l2_format *f); 20 + int vpu_process_output_buffer(struct vpu_inst *inst); 21 + int vpu_process_capture_buffer(struct vpu_inst *inst); 22 + struct vb2_v4l2_buffer *vpu_find_buf_by_sequence(struct vpu_inst *inst, u32 type, u32 sequence); 23 + struct vb2_v4l2_buffer *vpu_find_buf_by_idx(struct vpu_inst *inst, u32 type, u32 idx); 24 + void vpu_v4l2_set_error(struct vpu_inst *inst); 25 + int vpu_notify_eos(struct vpu_inst *inst); 26 + int vpu_notify_source_change(struct vpu_inst *inst); 27 + int vpu_set_last_buffer_dequeued(struct vpu_inst *inst); 28 + void vpu_vb2_buffers_return(struct vpu_inst *inst, unsigned int type, enum vb2_buffer_state state); 29 + int vpu_get_num_buffers(struct vpu_inst *inst, u32 type); 30 + 31 + dma_addr_t vpu_get_vb_phy_addr(struct vb2_buffer *vb, u32 plane_no); 32 + unsigned int vpu_get_vb_length(struct vb2_buffer *vb, u32 plane_no); 33 + static inline struct vpu_format *vpu_get_format(struct vpu_inst *inst, u32 type) 34 + { 35 + if (V4L2_TYPE_IS_OUTPUT(type)) 36 + return &inst->out_format; 37 + else 38 + return &inst->cap_format; 39 + } 40 + 41 + static inline char *vpu_type_name(u32 type) 42 + { 43 + return V4L2_TYPE_IS_OUTPUT(type) ? "output" : "capture"; 44 + } 45 + 46 + static inline int vpu_vb_is_codecconfig(struct vb2_v4l2_buffer *vbuf) 47 + { 48 + #ifdef V4L2_BUF_FLAG_CODECCONFIG 49 + return (vbuf->flags & V4L2_BUF_FLAG_CODECCONFIG) ? 1 : 0; 50 + #else 51 + return 0; 52 + #endif 53 + } 54 + 55 + #endif
+1169
drivers/media/platform/amphion/vpu_windsor.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright 2020-2021 NXP 4 + */ 5 + 6 + #include <linux/init.h> 7 + #include <linux/interconnect.h> 8 + #include <linux/ioctl.h> 9 + #include <linux/list.h> 10 + #include <linux/kernel.h> 11 + #include <linux/module.h> 12 + #include <linux/of_device.h> 13 + #include <linux/of_address.h> 14 + #include <linux/platform_device.h> 15 + #include <media/videobuf2-v4l2.h> 16 + #include <media/videobuf2-dma-contig.h> 17 + #include "vpu.h" 18 + #include "vpu_rpc.h" 19 + #include "vpu_defs.h" 20 + #include "vpu_helpers.h" 21 + #include "vpu_cmds.h" 22 + #include "vpu_v4l2.h" 23 + #include "vpu_imx8q.h" 24 + #include "vpu_windsor.h" 25 + 26 + #define CMD_SIZE 2560 27 + #define MSG_SIZE 25600 28 + #define WINDSOR_USER_DATA_WORDS 16 29 + #define WINDSOR_MAX_SRC_FRAMES 0x6 30 + #define WINDSOR_MAX_REF_FRAMES 0x3 31 + #define WINDSOR_BITRATE_UNIT 1024 32 + #define WINDSOR_H264_EXTENDED_SAR 255 33 + 34 + enum { 35 + GTB_ENC_CMD_NOOP = 0x0, 36 + GTB_ENC_CMD_STREAM_START, 37 + GTB_ENC_CMD_FRAME_ENCODE, 38 + GTB_ENC_CMD_FRAME_SKIP, 39 + GTB_ENC_CMD_STREAM_STOP, 40 + GTB_ENC_CMD_PARAMETER_UPD, 41 + GTB_ENC_CMD_TERMINATE, 42 + GTB_ENC_CMD_SNAPSHOT, 43 + GTB_ENC_CMD_ROLL_SNAPSHOT, 44 + GTB_ENC_CMD_LOCK_SCHEDULER, 45 + GTB_ENC_CMD_UNLOCK_SCHEDULER, 46 + GTB_ENC_CMD_CONFIGURE_CODEC, 47 + GTB_ENC_CMD_DEAD_MARK, 48 + GTB_ENC_CMD_FIRM_RESET, 49 + GTB_ENC_CMD_FW_STATUS, 50 + GTB_ENC_CMD_RESERVED 51 + }; 52 + 53 + enum { 54 + VID_API_EVENT_UNDEFINED = 0x0, 55 + VID_API_ENC_EVENT_RESET_DONE = 0x1, 56 + VID_API_ENC_EVENT_START_DONE, 57 + VID_API_ENC_EVENT_STOP_DONE, 58 + VID_API_ENC_EVENT_TERMINATE_DONE, 59 + VID_API_ENC_EVENT_FRAME_INPUT_DONE, 60 + VID_API_ENC_EVENT_FRAME_DONE, 61 + VID_API_ENC_EVENT_FRAME_RELEASE, 62 + VID_API_ENC_EVENT_PARA_UPD_DONE, 63 + VID_API_ENC_EVENT_MEM_REQUEST, 64 + VID_API_ENC_EVENT_FIRMWARE_XCPT, 65 + VID_API_ENC_EVENT_RESERVED 66 + }; 67 + 68 + enum { 69 + MEDIAIP_ENC_PIC_TYPE_B_FRAME = 0, 70 + MEDIAIP_ENC_PIC_TYPE_P_FRAME, 71 + MEDIAIP_ENC_PIC_TYPE_I_FRAME, 72 + MEDIAIP_ENC_PIC_TYPE_IDR_FRAME, 73 + MEDIAIP_ENC_PIC_TYPE_BI_FRAME 74 + }; 75 + 76 + struct windsor_iface { 77 + u32 exec_base_addr; 78 + u32 exec_area_size; 79 + struct vpu_rpc_buffer_desc cmd_buffer_desc; 80 + struct vpu_rpc_buffer_desc msg_buffer_desc; 81 + u32 cmd_int_enable[VID_API_NUM_STREAMS]; 82 + u32 fw_version; 83 + u32 mvd_fw_offset; 84 + u32 max_streams; 85 + u32 ctrl_iface[VID_API_NUM_STREAMS]; 86 + struct vpu_rpc_system_config system_config; 87 + u32 api_version; 88 + struct vpu_rpc_buffer_desc log_buffer_desc; 89 + }; 90 + 91 + struct windsor_ctrl_iface { 92 + u32 enc_yuv_buffer_desc; 93 + u32 enc_stream_buffer_desc; 94 + u32 enc_expert_mode_param; 95 + u32 enc_param; 96 + u32 enc_mem_pool; 97 + u32 enc_encoding_status; 98 + u32 enc_dsa_status; 99 + }; 100 + 101 + struct vpu_enc_yuv_desc { 102 + u32 frame_id; 103 + u32 luma_base; 104 + u32 chroma_base; 105 + u32 param_idx; 106 + u32 key_frame; 107 + }; 108 + 109 + struct vpu_enc_calib_params { 110 + u32 use_ame; 111 + 112 + u32 cme_mvx_max; 113 + u32 cme_mvy_max; 114 + u32 ame_prefresh_y0; 115 + u32 ame_prefresh_y1; 116 + u32 fme_min_sad; 117 + u32 cme_min_sad; 118 + 119 + u32 fme_pred_int_weight; 120 + u32 fme_pred_hp_weight; 121 + u32 fme_pred_qp_weight; 122 + u32 fme_cost_weight; 123 + u32 fme_act_thold; 124 + u32 fme_sad_thold; 125 + u32 fme_zero_sad_thold; 126 + 127 + u32 fme_lrg_mvx_lmt; 128 + u32 fme_lrg_mvy_lmt; 129 + u32 fme_force_mode; 130 + u32 fme_force4mvcost; 131 + u32 fme_force2mvcost; 132 + 133 + u32 h264_inter_thrd; 134 + 135 + u32 i16x16_mode_cost; 136 + u32 i4x4_mode_lambda; 137 + u32 i8x8_mode_lambda; 138 + 139 + u32 inter_mod_mult; 140 + u32 inter_sel_mult; 141 + u32 inter_bid_cost; 142 + u32 inter_bwd_cost; 143 + u32 inter_4mv_cost; 144 + s32 one_mv_i16_cost; 145 + s32 one_mv_i4x4_cost; 146 + s32 one_mv_i8x8_cost; 147 + s32 two_mv_i16_cost; 148 + s32 two_mv_i4x4_cost; 149 + s32 two_mv_i8x8_cost; 150 + s32 four_mv_i16_cost; 151 + s32 four_mv_i4x4_cost; 152 + s32 four_mv_i8x8_cost; 153 + 154 + u32 intra_pred_enab; 155 + u32 intra_chr_pred; 156 + u32 intra16_pred; 157 + u32 intra4x4_pred; 158 + u32 intra8x8_pred; 159 + 160 + u32 cb_base; 161 + u32 cb_size; 162 + u32 cb_head_room; 163 + 164 + u32 mem_page_width; 165 + u32 mem_page_height; 166 + u32 mem_total_size; 167 + u32 mem_chunk_phys_addr; 168 + u32 mem_chunk_virt_addr; 169 + u32 mem_chunk_size; 170 + u32 mem_y_stride; 171 + u32 mem_uv_stride; 172 + 173 + u32 split_wr_enab; 174 + u32 split_wr_req_size; 175 + u32 split_rd_enab; 176 + u32 split_rd_req_size; 177 + }; 178 + 179 + struct vpu_enc_config_params { 180 + u32 param_change; 181 + u32 start_frame; 182 + u32 end_frame; 183 + u32 userdata_enable; 184 + u32 userdata_id[4]; 185 + u32 userdata_message[WINDSOR_USER_DATA_WORDS]; 186 + u32 userdata_length; 187 + u32 h264_profile_idc; 188 + u32 h264_level_idc; 189 + u32 h264_au_delimiter; 190 + u32 h264_seq_end_code; 191 + u32 h264_recovery_points; 192 + u32 h264_vui_parameters; 193 + u32 h264_aspect_ratio_present; 194 + u32 h264_aspect_ratio_sar_width; 195 + u32 h264_aspect_ratio_sar_height; 196 + u32 h264_overscan_present; 197 + u32 h264_video_type_present; 198 + u32 h264_video_format; 199 + u32 h264_video_full_range; 200 + u32 h264_video_colour_descriptor; 201 + u32 h264_video_colour_primaries; 202 + u32 h264_video_transfer_char; 203 + u32 h264_video_matrix_coeff; 204 + u32 h264_chroma_loc_info_present; 205 + u32 h264_chroma_loc_type_top; 206 + u32 h264_chroma_loc_type_bot; 207 + u32 h264_timing_info_present; 208 + u32 h264_buffering_period_present; 209 + u32 h264_low_delay_hrd_flag; 210 + u32 aspect_ratio; 211 + u32 test_mode; // Automated firmware test mode 212 + u32 dsa_test_mode; // Automated test mode for the DSA. 213 + u32 fme_test_mode; // Automated test mode for the fme 214 + u32 cbr_row_mode; //0: FW mode; 1: HW mode 215 + u32 windsor_mode; //0: normal mode; 1: intra only mode; 2: intra+0MV mode 216 + u32 encode_mode; // H264, VC1, MPEG2, DIVX 217 + u32 frame_width; // display width 218 + u32 frame_height; // display height 219 + u32 enc_frame_width; // encoding width, should be 16-pix align 220 + u32 enc_frame_height; // encoding height, should be 16-pix aligned 221 + u32 frame_rate_num; 222 + u32 frame_rate_den; 223 + u32 vi_field_source; 224 + u32 vi_frame_width; 225 + u32 vi_frame_height; 226 + u32 crop_frame_width; 227 + u32 crop_frame_height; 228 + u32 crop_x_start_posn; 229 + u32 crop_y_start_posn; 230 + u32 mode422; 231 + u32 mode_yuy2; 232 + u32 dsa_luma_en; 233 + u32 dsa_chroma_en; 234 + u32 dsa_ext_hfilt_en; 235 + u32 dsa_di_en; 236 + u32 dsa_di_top_ref; 237 + u32 dsa_vertf_disable; 238 + u32 dsa_disable_pwb; 239 + u32 dsa_hor_phase; 240 + u32 dsa_ver_phase; 241 + u32 dsa_iac_enable; 242 + u32 iac_sc_threshold; 243 + u32 iac_vm_threshold; 244 + u32 iac_skip_mode; 245 + u32 iac_grp_width; 246 + u32 iac_grp_height; 247 + u32 rate_control_mode; 248 + u32 rate_control_resolution; 249 + u32 buffer_size; 250 + u32 buffer_level_init; 251 + u32 buffer_I_bit_budget; 252 + u32 top_field_first; 253 + u32 intra_lum_qoffset; 254 + u32 intra_chr_qoffset; 255 + u32 inter_lum_qoffset; 256 + u32 inter_chr_qoffset; 257 + u32 use_def_scaling_mtx; 258 + u32 inter_8x8_enab; 259 + u32 inter_4x4_enab; 260 + u32 fme_enable_qpel; 261 + u32 fme_enable_hpel; 262 + u32 fme_nozeromv; 263 + u32 fme_predmv_en; 264 + u32 fme_pred_2mv4mv; 265 + u32 fme_smallsadthresh; 266 + u32 ame_en_lmvc; 267 + u32 ame_x_mult; 268 + u32 cme_enable_4mv; 269 + u32 cme_enable_1mv; 270 + u32 hme_enable_16x8mv; 271 + u32 hme_enable_8x16mv; 272 + u32 cme_mv_weight; 273 + u32 cme_mv_cost; 274 + u32 ame_mult_mv; 275 + u32 ame_shift_mv; 276 + u32 hme_forceto1mv_en; 277 + u32 hme_2mv_cost; 278 + u32 hme_pred_mode; 279 + u32 hme_sc_rnge; 280 + u32 hme_sw_rnge; 281 + u32 output_format; 282 + u32 timestamp_enab; 283 + u32 initial_pts_enab; 284 + u32 initial_pts; 285 + }; 286 + 287 + struct vpu_enc_static_params { 288 + u32 param_change; 289 + u32 gop_length; 290 + u32 rate_control_bitrate; 291 + u32 rate_control_bitrate_min; 292 + u32 rate_control_bitrate_max; 293 + u32 rate_control_content_models; 294 + u32 rate_control_iframe_maxsize; 295 + u32 rate_control_qp_init; 296 + u32 rate_control_islice_qp; 297 + u32 rate_control_pslice_qp; 298 + u32 rate_control_bslice_qp; 299 + u32 adaptive_quantization; 300 + u32 aq_variance; 301 + u32 cost_optimization; 302 + u32 fdlp_mode; 303 + u32 enable_isegbframes; 304 + u32 enable_adaptive_keyratio; 305 + u32 keyratio_imin; 306 + u32 keyratio_imax; 307 + u32 keyratio_pmin; 308 + u32 keyratio_pmax; 309 + u32 keyratio_bmin; 310 + u32 keyratio_bmax; 311 + s32 keyratio_istep; 312 + s32 keyratio_pstep; 313 + s32 keyratio_bstep; 314 + u32 enable_paff; 315 + u32 enable_b_frame_ref; 316 + u32 enable_adaptive_gop; 317 + u32 enable_closed_gop; 318 + u32 open_gop_refresh_freq; 319 + u32 enable_adaptive_sc; 320 + u32 enable_fade_detection; 321 + s32 fade_detection_threshold; 322 + u32 enable_repeat_b; 323 + u32 enable_low_delay_b; 324 + }; 325 + 326 + struct vpu_enc_dynamic_params { 327 + u32 param_change; 328 + u32 rows_per_slice; 329 + u32 mbaff_enable; 330 + u32 dbf_enable; 331 + u32 field_source; 332 + u32 gop_b_length; 333 + u32 mb_group_size; 334 + u32 cbr_rows_per_group; 335 + u32 skip_enable; 336 + u32 pts_bits_0_to_31; 337 + u32 pts_bit_32; 338 + u32 rm_expsv_cff; 339 + u32 const_ipred; 340 + s32 chr_qp_offset; 341 + u32 intra_mb_qp_offset; 342 + u32 h264_cabac_init_method; 343 + u32 h264_cabac_init_idc; 344 + u32 h264_cabac_enable; 345 + s32 alpha_c0_offset_div2; 346 + s32 beta_offset_div2; 347 + u32 intra_prefresh_y0; 348 + u32 intra_prefresh_y1; 349 + u32 dbg_dump_rec_src; 350 + }; 351 + 352 + struct vpu_enc_expert_mode_param { 353 + struct vpu_enc_calib_params calib_param; 354 + struct vpu_enc_config_params config_param; 355 + struct vpu_enc_static_params static_param; 356 + struct vpu_enc_dynamic_params dynamic_param; 357 + }; 358 + 359 + enum MEDIAIP_ENC_FMT { 360 + MEDIAIP_ENC_FMT_H264 = 0, 361 + MEDIAIP_ENC_FMT_VC1, 362 + MEDIAIP_ENC_FMT_MPEG2, 363 + MEDIAIP_ENC_FMT_MPEG4SP, 364 + MEDIAIP_ENC_FMT_H263, 365 + MEDIAIP_ENC_FMT_MPEG1, 366 + MEDIAIP_ENC_FMT_SHORT_HEADER, 367 + MEDIAIP_ENC_FMT_NULL 368 + }; 369 + 370 + enum MEDIAIP_ENC_PROFILE { 371 + MEDIAIP_ENC_PROF_MPEG2_SP = 0, 372 + MEDIAIP_ENC_PROF_MPEG2_MP, 373 + MEDIAIP_ENC_PROF_MPEG2_HP, 374 + MEDIAIP_ENC_PROF_H264_BP, 375 + MEDIAIP_ENC_PROF_H264_MP, 376 + MEDIAIP_ENC_PROF_H264_HP, 377 + MEDIAIP_ENC_PROF_MPEG4_SP, 378 + MEDIAIP_ENC_PROF_MPEG4_ASP, 379 + MEDIAIP_ENC_PROF_VC1_SP, 380 + MEDIAIP_ENC_PROF_VC1_MP, 381 + MEDIAIP_ENC_PROF_VC1_AP 382 + }; 383 + 384 + enum MEDIAIP_ENC_BITRATE_MODE { 385 + MEDIAIP_ENC_BITRATE_MODE_VBR = 0x00000001, 386 + MEDIAIP_ENC_BITRATE_MODE_CBR = 0x00000002, 387 + MEDIAIP_ENC_BITRATE_MODE_CONSTANT_QP = 0x00000004 388 + }; 389 + 390 + struct vpu_enc_memory_resource { 391 + u32 phys; 392 + u32 virt; 393 + u32 size; 394 + }; 395 + 396 + struct vpu_enc_param { 397 + enum MEDIAIP_ENC_FMT codec_mode; 398 + enum MEDIAIP_ENC_PROFILE profile; 399 + u32 level; 400 + 401 + struct vpu_enc_memory_resource enc_mem_desc; 402 + 403 + u32 frame_rate; 404 + u32 src_stride; 405 + u32 src_width; 406 + u32 src_height; 407 + u32 src_offset_x; 408 + u32 src_offset_y; 409 + u32 src_crop_width; 410 + u32 src_crop_height; 411 + u32 out_width; 412 + u32 out_height; 413 + u32 iframe_interval; 414 + u32 bframes; 415 + u32 low_latency_mode; 416 + 417 + enum MEDIAIP_ENC_BITRATE_MODE bitrate_mode; 418 + u32 target_bitrate; 419 + u32 max_bitrate; 420 + u32 min_bitrate; 421 + u32 init_slice_qp; 422 + }; 423 + 424 + struct vpu_enc_mem_pool { 425 + struct vpu_enc_memory_resource enc_frames[WINDSOR_MAX_SRC_FRAMES]; 426 + struct vpu_enc_memory_resource ref_frames[WINDSOR_MAX_REF_FRAMES]; 427 + struct vpu_enc_memory_resource act_frame; 428 + }; 429 + 430 + struct vpu_enc_encoding_status { 431 + u32 frame_id; 432 + u32 error_flag; //Error type 433 + u32 mb_y; 434 + u32 mb_x; 435 + u32 reserved[12]; 436 + 437 + }; 438 + 439 + struct vpu_enc_dsa_status { 440 + u32 frame_id; 441 + u32 dsa_cyle; 442 + u32 mb_y; 443 + u32 mb_x; 444 + u32 reserved[4]; 445 + }; 446 + 447 + struct vpu_enc_ctrl { 448 + struct vpu_enc_yuv_desc *yuv_desc; 449 + struct vpu_rpc_buffer_desc *stream_desc; 450 + struct vpu_enc_expert_mode_param *expert; 451 + struct vpu_enc_param *param; 452 + struct vpu_enc_mem_pool *pool; 453 + struct vpu_enc_encoding_status *status; 454 + struct vpu_enc_dsa_status *dsa; 455 + }; 456 + 457 + struct vpu_enc_host_ctrls { 458 + struct vpu_enc_ctrl ctrls[VID_API_NUM_STREAMS]; 459 + }; 460 + 461 + struct windsor_pic_info { 462 + u32 frame_id; 463 + u32 pic_encod_done; 464 + u32 pic_type; 465 + u32 skipped_frame; 466 + u32 error_flag; 467 + u32 psnr; 468 + u32 flush_done; 469 + u32 mb_y; 470 + u32 mb_x; 471 + u32 frame_size; 472 + u32 frame_enc_ttl_cycles; 473 + u32 frame_enc_ttl_frm_cycles; 474 + u32 frame_enc_ttl_slc_cycles; 475 + u32 frame_enc_ttl_enc_cycles; 476 + u32 frame_enc_ttl_hme_cycles; 477 + u32 frame_enc_ttl_dsa_cycles; 478 + u32 frame_enc_fw_cycles; 479 + u32 frame_crc; 480 + u32 num_interrupts_1; 481 + u32 num_interrupts_2; 482 + u32 poc; 483 + u32 ref_info; 484 + u32 pic_num; 485 + u32 pic_activity; 486 + u32 scene_change; 487 + u32 mb_stats; 488 + u32 enc_cache_count0; 489 + u32 enc_cache_count1; 490 + u32 mtl_wr_strb_cnt; 491 + u32 mtl_rd_strb_cnt; 492 + u32 str_buff_wptr; 493 + u32 diagnosticEvents; 494 + u32 proc_iacc_tot_rd_cnt; 495 + u32 proc_dacc_tot_rd_cnt; 496 + u32 proc_dacc_tot_wr_cnt; 497 + u32 proc_dacc_reg_rd_cnt; 498 + u32 proc_dacc_reg_wr_cnt; 499 + u32 proc_dacc_rng_rd_cnt; 500 + u32 proc_dacc_rng_wr_cnt; 501 + s32 tv_s; 502 + u32 tv_ns; 503 + }; 504 + 505 + u32 vpu_windsor_get_data_size(void) 506 + { 507 + return sizeof(struct vpu_enc_host_ctrls); 508 + } 509 + 510 + static struct vpu_enc_yuv_desc *get_yuv_desc(struct vpu_shared_addr *shared, 511 + u32 instance) 512 + { 513 + struct vpu_enc_host_ctrls *hcs = shared->priv; 514 + 515 + return hcs->ctrls[instance].yuv_desc; 516 + } 517 + 518 + static struct vpu_enc_mem_pool *get_mem_pool(struct vpu_shared_addr *shared, 519 + u32 instance) 520 + { 521 + struct vpu_enc_host_ctrls *hcs = shared->priv; 522 + 523 + return hcs->ctrls[instance].pool; 524 + } 525 + 526 + static struct vpu_rpc_buffer_desc *get_stream_buf_desc(struct vpu_shared_addr *shared, 527 + u32 instance) 528 + { 529 + struct vpu_enc_host_ctrls *hcs = shared->priv; 530 + 531 + return hcs->ctrls[instance].stream_desc; 532 + } 533 + 534 + static struct vpu_enc_expert_mode_param *get_expert_param(struct vpu_shared_addr *shared, 535 + u32 instance) 536 + { 537 + struct vpu_enc_host_ctrls *hcs = shared->priv; 538 + 539 + return hcs->ctrls[instance].expert; 540 + } 541 + 542 + static struct vpu_enc_param *get_enc_param(struct vpu_shared_addr *shared, u32 instance) 543 + { 544 + struct vpu_enc_host_ctrls *hcs = shared->priv; 545 + 546 + return hcs->ctrls[instance].param; 547 + } 548 + 549 + static u32 get_ptr(u32 ptr) 550 + { 551 + return (ptr | 0x80000000); 552 + } 553 + 554 + void vpu_windsor_init_rpc(struct vpu_shared_addr *shared, 555 + struct vpu_buffer *rpc, dma_addr_t boot_addr) 556 + { 557 + unsigned long base_phy_addr; 558 + unsigned long phy_addr; 559 + unsigned long offset; 560 + struct windsor_iface *iface; 561 + struct windsor_ctrl_iface *ctrl; 562 + struct vpu_enc_host_ctrls *hcs; 563 + unsigned int i; 564 + 565 + if (rpc->phys < boot_addr) 566 + return; 567 + 568 + base_phy_addr = rpc->phys - boot_addr; 569 + iface = rpc->virt; 570 + shared->iface = iface; 571 + shared->boot_addr = boot_addr; 572 + hcs = shared->priv; 573 + 574 + iface->exec_base_addr = base_phy_addr; 575 + iface->exec_area_size = rpc->length; 576 + 577 + offset = sizeof(struct windsor_iface); 578 + phy_addr = base_phy_addr + offset; 579 + shared->cmd_desc = &iface->cmd_buffer_desc; 580 + shared->cmd_mem_vir = rpc->virt + offset; 581 + iface->cmd_buffer_desc.start = 582 + iface->cmd_buffer_desc.rptr = 583 + iface->cmd_buffer_desc.wptr = phy_addr; 584 + iface->cmd_buffer_desc.end = iface->cmd_buffer_desc.start + CMD_SIZE; 585 + 586 + offset += CMD_SIZE; 587 + phy_addr = base_phy_addr + offset; 588 + shared->msg_desc = &iface->msg_buffer_desc; 589 + shared->msg_mem_vir = rpc->virt + offset; 590 + iface->msg_buffer_desc.start = 591 + iface->msg_buffer_desc.wptr = 592 + iface->msg_buffer_desc.rptr = phy_addr; 593 + iface->msg_buffer_desc.end = iface->msg_buffer_desc.start + MSG_SIZE; 594 + 595 + offset += MSG_SIZE; 596 + for (i = 0; i < ARRAY_SIZE(iface->ctrl_iface); i++) { 597 + iface->ctrl_iface[i] = base_phy_addr + offset; 598 + offset += sizeof(struct windsor_ctrl_iface); 599 + } 600 + for (i = 0; i < ARRAY_SIZE(iface->ctrl_iface); i++) { 601 + ctrl = rpc->virt + (iface->ctrl_iface[i] - base_phy_addr); 602 + 603 + ctrl->enc_yuv_buffer_desc = base_phy_addr + offset; 604 + hcs->ctrls[i].yuv_desc = rpc->virt + offset; 605 + offset += sizeof(struct vpu_enc_yuv_desc); 606 + 607 + ctrl->enc_stream_buffer_desc = base_phy_addr + offset; 608 + hcs->ctrls[i].stream_desc = rpc->virt + offset; 609 + offset += sizeof(struct vpu_rpc_buffer_desc); 610 + 611 + ctrl->enc_expert_mode_param = base_phy_addr + offset; 612 + hcs->ctrls[i].expert = rpc->virt + offset; 613 + offset += sizeof(struct vpu_enc_expert_mode_param); 614 + 615 + ctrl->enc_param = base_phy_addr + offset; 616 + hcs->ctrls[i].param = rpc->virt + offset; 617 + offset += sizeof(struct vpu_enc_param); 618 + 619 + ctrl->enc_mem_pool = base_phy_addr + offset; 620 + hcs->ctrls[i].pool = rpc->virt + offset; 621 + offset += sizeof(struct vpu_enc_mem_pool); 622 + 623 + ctrl->enc_encoding_status = base_phy_addr + offset; 624 + hcs->ctrls[i].status = rpc->virt + offset; 625 + offset += sizeof(struct vpu_enc_encoding_status); 626 + 627 + ctrl->enc_dsa_status = base_phy_addr + offset; 628 + hcs->ctrls[i].dsa = rpc->virt + offset; 629 + offset += sizeof(struct vpu_enc_dsa_status); 630 + } 631 + 632 + rpc->bytesused = offset; 633 + } 634 + 635 + void vpu_windsor_set_log_buf(struct vpu_shared_addr *shared, struct vpu_buffer *log) 636 + { 637 + struct windsor_iface *iface = shared->iface; 638 + 639 + iface->log_buffer_desc.start = 640 + iface->log_buffer_desc.wptr = 641 + iface->log_buffer_desc.rptr = log->phys - shared->boot_addr; 642 + iface->log_buffer_desc.end = iface->log_buffer_desc.start + log->length; 643 + } 644 + 645 + void vpu_windsor_set_system_cfg(struct vpu_shared_addr *shared, 646 + u32 regs_base, void __iomem *regs, u32 core_id) 647 + { 648 + struct windsor_iface *iface = shared->iface; 649 + struct vpu_rpc_system_config *config = &iface->system_config; 650 + 651 + vpu_imx8q_set_system_cfg_common(config, regs_base, core_id); 652 + } 653 + 654 + int vpu_windsor_get_stream_buffer_size(struct vpu_shared_addr *shared) 655 + { 656 + return 0x300000; 657 + } 658 + 659 + static struct vpu_pair windsor_cmds[] = { 660 + {VPU_CMD_ID_CONFIGURE_CODEC, GTB_ENC_CMD_CONFIGURE_CODEC}, 661 + {VPU_CMD_ID_START, GTB_ENC_CMD_STREAM_START}, 662 + {VPU_CMD_ID_STOP, GTB_ENC_CMD_STREAM_STOP}, 663 + {VPU_CMD_ID_FRAME_ENCODE, GTB_ENC_CMD_FRAME_ENCODE}, 664 + {VPU_CMD_ID_SNAPSHOT, GTB_ENC_CMD_SNAPSHOT}, 665 + {VPU_CMD_ID_FIRM_RESET, GTB_ENC_CMD_FIRM_RESET}, 666 + {VPU_CMD_ID_UPDATE_PARAMETER, GTB_ENC_CMD_PARAMETER_UPD}, 667 + {VPU_CMD_ID_DEBUG, GTB_ENC_CMD_FW_STATUS} 668 + }; 669 + 670 + static struct vpu_pair windsor_msgs[] = { 671 + {VPU_MSG_ID_RESET_DONE, VID_API_ENC_EVENT_RESET_DONE}, 672 + {VPU_MSG_ID_START_DONE, VID_API_ENC_EVENT_START_DONE}, 673 + {VPU_MSG_ID_STOP_DONE, VID_API_ENC_EVENT_STOP_DONE}, 674 + {VPU_MSG_ID_FRAME_INPUT_DONE, VID_API_ENC_EVENT_FRAME_INPUT_DONE}, 675 + {VPU_MSG_ID_ENC_DONE, VID_API_ENC_EVENT_FRAME_DONE}, 676 + {VPU_MSG_ID_FRAME_RELEASE, VID_API_ENC_EVENT_FRAME_RELEASE}, 677 + {VPU_MSG_ID_MEM_REQUEST, VID_API_ENC_EVENT_MEM_REQUEST}, 678 + {VPU_MSG_ID_PARAM_UPD_DONE, VID_API_ENC_EVENT_PARA_UPD_DONE}, 679 + {VPU_MSG_ID_FIRMWARE_XCPT, VID_API_ENC_EVENT_FIRMWARE_XCPT}, 680 + }; 681 + 682 + int vpu_windsor_pack_cmd(struct vpu_rpc_event *pkt, u32 index, u32 id, void *data) 683 + { 684 + int ret; 685 + s64 timestamp; 686 + 687 + ret = vpu_find_dst_by_src(windsor_cmds, ARRAY_SIZE(windsor_cmds), id); 688 + if (ret < 0) 689 + return ret; 690 + pkt->hdr.id = ret; 691 + pkt->hdr.num = 0; 692 + pkt->hdr.index = index; 693 + if (id == VPU_CMD_ID_FRAME_ENCODE) { 694 + pkt->hdr.num = 2; 695 + timestamp = *(s64 *)data; 696 + if (timestamp < 0) { 697 + pkt->data[0] = (u32)-1; 698 + pkt->data[1] = 0; 699 + } else { 700 + pkt->data[0] = timestamp / NSEC_PER_SEC; 701 + pkt->data[1] = timestamp % NSEC_PER_SEC; 702 + } 703 + } 704 + 705 + return 0; 706 + } 707 + 708 + int vpu_windsor_convert_msg_id(u32 id) 709 + { 710 + return vpu_find_src_by_dst(windsor_msgs, ARRAY_SIZE(windsor_msgs), id); 711 + } 712 + 713 + static void vpu_windsor_unpack_pic_info(struct vpu_rpc_event *pkt, void *data) 714 + { 715 + struct vpu_enc_pic_info *info = data; 716 + struct windsor_pic_info *windsor = (struct windsor_pic_info *)pkt->data; 717 + 718 + info->frame_id = windsor->frame_id; 719 + switch (windsor->pic_type) { 720 + case MEDIAIP_ENC_PIC_TYPE_I_FRAME: 721 + case MEDIAIP_ENC_PIC_TYPE_IDR_FRAME: 722 + info->pic_type = V4L2_BUF_FLAG_KEYFRAME; 723 + break; 724 + case MEDIAIP_ENC_PIC_TYPE_P_FRAME: 725 + info->pic_type = V4L2_BUF_FLAG_PFRAME; 726 + break; 727 + case MEDIAIP_ENC_PIC_TYPE_B_FRAME: 728 + info->pic_type = V4L2_BUF_FLAG_BFRAME; 729 + break; 730 + default: 731 + break; 732 + } 733 + info->skipped_frame = windsor->skipped_frame; 734 + info->error_flag = windsor->error_flag; 735 + info->psnr = windsor->psnr; 736 + info->frame_size = windsor->frame_size; 737 + info->wptr = get_ptr(windsor->str_buff_wptr); 738 + info->crc = windsor->frame_crc; 739 + info->timestamp = MAKE_TIMESTAMP(windsor->tv_s, windsor->tv_ns); 740 + } 741 + 742 + static void vpu_windsor_unpack_mem_req(struct vpu_rpc_event *pkt, void *data) 743 + { 744 + struct vpu_pkt_mem_req_data *req_data = data; 745 + 746 + req_data->enc_frame_size = pkt->data[0]; 747 + req_data->enc_frame_num = pkt->data[1]; 748 + req_data->ref_frame_size = pkt->data[2]; 749 + req_data->ref_frame_num = pkt->data[3]; 750 + req_data->act_buf_size = pkt->data[4]; 751 + req_data->act_buf_num = 1; 752 + } 753 + 754 + int vpu_windsor_unpack_msg_data(struct vpu_rpc_event *pkt, void *data) 755 + { 756 + if (!pkt || !data) 757 + return -EINVAL; 758 + 759 + switch (pkt->hdr.id) { 760 + case VID_API_ENC_EVENT_FRAME_DONE: 761 + vpu_windsor_unpack_pic_info(pkt, data); 762 + break; 763 + case VID_API_ENC_EVENT_MEM_REQUEST: 764 + vpu_windsor_unpack_mem_req(pkt, data); 765 + break; 766 + case VID_API_ENC_EVENT_FRAME_RELEASE: 767 + *(u32 *)data = pkt->data[0]; 768 + break; 769 + default: 770 + break; 771 + } 772 + 773 + return 0; 774 + } 775 + 776 + static int vpu_windsor_fill_yuv_frame(struct vpu_shared_addr *shared, 777 + u32 instance, 778 + struct vb2_buffer *vb) 779 + { 780 + struct vpu_enc_yuv_desc *desc; 781 + struct vb2_v4l2_buffer *vbuf; 782 + 783 + if (instance >= VID_API_NUM_STREAMS) 784 + return -EINVAL; 785 + 786 + desc = get_yuv_desc(shared, instance); 787 + 788 + vbuf = to_vb2_v4l2_buffer(vb); 789 + desc->frame_id = vbuf->sequence; 790 + if (vbuf->flags & V4L2_BUF_FLAG_KEYFRAME) 791 + desc->key_frame = 1; 792 + else 793 + desc->key_frame = 0; 794 + desc->luma_base = vpu_get_vb_phy_addr(vb, 0); 795 + desc->chroma_base = vpu_get_vb_phy_addr(vb, 1); 796 + 797 + return 0; 798 + } 799 + 800 + int vpu_windsor_input_frame(struct vpu_shared_addr *shared, 801 + struct vpu_inst *inst, struct vb2_buffer *vb) 802 + { 803 + vpu_windsor_fill_yuv_frame(shared, inst->id, vb); 804 + return vpu_session_encode_frame(inst, vb->timestamp); 805 + } 806 + 807 + int vpu_windsor_config_memory_resource(struct vpu_shared_addr *shared, 808 + u32 instance, 809 + u32 type, 810 + u32 index, 811 + struct vpu_buffer *buf) 812 + { 813 + struct vpu_enc_mem_pool *pool; 814 + struct vpu_enc_memory_resource *res; 815 + 816 + if (instance >= VID_API_NUM_STREAMS) 817 + return -EINVAL; 818 + 819 + pool = get_mem_pool(shared, instance); 820 + 821 + switch (type) { 822 + case MEM_RES_ENC: 823 + res = &pool->enc_frames[index]; 824 + break; 825 + case MEM_RES_REF: 826 + res = &pool->ref_frames[index]; 827 + break; 828 + case MEM_RES_ACT: 829 + res = &pool->act_frame; 830 + break; 831 + default: 832 + return -EINVAL; 833 + } 834 + 835 + res->phys = buf->phys; 836 + res->virt = buf->phys - shared->boot_addr; 837 + res->size = buf->length; 838 + 839 + return 0; 840 + } 841 + 842 + int vpu_windsor_config_stream_buffer(struct vpu_shared_addr *shared, 843 + u32 instance, 844 + struct vpu_buffer *buf) 845 + { 846 + struct vpu_rpc_buffer_desc *desc; 847 + struct vpu_enc_expert_mode_param *expert; 848 + 849 + desc = get_stream_buf_desc(shared, instance); 850 + expert = get_expert_param(shared, instance); 851 + 852 + desc->start = buf->phys; 853 + desc->wptr = buf->phys; 854 + desc->rptr = buf->phys; 855 + desc->end = buf->phys + buf->length; 856 + 857 + expert->calib_param.mem_chunk_phys_addr = 0; 858 + expert->calib_param.mem_chunk_virt_addr = 0; 859 + expert->calib_param.mem_chunk_size = 0; 860 + expert->calib_param.cb_base = buf->phys; 861 + expert->calib_param.cb_size = buf->length; 862 + 863 + return 0; 864 + } 865 + 866 + int vpu_windsor_update_stream_buffer(struct vpu_shared_addr *shared, 867 + u32 instance, u32 ptr, bool write) 868 + { 869 + struct vpu_rpc_buffer_desc *desc; 870 + 871 + desc = get_stream_buf_desc(shared, instance); 872 + 873 + /*update wptr/rptr after data is written or read*/ 874 + mb(); 875 + if (write) 876 + desc->wptr = ptr; 877 + else 878 + desc->rptr = ptr; 879 + 880 + return 0; 881 + } 882 + 883 + int vpu_windsor_get_stream_buffer_desc(struct vpu_shared_addr *shared, 884 + u32 instance, struct vpu_rpc_buffer_desc *desc) 885 + { 886 + struct vpu_rpc_buffer_desc *rpc_desc; 887 + 888 + rpc_desc = get_stream_buf_desc(shared, instance); 889 + if (desc) { 890 + desc->wptr = get_ptr(rpc_desc->wptr); 891 + desc->rptr = get_ptr(rpc_desc->rptr); 892 + desc->start = get_ptr(rpc_desc->start); 893 + desc->end = get_ptr(rpc_desc->end); 894 + } 895 + 896 + return 0; 897 + } 898 + 899 + u32 vpu_windsor_get_version(struct vpu_shared_addr *shared) 900 + { 901 + struct windsor_iface *iface = shared->iface; 902 + 903 + return iface->fw_version; 904 + } 905 + 906 + static int vpu_windsor_set_frame_rate(struct vpu_enc_expert_mode_param *expert, 907 + struct vpu_encode_params *params) 908 + { 909 + expert->config_param.frame_rate_num = params->frame_rate.numerator; 910 + expert->config_param.frame_rate_den = params->frame_rate.denominator; 911 + 912 + return 0; 913 + } 914 + 915 + static int vpu_windsor_set_format(struct vpu_enc_param *param, u32 pixelformat) 916 + { 917 + switch (pixelformat) { 918 + case V4L2_PIX_FMT_H264: 919 + param->codec_mode = MEDIAIP_ENC_FMT_H264; 920 + break; 921 + default: 922 + return -EINVAL; 923 + } 924 + 925 + return 0; 926 + } 927 + 928 + static int vpu_windsor_set_profile(struct vpu_enc_param *param, u32 profile) 929 + { 930 + switch (profile) { 931 + case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE: 932 + param->profile = MEDIAIP_ENC_PROF_H264_BP; 933 + break; 934 + case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN: 935 + param->profile = MEDIAIP_ENC_PROF_H264_MP; 936 + break; 937 + case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH: 938 + param->profile = MEDIAIP_ENC_PROF_H264_HP; 939 + break; 940 + default: 941 + return -EINVAL; 942 + } 943 + 944 + return 0; 945 + } 946 + 947 + static const u32 h264_level[] = { 948 + [V4L2_MPEG_VIDEO_H264_LEVEL_1_0] = 10, 949 + [V4L2_MPEG_VIDEO_H264_LEVEL_1B] = 14, 950 + [V4L2_MPEG_VIDEO_H264_LEVEL_1_1] = 11, 951 + [V4L2_MPEG_VIDEO_H264_LEVEL_1_2] = 12, 952 + [V4L2_MPEG_VIDEO_H264_LEVEL_1_3] = 13, 953 + [V4L2_MPEG_VIDEO_H264_LEVEL_2_0] = 20, 954 + [V4L2_MPEG_VIDEO_H264_LEVEL_2_1] = 21, 955 + [V4L2_MPEG_VIDEO_H264_LEVEL_2_2] = 22, 956 + [V4L2_MPEG_VIDEO_H264_LEVEL_3_0] = 30, 957 + [V4L2_MPEG_VIDEO_H264_LEVEL_3_1] = 31, 958 + [V4L2_MPEG_VIDEO_H264_LEVEL_3_2] = 32, 959 + [V4L2_MPEG_VIDEO_H264_LEVEL_4_0] = 40, 960 + [V4L2_MPEG_VIDEO_H264_LEVEL_4_1] = 41, 961 + [V4L2_MPEG_VIDEO_H264_LEVEL_4_2] = 42, 962 + [V4L2_MPEG_VIDEO_H264_LEVEL_5_0] = 50, 963 + [V4L2_MPEG_VIDEO_H264_LEVEL_5_1] = 51 964 + }; 965 + 966 + static int vpu_windsor_set_level(struct vpu_enc_param *param, u32 level) 967 + { 968 + if (level >= ARRAY_SIZE(h264_level)) 969 + return -EINVAL; 970 + 971 + param->level = h264_level[level]; 972 + 973 + return 0; 974 + } 975 + 976 + static int vpu_windsor_set_size(struct vpu_enc_param *windsor, 977 + struct vpu_encode_params *params) 978 + { 979 + windsor->src_stride = params->src_stride; 980 + windsor->src_width = params->src_width; 981 + windsor->src_height = params->src_height; 982 + windsor->src_offset_x = params->crop.left; 983 + windsor->src_offset_y = params->crop.top; 984 + windsor->src_crop_width = params->crop.width; 985 + windsor->src_crop_height = params->crop.height; 986 + windsor->out_width = params->out_width; 987 + windsor->out_height = params->out_height; 988 + 989 + return 0; 990 + } 991 + 992 + static int vpu_windsor_set_gop(struct vpu_enc_param *param, u32 gop) 993 + { 994 + param->iframe_interval = gop; 995 + 996 + return 0; 997 + } 998 + 999 + static int vpu_windsor_set_bframes(struct vpu_enc_param *param, u32 bframes) 1000 + { 1001 + if (bframes) { 1002 + param->low_latency_mode = 0; 1003 + param->bframes = bframes; 1004 + } else { 1005 + param->low_latency_mode = 1; 1006 + param->bframes = 0; 1007 + } 1008 + 1009 + return 0; 1010 + } 1011 + 1012 + static int vpu_windsor_set_bitrate_mode(struct vpu_enc_param *param, u32 rc_enable, u32 mode) 1013 + { 1014 + if (!rc_enable) 1015 + param->bitrate_mode = MEDIAIP_ENC_BITRATE_MODE_CONSTANT_QP; 1016 + else if (mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) 1017 + param->bitrate_mode = MEDIAIP_ENC_BITRATE_MODE_VBR; 1018 + else 1019 + param->bitrate_mode = MEDIAIP_ENC_BITRATE_MODE_CBR; 1020 + 1021 + return 0; 1022 + } 1023 + 1024 + static u32 vpu_windsor_bitrate(u32 bitrate) 1025 + { 1026 + return DIV_ROUND_CLOSEST(bitrate, WINDSOR_BITRATE_UNIT); 1027 + } 1028 + 1029 + static int vpu_windsor_set_bitrate(struct vpu_enc_param *windsor, 1030 + struct vpu_encode_params *params) 1031 + { 1032 + windsor->target_bitrate = vpu_windsor_bitrate(params->bitrate); 1033 + windsor->min_bitrate = vpu_windsor_bitrate(params->bitrate_min); 1034 + windsor->max_bitrate = vpu_windsor_bitrate(params->bitrate_max); 1035 + 1036 + return 0; 1037 + } 1038 + 1039 + static int vpu_windsor_set_qp(struct vpu_enc_expert_mode_param *expert, 1040 + struct vpu_encode_params *params) 1041 + { 1042 + expert->static_param.rate_control_islice_qp = params->i_frame_qp; 1043 + expert->static_param.rate_control_pslice_qp = params->p_frame_qp; 1044 + expert->static_param.rate_control_bslice_qp = params->b_frame_qp; 1045 + 1046 + return 0; 1047 + } 1048 + 1049 + static int vpu_windsor_set_sar(struct vpu_enc_expert_mode_param *expert, 1050 + struct vpu_encode_params *params) 1051 + { 1052 + expert->config_param.h264_aspect_ratio_present = params->sar.enable; 1053 + if (params->sar.idc == V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_EXTENDED) 1054 + expert->config_param.aspect_ratio = WINDSOR_H264_EXTENDED_SAR; 1055 + else 1056 + expert->config_param.aspect_ratio = params->sar.idc; 1057 + expert->config_param.h264_aspect_ratio_sar_width = params->sar.width; 1058 + expert->config_param.h264_aspect_ratio_sar_height = params->sar.height; 1059 + 1060 + return 0; 1061 + } 1062 + 1063 + static int vpu_windsor_set_color(struct vpu_enc_expert_mode_param *expert, 1064 + struct vpu_encode_params *params) 1065 + { 1066 + expert->config_param.h264_video_type_present = 1; 1067 + expert->config_param.h264_video_format = 5; 1068 + expert->config_param.h264_video_colour_descriptor = 1; 1069 + expert->config_param.h264_video_colour_primaries = 1070 + vpu_color_cvrt_primaries_v2i(params->color.primaries); 1071 + expert->config_param.h264_video_transfer_char = 1072 + vpu_color_cvrt_transfers_v2i(params->color.transfer); 1073 + expert->config_param.h264_video_matrix_coeff = 1074 + vpu_color_cvrt_matrix_v2i(params->color.matrix); 1075 + expert->config_param.h264_video_full_range = 1076 + vpu_color_cvrt_full_range_v2i(params->color.full_range); 1077 + return 0; 1078 + } 1079 + 1080 + static int vpu_windsor_update_bitrate(struct vpu_shared_addr *shared, 1081 + u32 instance, struct vpu_encode_params *params) 1082 + { 1083 + struct vpu_enc_param *windsor; 1084 + struct vpu_enc_expert_mode_param *expert; 1085 + 1086 + windsor = get_enc_param(shared, instance); 1087 + expert = get_expert_param(shared, instance); 1088 + 1089 + if (windsor->bitrate_mode != MEDIAIP_ENC_BITRATE_MODE_CBR) 1090 + return 0; 1091 + if (!params->rc_enable) 1092 + return 0; 1093 + if (vpu_windsor_bitrate(params->bitrate) == windsor->target_bitrate) 1094 + return 0; 1095 + 1096 + vpu_windsor_set_bitrate(windsor, params); 1097 + expert->static_param.rate_control_bitrate = windsor->target_bitrate; 1098 + expert->static_param.rate_control_bitrate_min = windsor->min_bitrate; 1099 + expert->static_param.rate_control_bitrate_max = windsor->max_bitrate; 1100 + 1101 + return 0; 1102 + } 1103 + 1104 + static int vpu_windsor_set_params(struct vpu_shared_addr *shared, 1105 + u32 instance, struct vpu_encode_params *params) 1106 + { 1107 + struct vpu_enc_param *windsor; 1108 + int ret; 1109 + 1110 + windsor = get_enc_param(shared, instance); 1111 + 1112 + if (params->input_format != V4L2_PIX_FMT_NV12 && 1113 + params->input_format != V4L2_PIX_FMT_NV12M) 1114 + return -EINVAL; 1115 + 1116 + ret = vpu_windsor_set_format(windsor, params->codec_format); 1117 + if (ret) 1118 + return ret; 1119 + vpu_windsor_set_profile(windsor, params->profile); 1120 + vpu_windsor_set_level(windsor, params->level); 1121 + vpu_windsor_set_size(windsor, params); 1122 + vpu_windsor_set_gop(windsor, params->gop_length); 1123 + vpu_windsor_set_bframes(windsor, params->bframes); 1124 + vpu_windsor_set_bitrate_mode(windsor, params->rc_enable, params->rc_mode); 1125 + vpu_windsor_set_bitrate(windsor, params); 1126 + windsor->init_slice_qp = params->i_frame_qp; 1127 + 1128 + if (!params->frame_rate.numerator) 1129 + return -EINVAL; 1130 + windsor->frame_rate = params->frame_rate.denominator / params->frame_rate.numerator; 1131 + 1132 + return 0; 1133 + } 1134 + 1135 + static int vpu_windsor_update_params(struct vpu_shared_addr *shared, 1136 + u32 instance, struct vpu_encode_params *params) 1137 + { 1138 + struct vpu_enc_expert_mode_param *expert; 1139 + 1140 + expert = get_expert_param(shared, instance); 1141 + 1142 + vpu_windsor_set_frame_rate(expert, params); 1143 + vpu_windsor_set_qp(expert, params); 1144 + vpu_windsor_set_sar(expert, params); 1145 + vpu_windsor_set_color(expert, params); 1146 + vpu_windsor_update_bitrate(shared, instance, params); 1147 + /*expert->config_param.iac_sc_threshold = 0;*/ 1148 + 1149 + return 0; 1150 + } 1151 + 1152 + int vpu_windsor_set_encode_params(struct vpu_shared_addr *shared, 1153 + u32 instance, struct vpu_encode_params *params, u32 update) 1154 + { 1155 + if (!params) 1156 + return -EINVAL; 1157 + 1158 + if (!update) 1159 + return vpu_windsor_set_params(shared, instance, params); 1160 + else 1161 + return vpu_windsor_update_params(shared, instance, params); 1162 + } 1163 + 1164 + u32 vpu_windsor_get_max_instance_count(struct vpu_shared_addr *shared) 1165 + { 1166 + struct windsor_iface *iface = shared->iface; 1167 + 1168 + return iface->max_streams; 1169 + }
+37
drivers/media/platform/amphion/vpu_windsor.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Copyright 2020-2021 NXP 4 + */ 5 + 6 + #ifndef _AMPHION_VPU_WINDSOR_H 7 + #define _AMPHION_VPU_WINDSOR_H 8 + 9 + u32 vpu_windsor_get_data_size(void); 10 + void vpu_windsor_init_rpc(struct vpu_shared_addr *shared, 11 + struct vpu_buffer *rpc, dma_addr_t boot_addr); 12 + void vpu_windsor_set_log_buf(struct vpu_shared_addr *shared, struct vpu_buffer *log); 13 + void vpu_windsor_set_system_cfg(struct vpu_shared_addr *shared, 14 + u32 regs_base, void __iomem *regs, u32 core_id); 15 + int vpu_windsor_get_stream_buffer_size(struct vpu_shared_addr *shared); 16 + int vpu_windsor_pack_cmd(struct vpu_rpc_event *pkt, u32 index, u32 id, void *data); 17 + int vpu_windsor_convert_msg_id(u32 msg_id); 18 + int vpu_windsor_unpack_msg_data(struct vpu_rpc_event *pkt, void *data); 19 + int vpu_windsor_config_memory_resource(struct vpu_shared_addr *shared, 20 + u32 instance, u32 type, u32 index, 21 + struct vpu_buffer *buf); 22 + int vpu_windsor_config_stream_buffer(struct vpu_shared_addr *shared, 23 + u32 instance, struct vpu_buffer *buf); 24 + int vpu_windsor_update_stream_buffer(struct vpu_shared_addr *shared, 25 + u32 instance, u32 ptr, bool write); 26 + int vpu_windsor_get_stream_buffer_desc(struct vpu_shared_addr *shared, 27 + u32 instance, struct vpu_rpc_buffer_desc *desc); 28 + u32 vpu_windsor_get_version(struct vpu_shared_addr *shared); 29 + int vpu_windsor_set_encode_params(struct vpu_shared_addr *shared, 30 + u32 instance, 31 + struct vpu_encode_params *params, 32 + u32 update); 33 + int vpu_windsor_input_frame(struct vpu_shared_addr *shared, 34 + struct vpu_inst *inst, struct vb2_buffer *vb); 35 + u32 vpu_windsor_get_max_instance_count(struct vpu_shared_addr *shared); 36 + 37 + #endif
+2
drivers/media/v4l2-core/v4l2-ioctl.c
··· 1390 1390 case V4L2_META_FMT_VIVID: descr = "Vivid Metadata"; break; 1391 1391 case V4L2_META_FMT_RK_ISP1_PARAMS: descr = "Rockchip ISP1 3A Parameters"; break; 1392 1392 case V4L2_META_FMT_RK_ISP1_STAT_3A: descr = "Rockchip ISP1 3A Statistics"; break; 1393 + case V4L2_PIX_FMT_NV12M_8L128: descr = "NV12M (8x128 Linear)"; break; 1394 + case V4L2_PIX_FMT_NV12M_10BE_8L128: descr = "10-bit NV12M (8x128 Linear, BE)"; break; 1393 1395 1394 1396 default: 1395 1397 /* Compressed formats */
+2
include/uapi/linux/videodev2.h
··· 632 632 /* Tiled YUV formats, non contiguous planes */ 633 633 #define V4L2_PIX_FMT_NV12MT v4l2_fourcc('T', 'M', '1', '2') /* 12 Y/CbCr 4:2:0 64x32 tiles */ 634 634 #define V4L2_PIX_FMT_NV12MT_16X16 v4l2_fourcc('V', 'M', '1', '2') /* 12 Y/CbCr 4:2:0 16x16 tiles */ 635 + #define V4L2_PIX_FMT_NV12M_8L128 v4l2_fourcc('N', 'A', '1', '2') /* Y/CbCr 4:2:0 8x128 tiles */ 636 + #define V4L2_PIX_FMT_NV12M_10BE_8L128 v4l2_fourcc_be('N', 'T', '1', '2') /* Y/CbCr 4:2:0 10-bit 8x128 tiles */ 635 637 636 638 /* Bayer formats - see http://www.siliconimaging.com/RGB%20Bayer.htm */ 637 639 #define V4L2_PIX_FMT_SBGGR8 v4l2_fourcc('B', 'A', '8', '1') /* 8 BGBG.. GRGR.. */