/**
 * pm8xxx_work_handler - worker to set vibration level
 * @work: pointer to work_struct
 */
static void pm8xxx_work_handler(struct work_struct *work)
{
	struct pm8xxx_vib *vib = container_of(work, struct pm8xxx_vib, work);
	int rc;
	u8 val;

	rc = pm8xxx_vib_read_u8(vib, &val, VIB_DRV);
	if (rc < 0)
		return;

	/*
	 * pmic vibrator supports voltage ranges from 1.2 to 3.1V, so
	 * scale the level to fit into these ranges.
	 */
	if (vib->speed) {
		vib->active = true;
		vib->level = ((VIB_MAX_LEVELS * vib->speed) / MAX_FF_SPEED) +
						VIB_MIN_LEVEL_mV;
		vib->level /= 100;
	} else {
		vib->active = false;
		vib->level = VIB_MIN_LEVEL_mV / 100;
	}

	pm8xxx_vib_set(vib, vib->active);
}
static void pm8xxx_work_handler(struct work_struct *work)
{
	struct pm8xxx_vib *vib = container_of(work, struct pm8xxx_vib, work);
	int rc;
	u8 val;

	rc = pm8xxx_vib_read_u8(vib, &val, VIB_DRV);
	if (rc < 0)
		return;

	if (vib->speed) {
		vib->active = true;
		vib->level = ((VIB_MAX_LEVELS * vib->speed) / MAX_FF_SPEED) +
						VIB_MIN_LEVEL_mV;
		vib->level /= 100;
	} else {
		vib->active = false;
		vib->level = VIB_MIN_LEVEL_mV / 100;
	}

	pm8xxx_vib_set(vib, vib->active);
}
예제 #3
0
static int __devinit pm8xxx_vib_probe(struct platform_device *pdev)

