diff options
Diffstat (limited to 'drivers/staging/most/dim2/dim2.c')
-rw-r--r-- | drivers/staging/most/dim2/dim2.c | 115 |
1 files changed, 70 insertions, 45 deletions
diff --git a/drivers/staging/most/dim2/dim2.c b/drivers/staging/most/dim2/dim2.c index 093ef9a2b291..bd102329d8c8 100644 --- a/drivers/staging/most/dim2/dim2.c +++ b/drivers/staging/most/dim2/dim2.c @@ -108,6 +108,7 @@ struct dim2_hdm { struct dim2_platform_data { int (*enable)(struct platform_device *pdev); void (*disable)(struct platform_device *pdev); + u8 fcnt; }; #define iface_to_hdm(iface) container_of(iface, struct dim2_hdm, most_iface) @@ -117,7 +118,8 @@ struct dim2_platform_data { (((p)[1] == 0x18) && ((p)[2] == 0x05) && ((p)[3] == 0x0C) && \ ((p)[13] == 0x3C) && ((p)[14] == 0x00) && ((p)[15] == 0x0A)) -bool dim2_sysfs_get_state_cb(void) +static ssize_t state_show(struct device *dev, struct device_attribute *attr, + char *buf) { bool state; unsigned long flags; @@ -126,9 +128,18 @@ bool dim2_sysfs_get_state_cb(void) state = dim_get_lock_state(); spin_unlock_irqrestore(&dim_lock, flags); - return state; + return sysfs_emit(buf, "%s\n", state ? "locked" : ""); } +static DEVICE_ATTR_RO(state); + +static struct attribute *dim2_attrs[] = { + &dev_attr_state.attr, + NULL, +}; + +ATTRIBUTE_GROUPS(dim2); + /** * dimcb_on_error - callback from HAL to report miscommunication between * HDM and HAL @@ -716,6 +727,23 @@ static int get_dim2_clk_speed(const char *clock_speed, u8 *val) return -EINVAL; } +static void dim2_release(struct device *d) +{ + struct dim2_hdm *dev = container_of(d, struct dim2_hdm, dev); + unsigned long flags; + + kthread_stop(dev->netinfo_task); + + spin_lock_irqsave(&dim_lock, flags); + dim_shutdown(); + spin_unlock_irqrestore(&dim_lock, flags); + + if (dev->disable_platform) + dev->disable_platform(to_platform_device(d->parent)); + + kfree(dev); +} + /* * dim2_probe - dim2 probe handler * @pdev: platform device structure @@ -732,11 +760,12 @@ static int dim2_probe(struct platform_device *pdev) struct resource *res; int ret, i; u8 hal_ret; + u8 dev_fcnt = fcnt; int irq; enum { MLB_INT_IDX, AHB0_INT_IDX }; - dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); + dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (!dev) return -ENOMEM; @@ -748,30 +777,38 @@ static int dim2_probe(struct platform_device *pdev) "microchip,clock-speed", &clock_speed); if (ret) { dev_err(&pdev->dev, "missing dt property clock-speed\n"); - return ret; + goto err_free_dev; } ret = get_dim2_clk_speed(clock_speed, &dev->clk_speed); if (ret) { dev_err(&pdev->dev, "bad dt property clock-speed\n"); - return ret; + goto err_free_dev; } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); dev->io_base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(dev->io_base)) - return PTR_ERR(dev->io_base); + if (IS_ERR(dev->io_base)) { + ret = PTR_ERR(dev->io_base); + goto err_free_dev; + } of_id = of_match_node(dim2_of_match, pdev->dev.of_node); pdata = of_id->data; - ret = pdata && pdata->enable ? pdata->enable(pdev) : 0; - if (ret) - return ret; - - dev->disable_platform = pdata ? pdata->disable : NULL; + if (pdata) { + if (pdata->enable) { + ret = pdata->enable(pdev); + if (ret) + goto err_free_dev; + } + dev->disable_platform = pdata->disable; + if (pdata->fcnt) + dev_fcnt = pdata->fcnt; + } - dev_info(&pdev->dev, "sync: num of frames per sub-buffer: %u\n", fcnt); - hal_ret = dim_startup(dev->io_base, dev->clk_speed, fcnt); + dev_info(&pdev->dev, "sync: num of frames per sub-buffer: %u\n", + dev_fcnt); + hal_ret = dim_startup(dev->io_base, dev->clk_speed, dev_fcnt); if (hal_ret != DIM_NO_ERROR) { dev_err(&pdev->dev, "dim_startup failed: %d\n", hal_ret); ret = -ENODEV; @@ -857,32 +894,19 @@ static int dim2_probe(struct platform_device *pdev) dev->most_iface.request_netinfo = request_netinfo; dev->most_iface.driver_dev = &pdev->dev; dev->most_iface.dev = &dev->dev; - dev->dev.init_name = "dim2_state"; + dev->dev.init_name = dev->name; dev->dev.parent = &pdev->dev; + dev->dev.release = dim2_release; - ret = most_register_interface(&dev->most_iface); - if (ret) { - dev_err(&pdev->dev, "failed to register MOST interface\n"); - goto err_stop_thread; - } - - ret = dim2_sysfs_probe(&dev->dev); - if (ret) { - dev_err(&pdev->dev, "failed to create sysfs attribute\n"); - goto err_unreg_iface; - } + return most_register_interface(&dev->most_iface); - return 0; - -err_unreg_iface: - most_deregister_interface(&dev->most_iface); -err_stop_thread: - kthread_stop(dev->netinfo_task); err_shutdown_dim: dim_shutdown(); err_disable_platform: if (dev->disable_platform) dev->disable_platform(pdev); +err_free_dev: + kfree(dev); return ret; } @@ -896,18 +920,8 @@ err_disable_platform: static int dim2_remove(struct platform_device *pdev) { struct dim2_hdm *dev = platform_get_drvdata(pdev); - unsigned long flags; - dim2_sysfs_destroy(&dev->dev); most_deregister_interface(&dev->most_iface); - kthread_stop(dev->netinfo_task); - - spin_lock_irqsave(&dim_lock, flags); - dim_shutdown(); - spin_unlock_irqrestore(&dim_lock, flags); - - if (dev->disable_platform) - dev->disable_platform(pdev); return 0; } @@ -1047,9 +1061,19 @@ static void rcar_m3_disable(struct platform_device *pdev) enum dim2_platforms { FSL_MX6, RCAR_H2, RCAR_M3 }; static struct dim2_platform_data plat_data[] = { - [FSL_MX6] = { .enable = fsl_mx6_enable, .disable = fsl_mx6_disable }, - [RCAR_H2] = { .enable = rcar_h2_enable, .disable = rcar_h2_disable }, - [RCAR_M3] = { .enable = rcar_m3_enable, .disable = rcar_m3_disable }, + [FSL_MX6] = { + .enable = fsl_mx6_enable, + .disable = fsl_mx6_disable, + }, + [RCAR_H2] = { + .enable = rcar_h2_enable, + .disable = rcar_h2_disable, + }, + [RCAR_M3] = { + .enable = rcar_m3_enable, + .disable = rcar_m3_disable, + .fcnt = 3, + }, }; static const struct of_device_id dim2_of_match[] = { @@ -1082,6 +1106,7 @@ static struct platform_driver dim2_driver = { .driver = { .name = "hdm_dim2", .of_match_table = dim2_of_match, + .dev_groups = dim2_groups, }, }; |