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 v5.9 420 lines 11 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 <media/v4l2-event.h> 15#include <media/v4l2-mem2mem.h> 16#include <media/videobuf2-dma-contig.h> 17#include <linux/pm_runtime.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_vpu.h" 25 26module_param(mtk_v4l2_dbg_level, int, S_IRUGO | S_IWUSR); 27module_param(mtk_vcodec_dbg, bool, S_IRUGO | S_IWUSR); 28 29/* Wake up context wait_queue */ 30static void wake_up_ctx(struct mtk_vcodec_ctx *ctx, unsigned int reason) 31{ 32 ctx->int_cond = 1; 33 ctx->int_type = reason; 34 wake_up_interruptible(&ctx->queue); 35} 36 37static void clean_irq_status(unsigned int irq_status, void __iomem *addr) 38{ 39 if (irq_status & MTK_VENC_IRQ_STATUS_PAUSE) 40 writel(MTK_VENC_IRQ_STATUS_PAUSE, addr); 41 42 if (irq_status & MTK_VENC_IRQ_STATUS_SWITCH) 43 writel(MTK_VENC_IRQ_STATUS_SWITCH, addr); 44 45 if (irq_status & MTK_VENC_IRQ_STATUS_DRAM) 46 writel(MTK_VENC_IRQ_STATUS_DRAM, addr); 47 48 if (irq_status & MTK_VENC_IRQ_STATUS_SPS) 49 writel(MTK_VENC_IRQ_STATUS_SPS, addr); 50 51 if (irq_status & MTK_VENC_IRQ_STATUS_PPS) 52 writel(MTK_VENC_IRQ_STATUS_PPS, addr); 53 54 if (irq_status & MTK_VENC_IRQ_STATUS_FRM) 55 writel(MTK_VENC_IRQ_STATUS_FRM, addr); 56 57} 58static irqreturn_t mtk_vcodec_enc_irq_handler(int irq, void *priv) 59{ 60 struct mtk_vcodec_dev *dev = priv; 61 struct mtk_vcodec_ctx *ctx; 62 unsigned long flags; 63 void __iomem *addr; 64 65 spin_lock_irqsave(&dev->irqlock, flags); 66 ctx = dev->curr_ctx; 67 spin_unlock_irqrestore(&dev->irqlock, flags); 68 69 mtk_v4l2_debug(1, "id=%d", ctx->id); 70 addr = dev->reg_base[VENC_SYS] + MTK_VENC_IRQ_ACK_OFFSET; 71 72 ctx->irq_status = readl(dev->reg_base[VENC_SYS] + 73 (MTK_VENC_IRQ_STATUS_OFFSET)); 74 75 clean_irq_status(ctx->irq_status, addr); 76 77 wake_up_ctx(ctx, MTK_INST_IRQ_RECEIVED); 78 return IRQ_HANDLED; 79} 80 81static irqreturn_t mtk_vcodec_enc_lt_irq_handler(int irq, void *priv) 82{ 83 struct mtk_vcodec_dev *dev = priv; 84 struct mtk_vcodec_ctx *ctx; 85 unsigned long flags; 86 void __iomem *addr; 87 88 spin_lock_irqsave(&dev->irqlock, flags); 89 ctx = dev->curr_ctx; 90 spin_unlock_irqrestore(&dev->irqlock, flags); 91 92 mtk_v4l2_debug(1, "id=%d", ctx->id); 93 ctx->irq_status = readl(dev->reg_base[VENC_LT_SYS] + 94 (MTK_VENC_IRQ_STATUS_OFFSET)); 95 96 addr = dev->reg_base[VENC_LT_SYS] + MTK_VENC_IRQ_ACK_OFFSET; 97 98 clean_irq_status(ctx->irq_status, addr); 99 100 wake_up_ctx(ctx, MTK_INST_IRQ_RECEIVED); 101 return IRQ_HANDLED; 102} 103 104static void mtk_vcodec_enc_reset_handler(void *priv) 105{ 106 struct mtk_vcodec_dev *dev = priv; 107 struct mtk_vcodec_ctx *ctx; 108 109 mtk_v4l2_debug(0, "Watchdog timeout!!"); 110 111 mutex_lock(&dev->dev_mutex); 112 list_for_each_entry(ctx, &dev->ctx_list, list) { 113 ctx->state = MTK_STATE_ABORT; 114 mtk_v4l2_debug(0, "[%d] Change to state MTK_STATE_ABORT", 115 ctx->id); 116 } 117 mutex_unlock(&dev->dev_mutex); 118} 119 120static int fops_vcodec_open(struct file *file) 121{ 122 struct mtk_vcodec_dev *dev = video_drvdata(file); 123 struct mtk_vcodec_ctx *ctx = NULL; 124 int ret = 0; 125 126 ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); 127 if (!ctx) 128 return -ENOMEM; 129 130 mutex_lock(&dev->dev_mutex); 131 /* 132 * Use simple counter to uniquely identify this context. Only 133 * used for logging. 134 */ 135 ctx->id = dev->id_counter++; 136 v4l2_fh_init(&ctx->fh, video_devdata(file)); 137 file->private_data = &ctx->fh; 138 v4l2_fh_add(&ctx->fh); 139 INIT_LIST_HEAD(&ctx->list); 140 ctx->dev = dev; 141 init_waitqueue_head(&ctx->queue); 142 143 ctx->type = MTK_INST_ENCODER; 144 ret = mtk_vcodec_enc_ctrls_setup(ctx); 145 if (ret) { 146 mtk_v4l2_err("Failed to setup controls() (%d)", 147 ret); 148 goto err_ctrls_setup; 149 } 150 ctx->m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev_enc, ctx, 151 &mtk_vcodec_enc_queue_init); 152 if (IS_ERR((__force void *)ctx->m2m_ctx)) { 153 ret = PTR_ERR((__force void *)ctx->m2m_ctx); 154 mtk_v4l2_err("Failed to v4l2_m2m_ctx_init() (%d)", 155 ret); 156 goto err_m2m_ctx_init; 157 } 158 mtk_vcodec_enc_set_default_params(ctx); 159 160 if (v4l2_fh_is_singular(&ctx->fh)) { 161 /* 162 * vpu_load_firmware checks if it was loaded already and 163 * does nothing in that case 164 */ 165 ret = vpu_load_firmware(dev->vpu_plat_dev); 166 if (ret < 0) { 167 /* 168 * Return 0 if downloading firmware successfully, 169 * otherwise it is failed 170 */ 171 mtk_v4l2_err("vpu_load_firmware failed!"); 172 goto err_load_fw; 173 } 174 175 dev->enc_capability = 176 vpu_get_venc_hw_capa(dev->vpu_plat_dev); 177 mtk_v4l2_debug(0, "encoder capability %x", dev->enc_capability); 178 } 179 180 mtk_v4l2_debug(2, "Create instance [%d]@%p m2m_ctx=%p ", 181 ctx->id, ctx, ctx->m2m_ctx); 182 183 list_add(&ctx->list, &dev->ctx_list); 184 185 mutex_unlock(&dev->dev_mutex); 186 mtk_v4l2_debug(0, "%s encoder [%d]", dev_name(&dev->plat_dev->dev), 187 ctx->id); 188 return ret; 189 190 /* Deinit when failure occurred */ 191err_load_fw: 192 v4l2_m2m_ctx_release(ctx->m2m_ctx); 193err_m2m_ctx_init: 194 v4l2_ctrl_handler_free(&ctx->ctrl_hdl); 195err_ctrls_setup: 196 v4l2_fh_del(&ctx->fh); 197 v4l2_fh_exit(&ctx->fh); 198 kfree(ctx); 199 mutex_unlock(&dev->dev_mutex); 200 201 return ret; 202} 203 204static int fops_vcodec_release(struct file *file) 205{ 206 struct mtk_vcodec_dev *dev = video_drvdata(file); 207 struct mtk_vcodec_ctx *ctx = fh_to_ctx(file->private_data); 208 209 mtk_v4l2_debug(1, "[%d] encoder", ctx->id); 210 mutex_lock(&dev->dev_mutex); 211 212 mtk_vcodec_enc_release(ctx); 213 v4l2_fh_del(&ctx->fh); 214 v4l2_fh_exit(&ctx->fh); 215 v4l2_ctrl_handler_free(&ctx->ctrl_hdl); 216 v4l2_m2m_ctx_release(ctx->m2m_ctx); 217 218 list_del_init(&ctx->list); 219 kfree(ctx); 220 mutex_unlock(&dev->dev_mutex); 221 return 0; 222} 223 224static const struct v4l2_file_operations mtk_vcodec_fops = { 225 .owner = THIS_MODULE, 226 .open = fops_vcodec_open, 227 .release = fops_vcodec_release, 228 .poll = v4l2_m2m_fop_poll, 229 .unlocked_ioctl = video_ioctl2, 230 .mmap = v4l2_m2m_fop_mmap, 231}; 232 233static int mtk_vcodec_probe(struct platform_device *pdev) 234{ 235 struct mtk_vcodec_dev *dev; 236 struct video_device *vfd_enc; 237 struct resource *res; 238 int i, j, ret; 239 240 dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); 241 if (!dev) 242 return -ENOMEM; 243 244 INIT_LIST_HEAD(&dev->ctx_list); 245 dev->plat_dev = pdev; 246 247 dev->vpu_plat_dev = vpu_get_plat_device(dev->plat_dev); 248 if (dev->vpu_plat_dev == NULL) { 249 mtk_v4l2_err("[VPU] vpu device in not ready"); 250 return -EPROBE_DEFER; 251 } 252 253 vpu_wdt_reg_handler(dev->vpu_plat_dev, mtk_vcodec_enc_reset_handler, 254 dev, VPU_RST_ENC); 255 256 ret = mtk_vcodec_init_enc_pm(dev); 257 if (ret < 0) { 258 dev_err(&pdev->dev, "Failed to get mt vcodec clock source!"); 259 return ret; 260 } 261 262 for (i = VENC_SYS, j = 0; i < NUM_MAX_VCODEC_REG_BASE; i++, j++) { 263 res = platform_get_resource(pdev, IORESOURCE_MEM, j); 264 dev->reg_base[i] = devm_ioremap_resource(&pdev->dev, res); 265 if (IS_ERR((__force void *)dev->reg_base[i])) { 266 ret = PTR_ERR((__force void *)dev->reg_base[i]); 267 goto err_res; 268 } 269 mtk_v4l2_debug(2, "reg[%d] base=0x%p", i, dev->reg_base[i]); 270 } 271 272 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 273 if (res == NULL) { 274 dev_err(&pdev->dev, "failed to get irq resource"); 275 ret = -ENOENT; 276 goto err_res; 277 } 278 279 dev->enc_irq = platform_get_irq(pdev, 0); 280 ret = devm_request_irq(&pdev->dev, dev->enc_irq, 281 mtk_vcodec_enc_irq_handler, 282 0, pdev->name, dev); 283 if (ret) { 284 dev_err(&pdev->dev, "Failed to install dev->enc_irq %d (%d)", 285 dev->enc_irq, 286 ret); 287 ret = -EINVAL; 288 goto err_res; 289 } 290 291 dev->enc_lt_irq = platform_get_irq(pdev, 1); 292 ret = devm_request_irq(&pdev->dev, 293 dev->enc_lt_irq, mtk_vcodec_enc_lt_irq_handler, 294 0, pdev->name, dev); 295 if (ret) { 296 dev_err(&pdev->dev, 297 "Failed to install dev->enc_lt_irq %d (%d)", 298 dev->enc_lt_irq, ret); 299 ret = -EINVAL; 300 goto err_res; 301 } 302 303 disable_irq(dev->enc_irq); 304 disable_irq(dev->enc_lt_irq); /* VENC_LT */ 305 mutex_init(&dev->enc_mutex); 306 mutex_init(&dev->dev_mutex); 307 spin_lock_init(&dev->irqlock); 308 309 snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name), "%s", 310 "[MTK_V4L2_VENC]"); 311 312 ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev); 313 if (ret) { 314 mtk_v4l2_err("v4l2_device_register err=%d", ret); 315 goto err_res; 316 } 317 318 init_waitqueue_head(&dev->queue); 319 320 /* allocate video device for encoder and register it */ 321 vfd_enc = video_device_alloc(); 322 if (!vfd_enc) { 323 mtk_v4l2_err("Failed to allocate video device"); 324 ret = -ENOMEM; 325 goto err_enc_alloc; 326 } 327 vfd_enc->fops = &mtk_vcodec_fops; 328 vfd_enc->ioctl_ops = &mtk_venc_ioctl_ops; 329 vfd_enc->release = video_device_release; 330 vfd_enc->lock = &dev->dev_mutex; 331 vfd_enc->v4l2_dev = &dev->v4l2_dev; 332 vfd_enc->vfl_dir = VFL_DIR_M2M; 333 vfd_enc->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | 334 V4L2_CAP_STREAMING; 335 336 snprintf(vfd_enc->name, sizeof(vfd_enc->name), "%s", 337 MTK_VCODEC_ENC_NAME); 338 video_set_drvdata(vfd_enc, dev); 339 dev->vfd_enc = vfd_enc; 340 platform_set_drvdata(pdev, dev); 341 342 dev->m2m_dev_enc = v4l2_m2m_init(&mtk_venc_m2m_ops); 343 if (IS_ERR((__force void *)dev->m2m_dev_enc)) { 344 mtk_v4l2_err("Failed to init mem2mem enc device"); 345 ret = PTR_ERR((__force void *)dev->m2m_dev_enc); 346 goto err_enc_mem_init; 347 } 348 349 dev->encode_workqueue = 350 alloc_ordered_workqueue(MTK_VCODEC_ENC_NAME, 351 WQ_MEM_RECLAIM | 352 WQ_FREEZABLE); 353 if (!dev->encode_workqueue) { 354 mtk_v4l2_err("Failed to create encode workqueue"); 355 ret = -EINVAL; 356 goto err_event_workq; 357 } 358 359 ret = video_register_device(vfd_enc, VFL_TYPE_VIDEO, 1); 360 if (ret) { 361 mtk_v4l2_err("Failed to register video device"); 362 goto err_enc_reg; 363 } 364 365 mtk_v4l2_debug(0, "encoder registered as /dev/video%d", 366 vfd_enc->num); 367 368 return 0; 369 370err_enc_reg: 371 destroy_workqueue(dev->encode_workqueue); 372err_event_workq: 373 v4l2_m2m_release(dev->m2m_dev_enc); 374err_enc_mem_init: 375 video_unregister_device(vfd_enc); 376err_enc_alloc: 377 v4l2_device_unregister(&dev->v4l2_dev); 378err_res: 379 mtk_vcodec_release_enc_pm(dev); 380 return ret; 381} 382 383static const struct of_device_id mtk_vcodec_enc_match[] = { 384 {.compatible = "mediatek,mt8173-vcodec-enc",}, 385 {}, 386}; 387MODULE_DEVICE_TABLE(of, mtk_vcodec_enc_match); 388 389static int mtk_vcodec_enc_remove(struct platform_device *pdev) 390{ 391 struct mtk_vcodec_dev *dev = platform_get_drvdata(pdev); 392 393 mtk_v4l2_debug_enter(); 394 flush_workqueue(dev->encode_workqueue); 395 destroy_workqueue(dev->encode_workqueue); 396 if (dev->m2m_dev_enc) 397 v4l2_m2m_release(dev->m2m_dev_enc); 398 399 if (dev->vfd_enc) 400 video_unregister_device(dev->vfd_enc); 401 402 v4l2_device_unregister(&dev->v4l2_dev); 403 mtk_vcodec_release_enc_pm(dev); 404 return 0; 405} 406 407static struct platform_driver mtk_vcodec_enc_driver = { 408 .probe = mtk_vcodec_probe, 409 .remove = mtk_vcodec_enc_remove, 410 .driver = { 411 .name = MTK_VCODEC_ENC_NAME, 412 .of_match_table = mtk_vcodec_enc_match, 413 }, 414}; 415 416module_platform_driver(mtk_vcodec_enc_driver); 417 418 419MODULE_LICENSE("GPL v2"); 420MODULE_DESCRIPTION("Mediatek video codec V4L2 encoder driver");