mtk_vcodec_enc_drv.c (12828B)
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 134 ctx->type = MTK_INST_ENCODER; 135 ret = mtk_vcodec_enc_ctrls_setup(ctx); 136 if (ret) { 137 mtk_v4l2_err("Failed to setup controls() (%d)", 138 ret); 139 goto err_ctrls_setup; 140 } 141 ctx->m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev_enc, ctx, 142 &mtk_vcodec_enc_queue_init); 143 if (IS_ERR((__force void *)ctx->m2m_ctx)) { 144 ret = PTR_ERR((__force void *)ctx->m2m_ctx); 145 mtk_v4l2_err("Failed to v4l2_m2m_ctx_init() (%d)", 146 ret); 147 goto err_m2m_ctx_init; 148 } 149 src_vq = v4l2_m2m_get_vq(ctx->m2m_ctx, 150 V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); 151 ctx->empty_flush_buf.vb.vb2_buf.vb2_queue = src_vq; 152 mtk_vcodec_enc_set_default_params(ctx); 153 154 if (v4l2_fh_is_singular(&ctx->fh)) { 155 /* 156 * load fireware to checks if it was loaded already and 157 * does nothing in that case 158 */ 159 ret = mtk_vcodec_fw_load_firmware(dev->fw_handler); 160 if (ret < 0) { 161 /* 162 * Return 0 if downloading firmware successfully, 163 * otherwise it is failed 164 */ 165 mtk_v4l2_err("vpu_load_firmware failed!"); 166 goto err_load_fw; 167 } 168 169 dev->enc_capability = 170 mtk_vcodec_fw_get_venc_capa(dev->fw_handler); 171 mtk_v4l2_debug(0, "encoder capability %x", dev->enc_capability); 172 } 173 174 mtk_v4l2_debug(2, "Create instance [%d]@%p m2m_ctx=%p ", 175 ctx->id, ctx, ctx->m2m_ctx); 176 177 list_add(&ctx->list, &dev->ctx_list); 178 179 mutex_unlock(&dev->dev_mutex); 180 mtk_v4l2_debug(0, "%s encoder [%d]", dev_name(&dev->plat_dev->dev), 181 ctx->id); 182 return ret; 183 184 /* Deinit when failure occurred */ 185err_load_fw: 186 v4l2_m2m_ctx_release(ctx->m2m_ctx); 187err_m2m_ctx_init: 188 v4l2_ctrl_handler_free(&ctx->ctrl_hdl); 189err_ctrls_setup: 190 v4l2_fh_del(&ctx->fh); 191 v4l2_fh_exit(&ctx->fh); 192 kfree(ctx); 193 mutex_unlock(&dev->dev_mutex); 194 195 return ret; 196} 197 198static int fops_vcodec_release(struct file *file) 199{ 200 struct mtk_vcodec_dev *dev = video_drvdata(file); 201 struct mtk_vcodec_ctx *ctx = fh_to_ctx(file->private_data); 202 203 mtk_v4l2_debug(1, "[%d] encoder", ctx->id); 204 mutex_lock(&dev->dev_mutex); 205 206 v4l2_m2m_ctx_release(ctx->m2m_ctx); 207 mtk_vcodec_enc_release(ctx); 208 v4l2_fh_del(&ctx->fh); 209 v4l2_fh_exit(&ctx->fh); 210 v4l2_ctrl_handler_free(&ctx->ctrl_hdl); 211 212 list_del_init(&ctx->list); 213 kfree(ctx); 214 mutex_unlock(&dev->dev_mutex); 215 return 0; 216} 217 218static const struct v4l2_file_operations mtk_vcodec_fops = { 219 .owner = THIS_MODULE, 220 .open = fops_vcodec_open, 221 .release = fops_vcodec_release, 222 .poll = v4l2_m2m_fop_poll, 223 .unlocked_ioctl = video_ioctl2, 224 .mmap = v4l2_m2m_fop_mmap, 225}; 226 227static int mtk_vcodec_probe(struct platform_device *pdev) 228{ 229 struct mtk_vcodec_dev *dev; 230 struct video_device *vfd_enc; 231 struct resource *res; 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 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 276 if (res == NULL) { 277 dev_err(&pdev->dev, "failed to get irq resource"); 278 ret = -ENOENT; 279 goto err_res; 280 } 281 282 dev->enc_irq = platform_get_irq(pdev, 0); 283 irq_set_status_flags(dev->enc_irq, IRQ_NOAUTOEN); 284 ret = devm_request_irq(&pdev->dev, dev->enc_irq, 285 mtk_vcodec_enc_irq_handler, 286 0, pdev->name, dev); 287 if (ret) { 288 dev_err(&pdev->dev, 289 "Failed to install dev->enc_irq %d (%d) core_id (%d)", 290 dev->enc_irq, ret, dev->venc_pdata->core_id); 291 ret = -EINVAL; 292 goto err_res; 293 } 294 295 mutex_init(&dev->enc_mutex); 296 mutex_init(&dev->dev_mutex); 297 spin_lock_init(&dev->irqlock); 298 299 snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name), "%s", 300 "[MTK_V4L2_VENC]"); 301 302 ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev); 303 if (ret) { 304 mtk_v4l2_err("v4l2_device_register err=%d", ret); 305 goto err_res; 306 } 307 308 init_waitqueue_head(&dev->queue); 309 310 /* allocate video device for encoder and register it */ 311 vfd_enc = video_device_alloc(); 312 if (!vfd_enc) { 313 mtk_v4l2_err("Failed to allocate video device"); 314 ret = -ENOMEM; 315 goto err_enc_alloc; 316 } 317 vfd_enc->fops = &mtk_vcodec_fops; 318 vfd_enc->ioctl_ops = &mtk_venc_ioctl_ops; 319 vfd_enc->release = video_device_release; 320 vfd_enc->lock = &dev->dev_mutex; 321 vfd_enc->v4l2_dev = &dev->v4l2_dev; 322 vfd_enc->vfl_dir = VFL_DIR_M2M; 323 vfd_enc->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | 324 V4L2_CAP_STREAMING; 325 326 snprintf(vfd_enc->name, sizeof(vfd_enc->name), "%s", 327 MTK_VCODEC_ENC_NAME); 328 video_set_drvdata(vfd_enc, dev); 329 dev->vfd_enc = vfd_enc; 330 platform_set_drvdata(pdev, dev); 331 332 dev->m2m_dev_enc = v4l2_m2m_init(&mtk_venc_m2m_ops); 333 if (IS_ERR((__force void *)dev->m2m_dev_enc)) { 334 mtk_v4l2_err("Failed to init mem2mem enc device"); 335 ret = PTR_ERR((__force void *)dev->m2m_dev_enc); 336 goto err_enc_mem_init; 337 } 338 339 dev->encode_workqueue = 340 alloc_ordered_workqueue(MTK_VCODEC_ENC_NAME, 341 WQ_MEM_RECLAIM | 342 WQ_FREEZABLE); 343 if (!dev->encode_workqueue) { 344 mtk_v4l2_err("Failed to create encode workqueue"); 345 ret = -EINVAL; 346 goto err_event_workq; 347 } 348 349 if (of_get_property(pdev->dev.of_node, "dma-ranges", NULL)) 350 dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(34)); 351 352 ret = video_register_device(vfd_enc, VFL_TYPE_VIDEO, -1); 353 if (ret) { 354 mtk_v4l2_err("Failed to register video device"); 355 goto err_enc_reg; 356 } 357 358 mtk_v4l2_debug(0, "encoder %d registered as /dev/video%d", 359 dev->venc_pdata->core_id, vfd_enc->num); 360 361 return 0; 362 363err_enc_reg: 364 destroy_workqueue(dev->encode_workqueue); 365err_event_workq: 366 v4l2_m2m_release(dev->m2m_dev_enc); 367err_enc_mem_init: 368 video_unregister_device(vfd_enc); 369err_enc_alloc: 370 v4l2_device_unregister(&dev->v4l2_dev); 371err_res: 372 pm_runtime_disable(dev->pm.dev); 373err_enc_pm: 374 mtk_vcodec_fw_release(dev->fw_handler); 375 return ret; 376} 377 378static const struct mtk_vcodec_enc_pdata mt8173_avc_pdata = { 379 .capture_formats = mtk_video_formats_capture_h264, 380 .num_capture_formats = ARRAY_SIZE(mtk_video_formats_capture_h264), 381 .output_formats = mtk_video_formats_output, 382 .num_output_formats = ARRAY_SIZE(mtk_video_formats_output), 383 .min_bitrate = 64, 384 .max_bitrate = 60000000, 385 .core_id = VENC_SYS, 386}; 387 388static const struct mtk_vcodec_enc_pdata mt8173_vp8_pdata = { 389 .capture_formats = mtk_video_formats_capture_vp8, 390 .num_capture_formats = ARRAY_SIZE(mtk_video_formats_capture_vp8), 391 .output_formats = mtk_video_formats_output, 392 .num_output_formats = ARRAY_SIZE(mtk_video_formats_output), 393 .min_bitrate = 64, 394 .max_bitrate = 9000000, 395 .core_id = VENC_LT_SYS, 396}; 397 398static const struct mtk_vcodec_enc_pdata mt8183_pdata = { 399 .uses_ext = true, 400 .capture_formats = mtk_video_formats_capture_h264, 401 .num_capture_formats = ARRAY_SIZE(mtk_video_formats_capture_h264), 402 .output_formats = mtk_video_formats_output, 403 .num_output_formats = ARRAY_SIZE(mtk_video_formats_output), 404 .min_bitrate = 64, 405 .max_bitrate = 40000000, 406 .core_id = VENC_SYS, 407}; 408 409static const struct mtk_vcodec_enc_pdata mt8192_pdata = { 410 .uses_ext = true, 411 .capture_formats = mtk_video_formats_capture_h264, 412 .num_capture_formats = ARRAY_SIZE(mtk_video_formats_capture_h264), 413 .output_formats = mtk_video_formats_output, 414 .num_output_formats = ARRAY_SIZE(mtk_video_formats_output), 415 .min_bitrate = 64, 416 .max_bitrate = 100000000, 417 .core_id = VENC_SYS, 418}; 419 420static const struct mtk_vcodec_enc_pdata mt8195_pdata = { 421 .uses_ext = true, 422 .capture_formats = mtk_video_formats_capture_h264, 423 .num_capture_formats = ARRAY_SIZE(mtk_video_formats_capture_h264), 424 .output_formats = mtk_video_formats_output, 425 .num_output_formats = ARRAY_SIZE(mtk_video_formats_output), 426 .min_bitrate = 64, 427 .max_bitrate = 100000000, 428 .core_id = VENC_SYS, 429}; 430 431static const struct of_device_id mtk_vcodec_enc_match[] = { 432 {.compatible = "mediatek,mt8173-vcodec-enc", 433 .data = &mt8173_avc_pdata}, 434 {.compatible = "mediatek,mt8173-vcodec-enc-vp8", 435 .data = &mt8173_vp8_pdata}, 436 {.compatible = "mediatek,mt8183-vcodec-enc", .data = &mt8183_pdata}, 437 {.compatible = "mediatek,mt8192-vcodec-enc", .data = &mt8192_pdata}, 438 {.compatible = "mediatek,mt8195-vcodec-enc", .data = &mt8195_pdata}, 439 {}, 440}; 441MODULE_DEVICE_TABLE(of, mtk_vcodec_enc_match); 442 443static int mtk_vcodec_enc_remove(struct platform_device *pdev) 444{ 445 struct mtk_vcodec_dev *dev = platform_get_drvdata(pdev); 446 447 mtk_v4l2_debug_enter(); 448 destroy_workqueue(dev->encode_workqueue); 449 if (dev->m2m_dev_enc) 450 v4l2_m2m_release(dev->m2m_dev_enc); 451 452 if (dev->vfd_enc) 453 video_unregister_device(dev->vfd_enc); 454 455 v4l2_device_unregister(&dev->v4l2_dev); 456 pm_runtime_disable(dev->pm.dev); 457 mtk_vcodec_fw_release(dev->fw_handler); 458 return 0; 459} 460 461static struct platform_driver mtk_vcodec_enc_driver = { 462 .probe = mtk_vcodec_probe, 463 .remove = mtk_vcodec_enc_remove, 464 .driver = { 465 .name = MTK_VCODEC_ENC_NAME, 466 .of_match_table = mtk_vcodec_enc_match, 467 }, 468}; 469 470module_platform_driver(mtk_vcodec_enc_driver); 471 472 473MODULE_LICENSE("GPL v2"); 474MODULE_DESCRIPTION("Mediatek video codec V4L2 encoder driver");