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

Configure Feed

Select the types of activity you want to include in your feed.

at v6.2-rc2 485 lines 13 kB view raw
1// SPDX-License-Identifier: GPL-2.0 2/* 3* Copyright (c) 2016 MediaTek Inc. 4* Author: PC Chen <pc.chen@mediatek.com> 5* Tiffany Lin <tiffany.lin@mediatek.com> 6*/ 7 8#include <linux/slab.h> 9#include <linux/interrupt.h> 10#include <linux/irq.h> 11#include <linux/module.h> 12#include <linux/of_device.h> 13#include <linux/of.h> 14#include <linux/pm_runtime.h> 15#include <media/v4l2-event.h> 16#include <media/v4l2-mem2mem.h> 17#include <media/videobuf2-dma-contig.h> 18 19#include "mtk_vcodec_drv.h" 20#include "mtk_vcodec_enc.h" 21#include "mtk_vcodec_enc_pm.h" 22#include "mtk_vcodec_intr.h" 23#include "mtk_vcodec_util.h" 24#include "mtk_vcodec_fw.h" 25 26static const struct mtk_video_fmt mtk_video_formats_output[] = { 27 { 28 .fourcc = V4L2_PIX_FMT_NV12M, 29 .type = MTK_FMT_FRAME, 30 .num_planes = 2, 31 }, 32 { 33 .fourcc = V4L2_PIX_FMT_NV21M, 34 .type = MTK_FMT_FRAME, 35 .num_planes = 2, 36 }, 37 { 38 .fourcc = V4L2_PIX_FMT_YUV420M, 39 .type = MTK_FMT_FRAME, 40 .num_planes = 3, 41 }, 42 { 43 .fourcc = V4L2_PIX_FMT_YVU420M, 44 .type = MTK_FMT_FRAME, 45 .num_planes = 3, 46 }, 47}; 48 49static const struct mtk_video_fmt mtk_video_formats_capture_h264[] = { 50 { 51 .fourcc = V4L2_PIX_FMT_H264, 52 .type = MTK_FMT_ENC, 53 .num_planes = 1, 54 }, 55}; 56 57static const struct mtk_video_fmt mtk_video_formats_capture_vp8[] = { 58 { 59 .fourcc = V4L2_PIX_FMT_VP8, 60 .type = MTK_FMT_ENC, 61 .num_planes = 1, 62 }, 63}; 64 65static void clean_irq_status(unsigned int irq_status, void __iomem *addr) 66{ 67 if (irq_status & MTK_VENC_IRQ_STATUS_PAUSE) 68 writel(MTK_VENC_IRQ_STATUS_PAUSE, addr); 69 70 if (irq_status & MTK_VENC_IRQ_STATUS_SWITCH) 71 writel(MTK_VENC_IRQ_STATUS_SWITCH, addr); 72 73 if (irq_status & MTK_VENC_IRQ_STATUS_DRAM) 74 writel(MTK_VENC_IRQ_STATUS_DRAM, addr); 75 76 if (irq_status & MTK_VENC_IRQ_STATUS_SPS) 77 writel(MTK_VENC_IRQ_STATUS_SPS, addr); 78 79 if (irq_status & MTK_VENC_IRQ_STATUS_PPS) 80 writel(MTK_VENC_IRQ_STATUS_PPS, addr); 81 82 if (irq_status & MTK_VENC_IRQ_STATUS_FRM) 83 writel(MTK_VENC_IRQ_STATUS_FRM, addr); 84 85} 86static irqreturn_t mtk_vcodec_enc_irq_handler(int irq, void *priv) 87{ 88 struct mtk_vcodec_dev *dev = priv; 89 struct mtk_vcodec_ctx *ctx; 90 unsigned long flags; 91 void __iomem *addr; 92 93 spin_lock_irqsave(&dev->irqlock, flags); 94 ctx = dev->curr_ctx; 95 spin_unlock_irqrestore(&dev->irqlock, flags); 96 97 mtk_v4l2_debug(1, "id=%d coreid:%d", ctx->id, dev->venc_pdata->core_id); 98 addr = dev->reg_base[dev->venc_pdata->core_id] + 99 MTK_VENC_IRQ_ACK_OFFSET; 100 101 ctx->irq_status = readl(dev->reg_base[dev->venc_pdata->core_id] + 102 (MTK_VENC_IRQ_STATUS_OFFSET)); 103 104 clean_irq_status(ctx->irq_status, addr); 105 106 wake_up_ctx(ctx, MTK_INST_IRQ_RECEIVED, 0); 107 return IRQ_HANDLED; 108} 109 110static int fops_vcodec_open(struct file *file) 111{ 112 struct mtk_vcodec_dev *dev = video_drvdata(file); 113 struct mtk_vcodec_ctx *ctx = NULL; 114 int ret = 0; 115 struct vb2_queue *src_vq; 116 117 ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); 118 if (!ctx) 119 return -ENOMEM; 120 121 mutex_lock(&dev->dev_mutex); 122 /* 123 * Use simple counter to uniquely identify this context. Only 124 * used for logging. 125 */ 126 ctx->id = dev->id_counter++; 127 v4l2_fh_init(&ctx->fh, video_devdata(file)); 128 file->private_data = &ctx->fh; 129 v4l2_fh_add(&ctx->fh); 130 INIT_LIST_HEAD(&ctx->list); 131 ctx->dev = dev; 132 init_waitqueue_head(&ctx->queue[0]); 133 mutex_init(&ctx->q_mutex); 134 135 ctx->type = MTK_INST_ENCODER; 136 ret = mtk_vcodec_enc_ctrls_setup(ctx); 137 if (ret) { 138 mtk_v4l2_err("Failed to setup controls() (%d)", 139 ret); 140 goto err_ctrls_setup; 141 } 142 ctx->m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev_enc, ctx, 143 &mtk_vcodec_enc_queue_init); 144 if (IS_ERR((__force void *)ctx->m2m_ctx)) { 145 ret = PTR_ERR((__force void *)ctx->m2m_ctx); 146 mtk_v4l2_err("Failed to v4l2_m2m_ctx_init() (%d)", 147 ret); 148 goto err_m2m_ctx_init; 149 } 150 src_vq = v4l2_m2m_get_vq(ctx->m2m_ctx, 151 V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); 152 ctx->empty_flush_buf.vb.vb2_buf.vb2_queue = src_vq; 153 mtk_vcodec_enc_set_default_params(ctx); 154 155 if (v4l2_fh_is_singular(&ctx->fh)) { 156 /* 157 * load fireware to checks if it was loaded already and 158 * does nothing in that case 159 */ 160 ret = mtk_vcodec_fw_load_firmware(dev->fw_handler); 161 if (ret < 0) { 162 /* 163 * Return 0 if downloading firmware successfully, 164 * otherwise it is failed 165 */ 166 mtk_v4l2_err("vpu_load_firmware failed!"); 167 goto err_load_fw; 168 } 169 170 dev->enc_capability = 171 mtk_vcodec_fw_get_venc_capa(dev->fw_handler); 172 mtk_v4l2_debug(0, "encoder capability %x", dev->enc_capability); 173 } 174 175 mtk_v4l2_debug(2, "Create instance [%d]@%p m2m_ctx=%p ", 176 ctx->id, ctx, ctx->m2m_ctx); 177 178 list_add(&ctx->list, &dev->ctx_list); 179 180 mutex_unlock(&dev->dev_mutex); 181 mtk_v4l2_debug(0, "%s encoder [%d]", dev_name(&dev->plat_dev->dev), 182 ctx->id); 183 return ret; 184 185 /* Deinit when failure occurred */ 186err_load_fw: 187 v4l2_m2m_ctx_release(ctx->m2m_ctx); 188err_m2m_ctx_init: 189 v4l2_ctrl_handler_free(&ctx->ctrl_hdl); 190err_ctrls_setup: 191 v4l2_fh_del(&ctx->fh); 192 v4l2_fh_exit(&ctx->fh); 193 kfree(ctx); 194 mutex_unlock(&dev->dev_mutex); 195 196 return ret; 197} 198 199static int fops_vcodec_release(struct file *file) 200{ 201 struct mtk_vcodec_dev *dev = video_drvdata(file); 202 struct mtk_vcodec_ctx *ctx = fh_to_ctx(file->private_data); 203 204 mtk_v4l2_debug(1, "[%d] encoder", ctx->id); 205 mutex_lock(&dev->dev_mutex); 206 207 v4l2_m2m_ctx_release(ctx->m2m_ctx); 208 mtk_vcodec_enc_release(ctx); 209 v4l2_fh_del(&ctx->fh); 210 v4l2_fh_exit(&ctx->fh); 211 v4l2_ctrl_handler_free(&ctx->ctrl_hdl); 212 213 list_del_init(&ctx->list); 214 kfree(ctx); 215 mutex_unlock(&dev->dev_mutex); 216 return 0; 217} 218 219static const struct v4l2_file_operations mtk_vcodec_fops = { 220 .owner = THIS_MODULE, 221 .open = fops_vcodec_open, 222 .release = fops_vcodec_release, 223 .poll = v4l2_m2m_fop_poll, 224 .unlocked_ioctl = video_ioctl2, 225 .mmap = v4l2_m2m_fop_mmap, 226}; 227 228static int mtk_vcodec_probe(struct platform_device *pdev) 229{ 230 struct mtk_vcodec_dev *dev; 231 struct video_device *vfd_enc; 232 phandle rproc_phandle; 233 enum mtk_vcodec_fw_type fw_type; 234 int ret; 235 236 dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); 237 if (!dev) 238 return -ENOMEM; 239 240 INIT_LIST_HEAD(&dev->ctx_list); 241 dev->plat_dev = pdev; 242 243 if (!of_property_read_u32(pdev->dev.of_node, "mediatek,vpu", 244 &rproc_phandle)) { 245 fw_type = VPU; 246 } else if (!of_property_read_u32(pdev->dev.of_node, "mediatek,scp", 247 &rproc_phandle)) { 248 fw_type = SCP; 249 } else { 250 mtk_v4l2_err("Could not get venc IPI device"); 251 return -ENODEV; 252 } 253 dma_set_max_seg_size(&pdev->dev, UINT_MAX); 254 255 dev->fw_handler = mtk_vcodec_fw_select(dev, fw_type, ENCODER); 256 if (IS_ERR(dev->fw_handler)) 257 return PTR_ERR(dev->fw_handler); 258 259 dev->venc_pdata = of_device_get_match_data(&pdev->dev); 260 ret = mtk_vcodec_init_enc_clk(dev); 261 if (ret < 0) { 262 dev_err(&pdev->dev, "Failed to get mtk vcodec clock source!"); 263 goto err_enc_pm; 264 } 265 266 pm_runtime_enable(&pdev->dev); 267 268 dev->reg_base[dev->venc_pdata->core_id] = 269 devm_platform_ioremap_resource(pdev, 0); 270 if (IS_ERR(dev->reg_base[dev->venc_pdata->core_id])) { 271 ret = PTR_ERR(dev->reg_base[dev->venc_pdata->core_id]); 272 goto err_res; 273 } 274 275 dev->enc_irq = platform_get_irq(pdev, 0); 276 if (dev->enc_irq < 0) { 277 ret = dev->enc_irq; 278 goto err_res; 279 } 280 281 irq_set_status_flags(dev->enc_irq, IRQ_NOAUTOEN); 282 ret = devm_request_irq(&pdev->dev, dev->enc_irq, 283 mtk_vcodec_enc_irq_handler, 284 0, pdev->name, dev); 285 if (ret) { 286 dev_err(&pdev->dev, 287 "Failed to install dev->enc_irq %d (%d) core_id (%d)", 288 dev->enc_irq, ret, dev->venc_pdata->core_id); 289 ret = -EINVAL; 290 goto err_res; 291 } 292 293 mutex_init(&dev->enc_mutex); 294 mutex_init(&dev->dev_mutex); 295 spin_lock_init(&dev->irqlock); 296 297 snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name), "%s", 298 "[MTK_V4L2_VENC]"); 299 300 ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev); 301 if (ret) { 302 mtk_v4l2_err("v4l2_device_register err=%d", ret); 303 goto err_res; 304 } 305 306 init_waitqueue_head(&dev->queue); 307 308 /* allocate video device for encoder and register it */ 309 vfd_enc = video_device_alloc(); 310 if (!vfd_enc) { 311 mtk_v4l2_err("Failed to allocate video device"); 312 ret = -ENOMEM; 313 goto err_enc_alloc; 314 } 315 vfd_enc->fops = &mtk_vcodec_fops; 316 vfd_enc->ioctl_ops = &mtk_venc_ioctl_ops; 317 vfd_enc->release = video_device_release; 318 vfd_enc->lock = &dev->dev_mutex; 319 vfd_enc->v4l2_dev = &dev->v4l2_dev; 320 vfd_enc->vfl_dir = VFL_DIR_M2M; 321 vfd_enc->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | 322 V4L2_CAP_STREAMING; 323 324 snprintf(vfd_enc->name, sizeof(vfd_enc->name), "%s", 325 MTK_VCODEC_ENC_NAME); 326 video_set_drvdata(vfd_enc, dev); 327 dev->vfd_enc = vfd_enc; 328 platform_set_drvdata(pdev, dev); 329 330 dev->m2m_dev_enc = v4l2_m2m_init(&mtk_venc_m2m_ops); 331 if (IS_ERR((__force void *)dev->m2m_dev_enc)) { 332 mtk_v4l2_err("Failed to init mem2mem enc device"); 333 ret = PTR_ERR((__force void *)dev->m2m_dev_enc); 334 goto err_enc_mem_init; 335 } 336 337 dev->encode_workqueue = 338 alloc_ordered_workqueue(MTK_VCODEC_ENC_NAME, 339 WQ_MEM_RECLAIM | 340 WQ_FREEZABLE); 341 if (!dev->encode_workqueue) { 342 mtk_v4l2_err("Failed to create encode workqueue"); 343 ret = -EINVAL; 344 goto err_event_workq; 345 } 346 347 if (of_get_property(pdev->dev.of_node, "dma-ranges", NULL)) 348 dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(34)); 349 350 ret = video_register_device(vfd_enc, VFL_TYPE_VIDEO, -1); 351 if (ret) { 352 mtk_v4l2_err("Failed to register video device"); 353 goto err_enc_reg; 354 } 355 356 mtk_v4l2_debug(0, "encoder %d registered as /dev/video%d", 357 dev->venc_pdata->core_id, vfd_enc->num); 358 359 return 0; 360 361err_enc_reg: 362 destroy_workqueue(dev->encode_workqueue); 363err_event_workq: 364 v4l2_m2m_release(dev->m2m_dev_enc); 365err_enc_mem_init: 366 video_unregister_device(vfd_enc); 367err_enc_alloc: 368 v4l2_device_unregister(&dev->v4l2_dev); 369err_res: 370 pm_runtime_disable(dev->pm.dev); 371err_enc_pm: 372 mtk_vcodec_fw_release(dev->fw_handler); 373 return ret; 374} 375 376static const struct mtk_vcodec_enc_pdata mt8173_avc_pdata = { 377 .capture_formats = mtk_video_formats_capture_h264, 378 .num_capture_formats = ARRAY_SIZE(mtk_video_formats_capture_h264), 379 .output_formats = mtk_video_formats_output, 380 .num_output_formats = ARRAY_SIZE(mtk_video_formats_output), 381 .min_bitrate = 64, 382 .max_bitrate = 60000000, 383 .core_id = VENC_SYS, 384}; 385 386static const struct mtk_vcodec_enc_pdata mt8173_vp8_pdata = { 387 .capture_formats = mtk_video_formats_capture_vp8, 388 .num_capture_formats = ARRAY_SIZE(mtk_video_formats_capture_vp8), 389 .output_formats = mtk_video_formats_output, 390 .num_output_formats = ARRAY_SIZE(mtk_video_formats_output), 391 .min_bitrate = 64, 392 .max_bitrate = 9000000, 393 .core_id = VENC_LT_SYS, 394}; 395 396static const struct mtk_vcodec_enc_pdata mt8183_pdata = { 397 .uses_ext = true, 398 .capture_formats = mtk_video_formats_capture_h264, 399 .num_capture_formats = ARRAY_SIZE(mtk_video_formats_capture_h264), 400 .output_formats = mtk_video_formats_output, 401 .num_output_formats = ARRAY_SIZE(mtk_video_formats_output), 402 .min_bitrate = 64, 403 .max_bitrate = 40000000, 404 .core_id = VENC_SYS, 405}; 406 407static const struct mtk_vcodec_enc_pdata mt8188_pdata = { 408 .uses_ext = true, 409 .capture_formats = mtk_video_formats_capture_h264, 410 .num_capture_formats = ARRAY_SIZE(mtk_video_formats_capture_h264), 411 .output_formats = mtk_video_formats_output, 412 .num_output_formats = ARRAY_SIZE(mtk_video_formats_output), 413 .min_bitrate = 64, 414 .max_bitrate = 50000000, 415 .core_id = VENC_SYS, 416 .uses_34bit = true, 417}; 418 419static const struct mtk_vcodec_enc_pdata mt8192_pdata = { 420 .uses_ext = true, 421 .capture_formats = mtk_video_formats_capture_h264, 422 .num_capture_formats = ARRAY_SIZE(mtk_video_formats_capture_h264), 423 .output_formats = mtk_video_formats_output, 424 .num_output_formats = ARRAY_SIZE(mtk_video_formats_output), 425 .min_bitrate = 64, 426 .max_bitrate = 100000000, 427 .core_id = VENC_SYS, 428}; 429 430static const struct mtk_vcodec_enc_pdata mt8195_pdata = { 431 .uses_ext = true, 432 .capture_formats = mtk_video_formats_capture_h264, 433 .num_capture_formats = ARRAY_SIZE(mtk_video_formats_capture_h264), 434 .output_formats = mtk_video_formats_output, 435 .num_output_formats = ARRAY_SIZE(mtk_video_formats_output), 436 .min_bitrate = 64, 437 .max_bitrate = 100000000, 438 .core_id = VENC_SYS, 439}; 440 441static const struct of_device_id mtk_vcodec_enc_match[] = { 442 {.compatible = "mediatek,mt8173-vcodec-enc", 443 .data = &mt8173_avc_pdata}, 444 {.compatible = "mediatek,mt8173-vcodec-enc-vp8", 445 .data = &mt8173_vp8_pdata}, 446 {.compatible = "mediatek,mt8183-vcodec-enc", .data = &mt8183_pdata}, 447 {.compatible = "mediatek,mt8188-vcodec-enc", .data = &mt8188_pdata}, 448 {.compatible = "mediatek,mt8192-vcodec-enc", .data = &mt8192_pdata}, 449 {.compatible = "mediatek,mt8195-vcodec-enc", .data = &mt8195_pdata}, 450 {}, 451}; 452MODULE_DEVICE_TABLE(of, mtk_vcodec_enc_match); 453 454static int mtk_vcodec_enc_remove(struct platform_device *pdev) 455{ 456 struct mtk_vcodec_dev *dev = platform_get_drvdata(pdev); 457 458 mtk_v4l2_debug_enter(); 459 destroy_workqueue(dev->encode_workqueue); 460 if (dev->m2m_dev_enc) 461 v4l2_m2m_release(dev->m2m_dev_enc); 462 463 if (dev->vfd_enc) 464 video_unregister_device(dev->vfd_enc); 465 466 v4l2_device_unregister(&dev->v4l2_dev); 467 pm_runtime_disable(dev->pm.dev); 468 mtk_vcodec_fw_release(dev->fw_handler); 469 return 0; 470} 471 472static struct platform_driver mtk_vcodec_enc_driver = { 473 .probe = mtk_vcodec_probe, 474 .remove = mtk_vcodec_enc_remove, 475 .driver = { 476 .name = MTK_VCODEC_ENC_NAME, 477 .of_match_table = mtk_vcodec_enc_match, 478 }, 479}; 480 481module_platform_driver(mtk_vcodec_enc_driver); 482 483 484MODULE_LICENSE("GPL v2"); 485MODULE_DESCRIPTION("Mediatek video codec V4L2 encoder driver");