int bdisp_debugfs_create(struct bdisp_dev *bdisp) { char dirname[16]; snprintf(dirname, sizeof(dirname), "%s%d", BDISP_NAME, bdisp->id); bdisp->dbg.debugfs_entry = debugfs_create_dir(dirname, NULL); if (!bdisp->dbg.debugfs_entry) goto err; if (!bdisp_dbg_create_entry(regs)) goto err; if (!bdisp_dbg_create_entry(last_nodes)) goto err; if (!bdisp_dbg_create_entry(last_nodes_raw)) goto err; if (!bdisp_dbg_create_entry(last_request)) goto err; if (!bdisp_dbg_create_entry(perf)) goto err; return 0; err: bdisp_debugfs_remove(bdisp); return -ENOMEM; }
static int bdisp_remove(struct platform_device *pdev) { struct bdisp_dev *bdisp = platform_get_drvdata(pdev); bdisp_unregister_device(bdisp); bdisp_hw_free_filters(bdisp->dev); pm_runtime_disable(&pdev->dev); bdisp_debugfs_remove(bdisp); v4l2_device_unregister(&bdisp->v4l2_dev); if (!IS_ERR(bdisp->clock)) clk_unprepare(bdisp->clock); dev_dbg(&pdev->dev, "%s driver unloaded\n", pdev->name); return 0; }
static int bdisp_probe(struct platform_device *pdev) { struct bdisp_dev *bdisp; struct resource *res; struct device *dev = &pdev->dev; int ret; dev_dbg(dev, "%s\n", __func__); bdisp = devm_kzalloc(dev, sizeof(struct bdisp_dev), GFP_KERNEL); if (!bdisp) return -ENOMEM; bdisp->pdev = pdev; bdisp->dev = dev; platform_set_drvdata(pdev, bdisp); if (dev->of_node) bdisp->id = of_alias_get_id(pdev->dev.of_node, BDISP_NAME); else bdisp->id = pdev->id; init_waitqueue_head(&bdisp->irq_queue); INIT_DELAYED_WORK(&bdisp->timeout_work, bdisp_irq_timeout); bdisp->work_queue = create_workqueue(BDISP_NAME); spin_lock_init(&bdisp->slock); mutex_init(&bdisp->lock); /* get resources */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); bdisp->regs = devm_ioremap_resource(dev, res); if (IS_ERR(bdisp->regs)) { dev_err(dev, "failed to get regs\n"); return PTR_ERR(bdisp->regs); } bdisp->clock = devm_clk_get(dev, BDISP_NAME); if (IS_ERR(bdisp->clock)) { dev_err(dev, "failed to get clock\n"); return PTR_ERR(bdisp->clock); } ret = clk_prepare(bdisp->clock); if (ret < 0) { dev_err(dev, "clock prepare failed\n"); bdisp->clock = ERR_PTR(-EINVAL); return ret; } res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (!res) { dev_err(dev, "failed to get IRQ resource\n"); goto err_clk; } ret = devm_request_threaded_irq(dev, res->start, bdisp_irq_handler, bdisp_irq_thread, IRQF_ONESHOT, pdev->name, bdisp); if (ret) { dev_err(dev, "failed to install irq\n"); goto err_clk; } /* v4l2 register */ ret = v4l2_device_register(dev, &bdisp->v4l2_dev); if (ret) { dev_err(dev, "failed to register\n"); goto err_clk; } /* Debug */ ret = bdisp_debugfs_create(bdisp); if (ret) { dev_err(dev, "failed to create debugfs\n"); goto err_v4l2; } /* Power management */ pm_runtime_enable(dev); ret = pm_runtime_get_sync(dev); if (ret < 0) { dev_err(dev, "failed to set PM\n"); goto err_dbg; } /* Filters */ if (bdisp_hw_alloc_filters(bdisp->dev)) { dev_err(bdisp->dev, "no memory for filters\n"); ret = -ENOMEM; goto err_pm; } /* Register */ ret = bdisp_register_device(bdisp); if (ret) { dev_err(dev, "failed to register\n"); goto err_filter; } dev_info(dev, "%s%d registered as /dev/video%d\n", BDISP_NAME, bdisp->id, bdisp->vdev.num); pm_runtime_put(dev); return 0; err_filter: bdisp_hw_free_filters(bdisp->dev); err_pm: pm_runtime_put(dev); err_dbg: bdisp_debugfs_remove(bdisp); err_v4l2: v4l2_device_unregister(&bdisp->v4l2_dev); err_clk: if (!IS_ERR(bdisp->clock)) clk_unprepare(bdisp->clock); return ret; }