{
	const struct pm8xxx_vibrator_platform_data *pdata =
						pdev->dev.platform_data;
	struct pm8xxx_vib *vib;
	u8 val;
	int rc;

	if (!pdata)
		return -EINVAL;

	if (pdata->level_mV < VIB_MIN_LEVEL_mV ||
			 pdata->level_mV > VIB_MAX_LEVEL_mV)
		return -EINVAL;

	vib = kzalloc(sizeof(*vib), GFP_KERNEL);
	if (!vib)
		return -ENOMEM;

	vib->pdata	= pdata;
	vib->level	= pdata->level_mV / 100;
	vib->dev	= &pdev->dev;

	spin_lock_init(&vib->lock);
	INIT_WORK(&vib->work, pm8xxx_vib_update);

	hrtimer_init(&vib->vib_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
	vib->vib_timer.function = pm8xxx_vib_timer_func;

	vib->timed_dev.name = "vibrator";
	vib->timed_dev.get_time = pm8xxx_vib_get_time;
	vib->timed_dev.enable = pm8xxx_vib_enable;

	__dump_vib_regs(vib, "boot_vib_default");

	/*
	 * Configure the vibrator, it operates in manual mode
	 * for timed_output framework.
	 */
	rc = pm8xxx_vib_read_u8(vib, &val, VIB_DRV);
	if (rc < 0)
		goto err_read_vib;
	val &= ~VIB_DRV_EN_MANUAL_MASK;
	rc = pm8xxx_vib_write_u8(vib, val, VIB_DRV);
	if (rc < 0)
		goto err_read_vib;

	vib->reg_vib_drv = val;

	rc = timed_output_dev_register(&vib->timed_dev);
	if (rc < 0)
		goto err_read_vib;
	rc = device_create_file(vib->timed_dev.dev, &dev_attr_voltage_level);
	if (rc < 0) {
		VIB_ERR_LOG("%s, create sysfs fail: voltage_level\n", __func__);
	}

	platform_set_drvdata(pdev, vib);
	vib_dev = vib;
	return 0;

err_read_vib:
	kfree(vib);
	return rc;
}
예제 #4
0
static int vibrator_probe(struct platform_device *pdev)
{
    int nRet, i;   /* initialized below */

#if !defined(CONFIG_MACH_LGE_L9II_OPEN_EU)
    u8 val;

    vib_dev = kzalloc(sizeof(*vib_dev), GFP_KERNEL);
    if (!vib_dev)
        return -ENOMEM;

    vib_dev->dev = &pdev->dev;
#endif

    printk("[VIBRATOR] tspdrv_probe.!!\n");

#ifdef IMPLEMENT_AS_CHAR_DRIVER
    g_nMajor = register_chrdev(0, MODULE_NAME, &fops);
    if (g_nMajor < 0) 
    {
        DbgOut((KERN_ERR "tspdrv: can't get major number.\n"));
        return g_nMajor;
    }
#else
    nRet = misc_register(&miscdev);
	if (nRet) 
    {
        DbgOut((KERN_ERR "tspdrv: misc_register failed.\n"));
		return nRet;
	}
#endif

    DbgRecorderInit(());
    ImmVibeSPI_ForceOut_Initialize();
    VibeOSKernelLinuxInitTimer();

    /* Get and concatenate device name and initialize data buffer */
    g_cchDeviceName = 0;
    for (i=0; i<NUM_ACTUATORS; i++)
    {
        char *szName = g_szDeviceName + g_cchDeviceName;
        ImmVibeSPI_Device_GetName(i, szName, VIBE_MAX_DEVICE_NAME_LENGTH);

        /* Append version information and get buffer length */
        strcat(szName, VERSION_STR);
        g_cchDeviceName += strlen(szName);

        g_SamplesBuffer[i].nIndexPlayingBuffer = -1; /* Not playing */
        g_SamplesBuffer[i].actuatorSamples[0].nBufferSize = 0;
        g_SamplesBuffer[i].actuatorSamples[1].nBufferSize = 0;
    }

#if !defined(CONFIG_MACH_LGE_L9II_OPEN_EU)
    nRet = pm8xxx_vib_read_u8(vib_dev, &val, VIB_DRV);
    if (nRet < 0)
        goto err_read_vib;

    val &= ~VIB_DRV_EN_MANUAL_MASK;
    nRet = pm8xxx_vib_write_u8(vib_dev, val, VIB_DRV);
    if (nRet < 0)
        goto err_read_vib;

    vib_dev->reg_vib_drv = val;

    return 0;

err_read_vib :
    kfree(vib_dev);
    return nRet;
#else
	return 0;
#endif
}
static int __devinit pm8xxx_vib_probe(struct platform_device *pdev)

{
	const struct pm8xxx_vibrator_platform_data *pdata =
						pdev->dev.platform_data;
	struct pm8xxx_vib *vib;
	u8 val;
	int rc;
	printk("[vibrator] %s ,probe+++++ \n",__func__ );/*Carl Chang*/

	if (!pdata)
		return -EINVAL;

	if (pdata->level_mV < VIB_MIN_LEVEL_mV ||
			 pdata->level_mV > VIB_MAX_LEVEL_mV)
		return -EINVAL;

	vib = kzalloc(sizeof(*vib), GFP_KERNEL);
	if (!vib)
		return -ENOMEM;

	vib->pdata	= pdata;
	vib->level	= pdata->level_mV / 100;
	vib->dev	= &pdev->dev;

	//spin_lock_init(&vib->lock);
	mutex_init(&vib->lock);
	/*Register PM_log*/
#ifdef CONFIG_PM_LOG
	vib->pmlog_device = pmlog_register_device(&pdev->dev);
#endif
	/*Carl Chang,20120528*/
	INIT_WORK(&vib->work, pm8xxx_vib_update);

	hrtimer_init(&vib->vib_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
	vib->vib_timer.function = pm8xxx_vib_timer_func;

	vib->timed_dev.name = "vibrator";
	vib->timed_dev.get_time = pm8xxx_vib_get_time;
	vib->timed_dev.enable = pm8xxx_vib_enable;

	__dump_vib_regs(vib, "boot_vib_default");

	/*
	 * Configure the vibrator, it operates in manual mode
	 * for timed_output framework.
	 */
	rc = pm8xxx_vib_read_u8(vib, &val, VIB_DRV);
	if (rc < 0)
		goto err_read_vib;
	val &= ~VIB_DRV_EN_MANUAL_MASK;
	rc = pm8xxx_vib_write_u8(vib, val, VIB_DRV);
	if (rc < 0)
		goto err_read_vib;

	vib->reg_vib_drv = val;

	rc = timed_output_dev_register(&vib->timed_dev);
	if (rc < 0)
		goto err_read_vib;

	//pm8xxx_vib_enable(&vib->timed_dev, pdata->initial_vibrate_ms);
	// Carl Chang, 20120829, remove initial vibrate

	platform_set_drvdata(pdev, vib);

	vib_dev = vib;

	/* Add for debugfs and fvs mode test */
	vibrator_create_debugfs_entries(vib_dev);
	vibrator_create_kernel_debuglevel_entries();
	/* Emily Jiang, 20120201 */
	printk("[vibrator] %s ,probe----- \n",__func__ );/*Carl Chang*/
	
	return 0;

err_read_vib:
	kfree(vib);
	return rc;
}
static int __devinit pm8xxx_vib_probe(struct platform_device *pdev)

{
	struct pm8xxx_vib *vib;
	struct input_dev *input_dev;
	int error;
	u8 val;

	vib = kzalloc(sizeof(*vib), GFP_KERNEL);
	input_dev = input_allocate_device();
	if (!vib || !input_dev) {
		dev_err(&pdev->dev, "couldn't allocate memory\n");
		error = -ENOMEM;
		goto err_free_mem;
	}

	INIT_WORK(&vib->work, pm8xxx_work_handler);
	vib->dev = &pdev->dev;
	vib->vib_input_dev = input_dev;

	
	error = pm8xxx_vib_read_u8(vib, &val, VIB_DRV);
	if (error < 0)
		goto err_free_mem;
	val &= ~VIB_DRV_EN_MANUAL_MASK;
	error = pm8xxx_vib_write_u8(vib, val, VIB_DRV);
	if (error < 0)
		goto err_free_mem;

	vib->reg_vib_drv = val;

	input_dev->name = "pm8xxx_vib_ffmemless";
	input_dev->id.version = 1;
	input_dev->dev.parent = &pdev->dev;
	input_dev->close = pm8xxx_vib_close;
	input_set_drvdata(input_dev, vib);
	input_set_capability(vib->vib_input_dev, EV_FF, FF_RUMBLE);

	error = input_ff_create_memless(input_dev, NULL,
					pm8xxx_vib_play_effect);
	if (error) {
		dev_err(&pdev->dev,
			"couldn't register vibrator as FF device\n");
		goto err_free_mem;
	}

	error = input_register_device(input_dev);
	if (error) {
		dev_err(&pdev->dev, "couldn't register input device\n");
		goto err_destroy_memless;
	}

	platform_set_drvdata(pdev, vib);
	return 0;

err_destroy_memless:
	input_ff_destroy(input_dev);
err_free_mem:
	input_free_device(input_dev);
	kfree(vib);

	return error;
}
예제 #7
0
static int __devinit pm8xxx_vib_probe(struct platform_device *pdev)

{
	const struct pm8xxx_vibrator_platform_data *pdata =
						pdev->dev.platform_data;
	struct pm8xxx_vib *vib;
	u8 val;
	int rc;

	if (!pdata)
		return -EINVAL;

	if (pdata->level_mV < VIB_MIN_LEVEL_mV ||
			 pdata->level_mV > VIB_MAX_LEVEL_mV)
		return -EINVAL;

	vib = kzalloc(sizeof(*vib), GFP_KERNEL);
	if (!vib)
		return -ENOMEM;

	vib->pdata	= pdata;
	vib->level	= pdata->level_mV / 100;
	vib->dev	= &pdev->dev;

	spin_lock_init(&vib->lock);
	INIT_WORK(&vib->work, pm8xxx_vib_update);

	hrtimer_init(&vib->vib_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
	vib->vib_timer.function = pm8xxx_vib_timer_func;

	vib->timed_dev.name = "vibrator";
	vib->timed_dev.get_time = pm8xxx_vib_get_time;
	vib->timed_dev.enable = pm8xxx_vib_enable;

	__dump_vib_regs(vib, "boot_vib_default");

	/*
	 * Configure the vibrator, it operates in manual mode
	 * for timed_output framework.
	 */
	rc = pm8xxx_vib_read_u8(vib, &val, VIB_DRV);
	if (rc < 0)
		goto err_read_vib;
	val &= ~VIB_DRV_EN_MANUAL_MASK;
	rc = pm8xxx_vib_write_u8(vib, val, VIB_DRV);
	if (rc < 0)
		goto err_read_vib;

	vib->reg_vib_drv = val;

	rc = timed_output_dev_register(&vib->timed_dev);
	if (rc < 0)
		goto err_read_vib;

	/*PERI-AH-VIBRATOR_Add_level_file_node-00+[ */
	vib_Level = vib->level;
	dev_info(&pdev->dev, "default vib_Level %d \n", vib_Level);
	
	/* Set voltage parameter of vibrator(corresponding to the file node /sys/class/timed_output/vibrator/level) */
	rc = device_create_file(vib->timed_dev.dev, &dev_attr_level);	
	if (rc) {
		dev_err(&pdev->dev, "dev_attr_level device_create_file failed\n");
		device_remove_file(vib->timed_dev.dev, &dev_attr_level);
	}
	/*PERI-AH-VIBRATOR_Add_level_file_node-00+[ */

	#ifdef INIT_VIB_ENABLE
	pm8xxx_vib_enable(&vib->timed_dev, pdata->initial_vibrate_ms);
	#endif

	platform_set_drvdata(pdev, vib);

	vib_dev = vib;

	return 0;

err_read_vib:
	kfree(vib);
	return rc;
}
예제 #8
0
static int __devinit pm8xxx_vib_probe(struct platform_device *pdev)

{
	const struct pm8xxx_vibrator_platform_data *pdata =
						pdev->dev.platform_data;
	struct pm8xxx_vib *vib;
	u8 val;
	int rc;

	if (!pdata)
		return -EINVAL;

	if (pdata->level_mV < VIB_MIN_LEVEL_mV ||
			 pdata->level_mV > VIB_MAX_LEVEL_mV)
		return -EINVAL;

	vib = kzalloc(sizeof(*vib), GFP_KERNEL);
	if (!vib)
		return -ENOMEM;

	vib->pdata	= pdata;
	vib->level	= pdata->level_mV / 100;
	vib->pre_value  = 0;
	vib->dev	= &pdev->dev;

	spin_lock_init(&vib->lock);
	INIT_WORK(&vib->work, pm8xxx_vib_update);

	hrtimer_init(&vib->vib_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
	vib->vib_timer.function = pm8xxx_vib_timer_func;

	vib->timed_dev.name = "vibrator";
	vib->timed_dev.get_time = pm8xxx_vib_get_time;
	vib->timed_dev.enable = pm8xxx_vib_enable;

	__dump_vib_regs(vib, "boot_vib_default");

	/*
	 * Configure the vibrator, it operates in manual mode
	 * for timed_output framework.
	 */
	rc = pm8xxx_vib_read_u8(vib, &val, VIB_DRV);
	if (rc < 0)
		goto err_read_vib;
	val &= ~VIB_DRV_EN_MANUAL_MASK;
	rc = pm8xxx_vib_write_u8(vib, val, VIB_DRV);
	if (rc < 0)
		goto err_read_vib;

	vib->reg_vib_drv = val;

	rc = timed_output_dev_register(&vib->timed_dev);
	if (rc < 0)
		goto err_read_vib;

#ifdef CONFIG_LGE_PMIC8XXX_VIBRATOR_VOL
	rc = device_create_file(vib->timed_dev.dev, &dev_attr_amp);
	if (rc < 0)
		goto err_read_vib;

	/* no vibration during initialization, [email protected], 01/02/2012 */
	//pm8xxx_vib_enable(&vib->timed_dev, pdata->initial_vibrate_ms);
#else
	pm8xxx_vib_enable(&vib->timed_dev, pdata->initial_vibrate_ms);
#endif

	platform_set_drvdata(pdev, vib);

	vib_dev = vib;

	return 0;

err_read_vib:
	kfree(vib);
	return rc;
}
예제 #9
0
static int __devinit pm8xxx_vib_probe(struct platform_device *pdev)

{
    const struct pm8xxx_vibrator_platform_data *pdata =
                        pdev->dev.platform_data;
    struct pm8xxx_vib *vib;
    u8 val;
    int rc;
    int count = 0;

    VIB_DEBUG_LOG(KERN_INFO, "called.\n");
    if (!pdata) {
        VIB_LOG(KERN_ERR, "pdata is NULL\n");
        return -EINVAL;
    }

    if (pdata->level_mV < VIB_MIN_LEVEL_mV ||
             pdata->level_mV > VIB_MAX_LEVEL_mV) {
        VIB_LOG(KERN_ERR, "level_mV error. level_mV=%d\n",
                                         pdata->level_mV);
        return -EINVAL;
    }

    vib = kzalloc(sizeof(*vib), GFP_KERNEL);
    if (!vib) {
        VIB_LOG(KERN_ERR, "kzalloc error.\n");
        return -ENOMEM;
    }

    vib->pdata  = pdata;
    vib->level  = pdata->level_mV / 100;
    vib->dev    = &pdev->dev;

    mutex_init(&vib->vib_mutex);
    for (count = 0; count < VIB_WORK_NUM; count++) {
        INIT_WORK(&(vib->vib_on_work_data[count].work_vib_on),
                                          pm8xxx_vibrator_on);
        INIT_WORK(&vib->work_vib_off[count], pm8xxx_vibrator_off);
        vib->vib_on_work_data[count].vib_time = 0;
        VIB_DEBUG_LOG(KERN_INFO, "vib_on_work_data[%d].vib_time=%d\n", count,
                                      vib->vib_on_work_data[count].vib_time);
    }

    vib->work_vib_on_pos = 0;
    vib->work_vib_off_pos = 0;

    hrtimer_init(&vib->vib_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
    vib->vib_timer.function = pm8xxx_vib_timer_func;

    vib->timed_dev.name = "vibrator";
    vib->timed_dev.get_time = pm8xxx_vib_get_time;
    vib->timed_dev.enable = pm8xxx_vib_enable;

#ifdef DEBUG_VIB_PM8XXX
    __dump_vib_regs(vib, "boot_vib_default");
#endif /* DEBUG_VIB_PM8XXX */

    /*
     * Configure the vibrator, it operates in manual mode
     * for timed_output framework.
     */
    rc = pm8xxx_vib_read_u8(vib, &val, VIB_DRV);
    if (rc < 0) {
        VIB_LOG(KERN_ERR, "pm8xxx_vib_read_u8 error. rc=%d\n", rc);
        goto err_read_vib;
    }
    val &= ~VIB_DRV_EN_MANUAL_MASK;
    rc = pm8xxx_vib_write_u8(vib, val, VIB_DRV);
    if (rc < 0) {
        VIB_LOG(KERN_ERR, "pm8xxx_vib_write_u8 error. rc=%d\n", rc);
        goto err_read_vib;
    }

    vib->reg_vib_drv = val;

    rc = timed_output_dev_register(&vib->timed_dev);
    if (rc < 0) {
        VIB_LOG(KERN_ERR, "timed_output_dev_register error. rc=%d\n", rc);
        goto err_read_vib;
    }

    platform_set_drvdata(pdev, vib);

    vib_dev = vib;

    VIB_DEBUG_LOG(KERN_INFO, "end.rc=%d\n", 0);
    return 0;

err_read_vib:
    VIB_DEBUG_LOG(KERN_INFO, "err_read_vib.\n");
    kfree(vib);
    VIB_DEBUG_LOG(KERN_INFO, "end.rc=%d\n", rc);
    return rc;
}
static int __devinit pm8xxx_vib_probe(struct platform_device *pdev)

{
	const struct pm8xxx_vibrator_platform_data *pdata =
						pdev->dev.platform_data;
	struct pm8xxx_vib *vib;
	u8 val;
	int rc;

	if (!pdata)
		return -EINVAL;

	if (pdata->level_mV < VIB_MIN_LEVEL_mV ||
			 pdata->level_mV > VIB_MAX_LEVEL_mV)
		return -EINVAL;

	vib = kzalloc(sizeof(*vib), GFP_KERNEL);
	if (!vib)
		return -ENOMEM;

	vib->pdata	= pdata;
	vib->level	= pdata->level_mV / 100;
	vib->dev	= &pdev->dev;

#ifdef CONFIG_LGE_PMIC8XXX_VIBRATOR_VOL
	vib->default_level  = vib->level;
	vib->request_level  = vib->level;
#endif

#ifdef CONFIG_LGE_PMIC8XXX_VIBRATOR_MIN_TIMEOUT
	vib->min_timeout_ms  = pdata->min_timeout_ms;
	vib->pre_value  = 0;
#endif

#ifdef CONFIG_LGE_PMIC8XXX_VIBRATOR_OVERDRIVE
	vib->overdrive_ms  = pdata->overdrive_ms;
	vib->overdrive_range_ms  = pdata->overdrive_range_ms;
#endif

#ifdef CONFIG_LGE_PMIC8XXX_VIBRATOR_REST_POWER
	vib->min_stop_ms  = pdata->min_stop_ms;
	vib->start_tv.tv_sec = 0;
	vib->start_tv.tv_usec = 0;
	vib->stop_tv.tv_sec = 0;
	vib->stop_tv.tv_usec = 0;
#endif

    vib->max_level_mv = VIB_MAX_LEVEL_mV;
    vib->min_level_mv = VIB_MIN_LEVEL_mV;

	spin_lock_init(&vib->lock);
	INIT_WORK(&vib->work, pm8xxx_vib_update);

	hrtimer_init(&vib->vib_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
	vib->vib_timer.function = pm8xxx_vib_timer_func;

#ifdef CONFIG_LGE_PMIC8XXX_VIBRATOR_OVERDRIVE
	hrtimer_init(&vib->vib_overdrive_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
	vib->vib_overdrive_timer.function = pm8xxx_vib_overdrive_timer_func;
#endif

	vib->timed_dev.name = "vibrator";
	vib->timed_dev.get_time = pm8xxx_vib_get_time;
	vib->timed_dev.enable = pm8xxx_vib_enable;

	__dump_vib_regs(vib, "boot_vib_default");

	/*
	 * Configure the vibrator, it operates in manual mode
	 * for timed_output framework.
	 */
	rc = pm8xxx_vib_read_u8(vib, &val, VIB_DRV);
	if (rc < 0)
		goto err_read_vib;
	val &= ~VIB_DRV_EN_MANUAL_MASK;
	rc = pm8xxx_vib_write_u8(vib, val, VIB_DRV);
	if (rc < 0)
		goto err_read_vib;

	vib->reg_vib_drv = val;

	rc = timed_output_dev_register(&vib->timed_dev);
	if (rc < 0)
		goto err_read_vib;

    rc = sysfs_create_group(&vib->timed_dev.dev->kobj, &pm8xxx_vib_attr_group);

#if 0

#ifdef CONFIG_LGE_PMIC8XXX_VIBRATOR_VOL
	rc = device_create_file(vib->timed_dev.dev, &dev_attr_amp);
	if (rc < 0)
		goto err_read_vib;

	rc = device_create_file(vib->timed_dev.dev, &dev_attr_default_level);
	if (rc < 0)
		goto err_read_vib;
#endif

// LGE does not use this function. power on vib effect is played at SBL3
#ifndef CONFIG_MACH_LGE
	pm8xxx_vib_enable(&vib->timed_dev, pdata->initial_vibrate_ms);
#endif

#ifdef CONFIG_LGE_PMIC8XXX_VIBRATOR_MIN_TIMEOUT
	rc = device_create_file(vib->timed_dev.dev, &dev_attr_min_ms);
	if (rc < 0)
		goto err_read_vib;
#endif

#ifdef CONFIG_LGE_PMIC8XXX_VIBRATOR_OVERDRIVE
	rc = device_create_file(vib->timed_dev.dev, &dev_attr_over_ms);
	if (rc < 0)
		goto err_read_vib;

	rc = device_create_file(vib->timed_dev.dev, &dev_attr_over_range_ms);
	if (rc < 0)
		goto err_read_vib;
#endif

#ifdef CONFIG_LGE_PMIC8XXX_VIBRATOR_REST_POWER
	rc = device_create_file(vib->timed_dev.dev, &dev_attr_min_stop_ms);
	if (rc < 0)
		goto err_read_vib;
#endif

#endif // #if 0
	platform_set_drvdata(pdev, vib);

	vib_dev = vib;

	return 0;

err_read_vib:
	kfree(vib);
	return rc;
}