Ejemplo n.º 1
0
static int resume(struct platform_device *pdev)
{
	/* Restart system timers */
	vibetonz_clk_on(&pdev->dev);
	DbgOut((KERN_DEBUG "tspdrv: %s.\n", __func__));
	return 0;
}
Ejemplo n.º 2
0
static int max77843_haptic_resume(struct platform_device *pdev)
{
	pr_info("[VIB] %s\n", __func__);
	vibetonz_clk_on(&pdev->dev, true);
	g_hap_data->resumed = true;
	return 0;
}
Ejemplo n.º 3
0
int init_module(void)
{
    int nRet, i;   /* initialized below */

#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

    nRet = platform_device_register(&platdev);
    if (nRet)
        DbgOut((KERN_ERR "tspdrv: platform_device_register failed.\n"));

    nRet = platform_driver_register(&platdrv);
    if (nRet)
        DbgOut((KERN_ERR "tspdrv: platform_driver_register failed.\n"));

    nRet = platform_driver_register(&max8997_hapticmotor_driver);
    if (nRet)
        DbgOut((KERN_ERR "tspdrv: platform_driver_register failed (hapticmotor).\n"));

    DbgRecorderInit(());

    vibetonz_clk_on(&platdev.dev);

    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;
    }

    wake_lock_init(&vib_wake_lock, WAKE_LOCK_SUSPEND, "vib_present");

    vibetonz_start();

    return 0;
}
Ejemplo n.º 4
0
static __devinit int tspdrv_probe(struct platform_device *pdev)
{
	int ret, i, rc;   /* initialized below */

	DbgOut((KERN_INFO "tspdrv: tspdrv_probe.\n"));
	motor_min_strength = g_nlra_gp_clk_n*MOTOR_MIN_STRENGTH/100;
	if(!pdev->dev.of_node){
		DbgOut(KERN_ERR "tspdrv: tspdrv probe failed, DT is NULL");
		return -ENODEV;
	}
	
	rc = tspdrv_parse_dt(pdev);
	if(rc)
		return rc;
	virt_mmss_gp0_base = ioremap(MSM_MMSS_GP0_BASE,0x28);
	if (!virt_mmss_gp0_base)
		panic("tspdrv : Unable to ioremap MSM_MMSS_GP0 memory!");

	vibrator_drvdata.power_onoff = NULL;
	vibrator_drvdata.pwm_dev = NULL;

	ret = misc_register(&miscdev);
	if (ret) {
		DbgOut((KERN_ERR "tspdrv: misc_register failed.\n"));
		iounmap(virt_mmss_gp0_base);
		return ret;
	}
	DbgRecorderInit(());

	vibetonz_clk_on(&pdev->dev);

	ImmVibeSPI_ForceOut_Initialize();
	VibeOSKernelLinuxInitTimer();

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

		/* Append version information and get buffer length */
		strlcat(szName, VERSION_STR, sizeof(VERSION_STR));
		g_cchdevice_name += strnlen(szName, sizeof(szName));

		g_samples_buffer[i].nindex_playing_buffer = -1;/* Not playing */
		g_samples_buffer[i].actuator_samples[0].nbuffer_size = 0;
		g_samples_buffer[i].actuator_samples[1].nbuffer_size = 0;
	}
	wake_lock_init(&vib_wake_lock, WAKE_LOCK_SUSPEND, "vib_present");

	vibetonz_start();

	return 0;
}
static int max77833_haptic_suspend(struct platform_device *pdev,
		pm_message_t state)
{
	struct max77833_haptic_data *data = platform_get_drvdata(pdev);
	pr_info("[VIB] %s\n", __func__);
	cancel_work_sync(&g_hap_data->work);
	hrtimer_cancel(&g_hap_data->timer);
	vibetonz_clk_on(&pdev->dev, false);
	max77833_haptic_i2c(data, false);
	return 0;
}
Ejemplo n.º 6
0
static int resume(struct platform_device *pdev)
{
	u32 __iomem *pram;

	/* Restart system timers */
	vibetonz_clk_on(&pdev->dev);

	/* Restore system timers configuration */
	pram = ioremap(S5P_PA_TIMER, 4);
	writel(0x0F00, pram);
	iounmap(pram);

	DbgOut((KERN_DEBUG "tspdrv: %s.\n", __func__));
	return 0;
}
static __devinit int tspdrv_probe(struct platform_device *pdev)
{
	int ret, i, rc;   /* initialized below */

	DbgOut((KERN_INFO "tspdrv: tspdrv_probe.\n"));
	motor_min_strength = g_nlra_gp_clk_n*MOTOR_MIN_STRENGTH/100;
	if(!pdev->dev.of_node){
		DbgOut(KERN_ERR "tspdrv: tspdrv probe failed, DT is NULL");
		return -ENODEV;
	}
	
	rc = tspdrv_parse_dt(pdev);
	if(rc)
		return rc;

#if defined(CONFIG_MACH_HLTEDCM) || defined(CONFIG_MACH_HLTEKDI) || defined(CONFIG_MACH_JS01LTEDCM)
	virt_mmss_gp1_base = ioremap(MSM_MMSS_GP3_BASE,0x28);
#elif defined(CONFIG_SEC_BERLUTI_PROJECT) || defined(CONFIG_MACH_S3VE3G_EUR)
	virt_mmss_gp1_base = ioremap(MSM_MMSS_GP0_BASE,0x28);
#else
	virt_mmss_gp1_base = ioremap(MSM_MMSS_GP1_BASE,0x28);
#endif

	if (!virt_mmss_gp1_base)
		panic("tspdrv : Unable to ioremap MSM_MMSS_GP1 memory!");
			
#if defined(CONFIG_MOTOR_DRV_MAX77803) || defined(CONFIG_MOTOR_DRV_MAX77804K) || defined(CONFIG_MOTOR_DRV_MAX77828)
	vibrator_drvdata.power_onoff = max77803_haptic_power_onoff;
#else
	vibrator_drvdata.power_onoff = NULL;
#endif
	vibrator_drvdata.pwm_dev = NULL;

#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"));
		ret = g_nmajor;
		iounmap(virt_mmss_gp1_base);
		return ret;
	}
#else
	ret = misc_register(&miscdev);
	if (ret) {
		DbgOut((KERN_ERR "tspdrv: misc_register failed.\n"));
		iounmap(virt_mmss_gp1_base);
		return ret;
	}
#endif

	DbgRecorderInit(());

	vibetonz_clk_on(&pdev->dev);

	ImmVibeSPI_ForceOut_Initialize();
	VibeOSKernelLinuxInitTimer();

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

		/* Append version information and get buffer length */
		strlcat(szName, VERSION_STR, sizeof(VERSION_STR));
		g_cchdevice_name += strnlen(szName, sizeof(szName));

		g_samples_buffer[i].nindex_playing_buffer = -1;/* Not playing */
		g_samples_buffer[i].actuator_samples[0].nbuffer_size = 0;
		g_samples_buffer[i].actuator_samples[1].nbuffer_size = 0;
	}
	wake_lock_init(&vib_wake_lock, WAKE_LOCK_SUSPEND, "vib_present");

	vibetonz_start();

	vib_dev = device_create(sec_class, NULL, 0, NULL, "vib");
	if (IS_ERR(vib_dev)) {
		pr_info("Failed to create device for samsung vib\n");
	}

	ret = sysfs_create_file(&vib_dev->kobj, &dev_attr_vib_tuning.attr);
	if (ret) {
		pr_info("Failed to create sysfs group for samsung specific led\n");
	}

	return 0;
}
static int max77833_haptic_probe(struct platform_device *pdev)
{
	int error = 0;
	struct max77833_dev *max77833 = dev_get_drvdata(pdev->dev.parent);
	struct max77833_platform_data *max77833_pdata
		= dev_get_platdata(max77833->dev);
	struct max77833_haptic_platform_data *pdata
		= max77833_pdata->haptic_data;
	struct max77833_haptic_data *hap_data;

	pr_info("[VIB] ++ %s\n", __func__);

#if defined(CONFIG_OF)
	if (pdata == NULL) {
		pdata = of_max77833_haptic_dt(&pdev->dev);
		if (!pdata) {
			pr_err("[VIB] max77833-haptic : %s not found haptic dt!\n",
					__func__);
			return -1;
		}
	}
#else
	if (pdata == NULL) {
		pr_err("[VIB] %s: no pdata\n", __func__);
		return -ENODEV;
	}
#endif /* CONFIG_OF */

	hap_data = kzalloc(sizeof(struct max77833_haptic_data), GFP_KERNEL);
	if (!hap_data) {
		pr_err("[VIB] %s: no hap_pdata\n", __func__);
		kfree(pdata);
		return -ENOMEM;
	}
	platform_set_drvdata(pdev, hap_data);
	g_hap_data = hap_data;
	hap_data->max77833 = max77833;
	hap_data->i2c = max77833->i2c;
	hap_data->pdata = pdata;

	hap_data->workqueue = create_singlethread_workqueue("hap_work");
	if (NULL == hap_data->workqueue) {
		error = -EFAULT;
		pr_err("[VIB] Failed to create workqueue, err num: %d\n", error);
		goto err_work_queue;
	}
	INIT_WORK(&(hap_data->work), haptic_work);
	spin_lock_init(&(hap_data->lock));

	hap_data->pwm = pwm_request(hap_data->pdata->pwm_id, "vibrator");
	if (IS_ERR(hap_data->pwm)) {
		error = -EFAULT;
		pr_err("[VIB] Failed to request pwm, err num: %d\n", error);
		goto err_pwm_request;
	}

	pwm_config(hap_data->pwm, pdata->period / 2, pdata->period);
	prev_duty = hap_data->pdata->period / 2;
	vibetonz_clk_on(&pdev->dev, true);

	/* hrtimer init */
	hrtimer_init(&hap_data->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
	hap_data->timer.function = haptic_timer_func;

	/* timed_output_dev init*/
	hap_data->tout_dev.name = "vibrator";
	hap_data->tout_dev.get_time = haptic_get_time;
	hap_data->tout_dev.enable = haptic_enable;

	motor_dev = sec_device_create(hap_data, "motor");
	if (IS_ERR(motor_dev)) {
		error = -ENODEV;
		pr_err("[VIB] Failed to create device\
				for samsung specific motor, err num: %d\n", error);
		goto exit_sec_devices;
	}
	error = sysfs_create_group(&motor_dev->kobj, &sec_motor_attr_group);
	if (error) {
		error = -ENODEV;
		pr_err("[VIB] Failed to create sysfs group\
				for samsung specific motor, err num: %d\n", error);
		goto exit_sysfs;
	}

#ifdef CONFIG_ANDROID_TIMED_OUTPUT
	error = timed_output_dev_register(&hap_data->tout_dev);
	if (error < 0) {
		error = -EFAULT;
		pr_err("[VIB] Failed to register timed_output : %d\n", error);
		goto err_timed_output_register;
	}
#endif

	vibtonz_en = max77833_vibtonz_en;
	vibtonz_pwm = max77833_vibtonz_pwm;
	prev_temperature_level = 1;

	/* autoresonance range setting */
	error = max77833_write_reg(hap_data->i2c,
		MAX77833_AUTORES_CONFIG, 0x00);
	if (error < 0) {
		pr_err("[VIB] %s Failed to write REG(0x%02x) [%d]\n",
				__func__, MAX77833_AUTORES_CONFIG, error);
	}

	error = max77833_write_reg(hap_data->i2c,
		MAX77833_AUTORES_MIN_FREQ_LOW, pdata->auto_res_min_low);
	if (error < 0) {
		pr_err("[VIB] %s Failed to write REG(0x%02x) [%d]\n",
				__func__, MAX77833_AUTORES_MIN_FREQ_LOW, error);
	}

	error = max77833_write_reg(hap_data->i2c,
		MAX77833_AUTORES_MAX_FREQ_LOW, pdata->auto_res_max_low);
	if (error < 0) {
		pr_err("[VIB] %s Failed to write REG(0x%02x) [%d]\n",
				__func__, MAX77833_AUTORES_MAX_FREQ_LOW, error);
	}

	error = max77833_write_reg(hap_data->i2c,
		MAX77833_AUTORES_INIT_GUESS_LOW, pdata->auto_res_init_low);
	if (error < 0) {
		pr_err("[VIB] %s Failed to write REG(0x%02x) [%d]\n",
				__func__, MAX77833_AUTORES_INIT_GUESS_LOW, error);
	}

	error = max77833_write_reg(hap_data->i2c,
		MAX77833_NOMINAL_STRENGTH, pdata->nominal_strength);
	if (error < 0) {
		pr_err("[VIB] %s Failed to write REG(0x%02x) [%d]\n",
				__func__, MAX77833_NOMINAL_STRENGTH, error);
	}

	error = max77833_write_reg(hap_data->i2c,
		MAX77833_RES_MIN_FREQ_HIGH, pdata->auto_res_min_high);
	if (error < 0) {
		pr_err("[VIB] %s Failed to write REG(0x%02x) [%d]\n",
				__func__, MAX77833_RES_MIN_FREQ_HIGH, error);
	}

	error = max77833_write_reg(hap_data->i2c,
		MAX77833_RES_MAX_FREQ_HIGH, pdata->auto_res_max_high);
	if (error < 0) {
		pr_err("[VIB] %s Failed to write REG(0x%02x) [%d]\n",
				__func__, MAX77833_RES_MAX_FREQ_HIGH, error);
	}

	error = max77833_write_reg(hap_data->i2c,
		MAX77833_AUTORES_INIT_GUESS_HIGH, pdata->auto_res_init_high);
	if (error < 0) {
		pr_err("[VIB] %s Failed to write REG(0x%02x) [%d]\n",
				__func__, MAX77833_AUTORES_INIT_GUESS_HIGH, error);
	}

	error = max77833_write_reg(hap_data->i2c,
		MAX77833_AUTORES_LOCK_WINDOW, pdata->auto_res_lock_window);
	if (error < 0) {
		pr_err("[VIB] %s Failed to write REG(0x%02x) [%d]\n",
				__func__, MAX77833_AUTORES_LOCK_WINDOW, error);
	}

	error = max77833_write_reg(hap_data->i2c,
		MAX77833_AUTORES_UPDATE_FREQ, pdata->auto_res_update_freq);
	if (error < 0) {
		pr_err("[VIB] %s Failed to write REG(0x%02x) [%d]\n",
				__func__, MAX77833_AUTORES_UPDATE_FREQ, error);
	}

	if (!pdata->auto_res_enable) {
		error = max77833_write_reg(hap_data->i2c, MAX77833_OPTION_REG1, 0x11);
		if (error < 0) {
			pr_err("[VIB] %s Failed to write REG(0x%02x) [%d]\n",
					__func__, MAX77833_OPTION_REG1, error);
		}
	}
	return error;

err_timed_output_register:
	sysfs_remove_group(&motor_dev->kobj, &sec_motor_attr_group);
exit_sysfs:
	sec_device_destroy(motor_dev->devt);
exit_sec_devices:
	pwm_free(hap_data->pwm);
err_pwm_request:
	destroy_workqueue(hap_data->workqueue);
err_work_queue:
	kfree(hap_data);
	kfree(pdata);
	g_hap_data = NULL;
	return error;
}
static int max77828_haptic_suspend(struct platform_device *pdev,
		pm_message_t state)
{
	vibetonz_clk_on(&pdev->dev, false);
	return 0;
}
static int max77828_haptic_resume(struct platform_device *pdev)
{
	vibetonz_clk_on(&pdev->dev, true);
	return 0;
}
Ejemplo n.º 11
0
static int vibrator_resume(struct platform_device *pdev)
{
	vibetonz_clk_on(&pdev->dev, true);
	return 0;
}
Ejemplo n.º 12
0
static int max77693_haptic_probe(struct platform_device *pdev)
{
	int error = 0;
	struct max77693_dev *max77693 = dev_get_drvdata(pdev->dev.parent);
	struct max77693_platform_data *max77693_pdata
		= dev_get_platdata(max77693->dev);
	struct max77693_haptic_platform_data *pdata
		= max77693_pdata->haptic_data;
	struct max77693_haptic_data *hap_data;

	pr_debug("[VIB] ++ %s\n", __func__);
	 if (pdata == NULL) {
		pr_err("%s: no pdata\n", __func__);
		return -ENODEV;
	}

	hap_data = kzalloc(sizeof(struct max77693_haptic_data), GFP_KERNEL);
	if (!hap_data)
		return -ENOMEM;

	platform_set_drvdata(pdev, hap_data);
	g_hap_data = hap_data;
	hap_data->max77693 = max77693;
	hap_data->i2c = max77693->haptic;
	hap_data->pmic_i2c = max77693->i2c;
	hap_data->pdata = pdata;

	hap_data->workqueue = create_singlethread_workqueue("hap_work");
	if (IS_ERR(hap_data->workqueue)) {
	        pr_err("[VIB] Failed to create workqueue for hap_work\n");
	        error = -EFAULT;
		goto err_create_workqueue;
	}

	INIT_WORK(&(hap_data->work), haptic_work);
	spin_lock_init(&(hap_data->lock));

	hap_data->pwm = pwm_request(hap_data->pdata->pwm_id, "vibrator");
	if (IS_ERR(hap_data->pwm)) {
		pr_err("[VIB] Failed to request pwm\n");
		error = -EFAULT;
		goto err_pwm_request;
	}
	pwm_config(hap_data->pwm, pdata->period / 2, pdata->period);

	vibetonz_clk_on(&pdev->dev, true);

	if (pdata->init_hw)
		pdata->init_hw();

	hap_data->regulator
		= regulator_get(NULL, pdata->regulator_name);

	if (IS_ERR(hap_data->regulator)) {
		pr_err("[VIB] Failed to get vmoter regulator.\n");
		error = -EFAULT;
		goto err_regulator_get;
	}

	/* hrtimer init */
	hrtimer_init(&hap_data->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
	hap_data->timer.function = haptic_timer_func;

	/* timed_output_dev init*/
	hap_data->tout_dev.name = "vibrator";
	hap_data->tout_dev.get_time = haptic_get_time;
	hap_data->tout_dev.enable = haptic_enable;

    create_vibrator_sysfs();


#ifdef CONFIG_ANDROID_TIMED_OUTPUT
	error = timed_output_dev_register(&hap_data->tout_dev);
	if (error < 0) {
		pr_err("[VIB] Failed to register timed_output : %d\n", error);
		error = -EFAULT;
		goto err_timed_output_register;
	}

	pr_err("[VIB] timed_output device is registrated\n");

	/* User controllable pwm level */
	error = device_create_file(hap_data->tout_dev.dev, &dev_attr_pwm_value);
	if (error < 0) {
		pr_err("[VIB] create sysfs fail: pwm_value\n");
	}
#endif
	pr_debug("[VIB] -- %s\n", __func__);

	return error;

err_timed_output_register:
	regulator_put(hap_data->regulator);
err_regulator_get:
	pwm_free(hap_data->pwm);
err_pwm_request:
	destroy_workqueue(hap_data->workqueue);
err_create_workqueue:
	kfree(hap_data);
	g_hap_data = NULL;
	return error;
}
Ejemplo n.º 13
0
static int __devinit vibrator_probe(struct platform_device *pdev)
{
	struct max8997_dev *max8997 = dev_get_drvdata(pdev->dev.parent);
	struct max8997_platform_data *max8997_pdata
		= dev_get_platdata(max8997->dev);
	struct max8997_motor_data *pdata = max8997_pdata->motor;
	struct vibrator_drvdata *ddata;
	int error = 0;

	ddata = kzalloc(sizeof(struct vibrator_drvdata), GFP_KERNEL);
	if (NULL == ddata) {
		pr_err("[VIB] Failed to alloc memory\n");
		error = -ENOMEM;
		goto err_free_mem;
	}

	if (pdata->init_hw)
		pdata->init_hw();
	else {
		ddata->regulator = regulator_get(NULL, "vmotor");
		if (IS_ERR(ddata->regulator)) {
			pr_err("[VIB] Failed to get vmoter regulator.\n");
			error = -EFAULT;
			goto err_regulator_get;
		}
	}

	ddata->pdata = pdata;
	ddata->dev.name = "vibrator";
	ddata->dev.get_time = vibrator_get_time;
	ddata->dev.enable = vibrator_enable;
	ddata->client = max8997->hmotor;

	platform_set_drvdata(pdev, ddata);

	hrtimer_init(&ddata->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
	ddata->timer.function = vibrator_timer_func;
	INIT_WORK(&ddata->work, vibrator_work);
	spin_lock_init(&ddata->lock);

	ddata->pwm = pwm_request(pdata->pwm_id, "vibrator");
	if (IS_ERR(ddata->pwm)) {
		pr_err("[VIB] Failed to request pwm.\n");
		error = -EFAULT;
		goto err_pwm_request;
	}
	pwm_config(ddata->pwm,
		ddata->pdata->period/2, ddata->pdata->period);

	vibetonz_clk_on(&pdev->dev, true);

	error = timed_output_dev_register(&ddata->dev);
	if (error < 0) {
		pr_err("[VIB] Failed to register timed_output : %d\n", error);
		error = -EFAULT;
		goto err_timed_output_register;
	}

	/* User controllable pwm level */
	error = device_create_file(ddata->dev.dev, &dev_attr_pwm_value);
	if (error < 0) {
		pr_err("[VIB] create sysfs fail: pwm_value\n");
	}

#ifdef CONFIG_VIBETONZ
	g_data = ddata;
	pwm_duty_max = g_data->pdata->duty;
	pwm_duty_min = pwm_duty_max/2;
	pwm_duty = (pwm_duty_min + pwm_duty_max)/2;
#endif

	return 0;

err_timed_output_register:
	timed_output_dev_unregister(&ddata->dev);
err_regulator_get:
	regulator_put(ddata->regulator);
err_pwm_request:
	pwm_free(ddata->pwm);
err_free_mem:
	kfree(ddata);
	return error;
}
Ejemplo n.º 14
0
static int max77843_haptic_probe(struct platform_device *pdev)
{
	int error = 0;
	struct max77843_dev *max77843 = dev_get_drvdata(pdev->dev.parent);
	struct max77843_platform_data *max77843_pdata
		= dev_get_platdata(max77843->dev);
	struct max77843_haptic_platform_data *pdata
		= max77843_pdata->haptic_data;
	struct max77843_haptic_data *hap_data;

	pr_info("[VIB] ++ %s\n", __func__);

#if defined(CONFIG_OF)
	if (pdata == NULL) {
		pdata = of_max77843_haptic_dt(&pdev->dev);
		if (!pdata) {
			pr_err("[VIB] max77843-haptic : %s not found haptic dt!\n",
					__func__);
			return -1;
		}
	}
#else
	if (pdata == NULL) {
		pr_err("%s: no pdata\n", __func__);
		return -ENODEV;
	}
#endif /* CONFIG_OF */

	hap_data = kzalloc(sizeof(struct max77843_haptic_data), GFP_KERNEL);
	if (!hap_data) {
		kfree(pdata);
		return -ENOMEM;
	}
	platform_set_drvdata(pdev, hap_data);
	g_hap_data = hap_data;
	hap_data->max77843 = max77843;
	hap_data->i2c = max77843->i2c;
	hap_data->pdata = pdata;

	hap_data->workqueue = create_singlethread_workqueue("hap_work");
	if (NULL == hap_data->workqueue) {
		error = -EFAULT;
		pr_err("[VIB] Failed to create workqueue, err num: %d\n", error);
		goto err_work_queue;
	}
	INIT_WORK(&(hap_data->work), haptic_work);
	spin_lock_init(&(hap_data->lock));

	hap_data->pwm = pwm_request(hap_data->pdata->pwm_id, "vibrator");
	if (IS_ERR(hap_data->pwm)) {
		error = -EFAULT;
		pr_err("[VIB] Failed to request pwm, err num: %d\n", error);
		goto err_pwm_request;
	}

	pwm_config(hap_data->pwm, pdata->period / 2, pdata->period);

	vibetonz_clk_on(&pdev->dev, true);
	if (pdata->init_hw)
		pdata->init_hw();
	else
		hap_data->regulator
			= regulator_get(NULL, pdata->regulator_name);

	if (IS_ERR(hap_data->regulator)) {
		error = -EFAULT;
		pr_err("[VIB] Failed to get vmoter regulator, err num: %d\n", error);
		goto err_regulator_get;
	}
	/* hrtimer init */
	hrtimer_init(&hap_data->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
	hap_data->timer.function = haptic_timer_func;

	/* timed_output_dev init*/
	hap_data->tout_dev.name = "vibrator";
	hap_data->tout_dev.get_time = haptic_get_time;
	hap_data->tout_dev.enable = haptic_enable;

	hap_data->resumed = false;

	motor_dev = sec_device_create(hap_data, "motor");
	if (IS_ERR(motor_dev)) {
		error = -ENODEV;
		pr_err("[VIB] Failed to create device\
				for samsung specific motor, err num: %d\n", error);
		goto exit_sec_devices;
	}
	error = sysfs_create_group(&motor_dev->kobj, &sec_motor_attr_group);
	if (error) {
		error = -ENODEV;
		pr_err("[VIB] Failed to create sysfs group\
				for samsung specific motor, err num: %d\n", error);
		goto exit_sysfs;
	}

#ifdef CONFIG_ANDROID_TIMED_OUTPUT
	error = timed_output_dev_register(&hap_data->tout_dev);
	if (error < 0) {
		error = -EFAULT;
		pr_err("[VIB] Failed to register timed_output : %d\n", error);
		goto err_timed_output_register;
	}
#endif

	pr_debug("[VIB] -- %s\n", __func__);

	return error;

err_timed_output_register:
	sysfs_remove_group(&motor_dev->kobj, &sec_motor_attr_group);
exit_sysfs:
	sec_device_destroy(motor_dev->devt);
exit_sec_devices:
	regulator_put(hap_data->regulator);
err_regulator_get:
	pwm_free(hap_data->pwm);
err_pwm_request:
	destroy_workqueue(hap_data->workqueue);
err_work_queue:
	kfree(hap_data);
	kfree(pdata);
	g_hap_data = NULL;
	return error;
}
static __devinit int tspdrv_probe(struct platform_device *pdev)
{
	struct vibrator_platform_data *pdata;
	int ret, i;   /* initialized below */

	DbgOut((KERN_INFO "tspdrv: tspdrv_probe.\n"));

	/* This condition will be removed,after all board files changes done */
	if (pdev->dev.platform_data == NULL) {
		DbgOut(KERN_ERR "tspdrv: tspdrv probe failed, pdata is NULL");
		return -EINVAL;
	} else {
		pdata = pdev->dev.platform_data;
		vibrator_drvdata.vib_model = pdata->vib_model;
		vibrator_drvdata.is_pmic_haptic_pwr_en = \
				pdata->is_pmic_haptic_pwr_en;
		if (pdata->vib_model == HAPTIC_PWM) {
			if (pdata->is_pmic_vib_pwm)
				vibrator_drvdata.vib_pwm_gpio = \
				PM8921_GPIO_PM_TO_SYS(pdata->vib_pwm_gpio);
			else
				vibrator_drvdata.vib_pwm_gpio =
					pdata->vib_pwm_gpio;
		}
		vibrator_drvdata.power_onoff = pdata->power_onoff;
	}
#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"));
		ret = g_nmajor;
		return ret;
	}
#else
	ret = misc_register(&miscdev);
	if (ret) {
		DbgOut((KERN_ERR "tspdrv: misc_register failed.\n"));
		return ret;
	}
#endif

	DbgRecorderInit(());

	vibetonz_clk_on(&pdev->dev);

	ImmVibeSPI_ForceOut_Initialize();
	VibeOSKernelLinuxInitTimer();

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

		/* Append version information and get buffer length */
		strlcat(szName, VERSION_STR, sizeof(VERSION_STR));
		g_cchdevice_name +=
			strnlen(szName, (VIBE_MAX_DEVICE_NAME_LENGTH+VERSION_STR_LEN)*NUM_ACTUATORS);

		g_samples_buffer[i].nindex_playing_buffer = -1;/* Not playing */
		g_samples_buffer[i].actuator_samples[0].nbuffer_size = 0;
		g_samples_buffer[i].actuator_samples[1].nbuffer_size = 0;
	}
	wake_lock_init(&vib_wake_lock, WAKE_LOCK_SUSPEND, "vib_present");

	vibetonz_start();

	return 0;
}
Ejemplo n.º 16
0
static __devinit int tspdrv_probe(struct platform_device *pdev)
{
	struct vibrator_platform_data *pdata;
	int ret, i;   /* initialized below */
	struct device *sec_vibetonz;

	DbgOut((KERN_INFO "tspdrv: tspdrv_probe.\n"));

	/* This condition will be removed,after all board files changes done */
	if (unlikely(pdev->dev.platform_data == NULL)) {
		DbgOut((KERN_ERR "tspdrv: can't get platform data.\n"));
		ret = -ENODATA;
		goto platform_data_err;
	} else {
		pdata = pdev->dev.platform_data;
			vibrator_drvdata.vib_en_gpio = \
				pdata->vib_en_gpio;
			vibrator_drvdata.vib_pwm_gpio = pdata->vib_pwm_gpio;

			vibrator_drvdata.vib_pwm_gpio = \
				pdata->vib_pwm_gpio;

		g_nlra_gp_clk_PreDiv = pdata->vib_pwm_PreDiv;
		g_nlra_gp_clk_m = pdata->vib_pwm_M;
		g_nlra_gp_clk_n = pdata->vib_pwm_N;
		g_nlra_gp_clk_d = pdata->vib_pwm_D;
	}
#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"));
		ret = g_nmajor;
		goto register_err;
	}
#else
	ret = misc_register(&miscdev);
	if (ret) {
		DbgOut((KERN_ERR "tspdrv: misc_register failed.\n"));
		goto register_err;
	}
#endif

	DbgRecorderInit(());

	vibetonz_clk_on(&pdev->dev);

	ImmVibeSPI_ForceOut_Initialize();
	VibeOSKernelLinuxInitTimer();

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

		/* Append version information and get buffer length */
		strncat(szName, VERSION_STR, sizeof(VERSION_STR));
		g_cchdevice_name += strnlen(szName, sizeof(szName));

		g_samples_buffer[i].nindex_playing_buffer = -1;/* Not playing */
		g_samples_buffer[i].actuator_samples[0].nbuffer_size = 0;
		g_samples_buffer[i].actuator_samples[1].nbuffer_size = 0;
	}
	wake_lock_init(&vib_wake_lock, WAKE_LOCK_SUSPEND, "vib_present");

	vib_clk = clk_get(&pdev->dev, "core_clk");
	if (IS_ERR(vib_clk))
		printk(KERN_INFO "[VIB] android vib clk failed!!!\n");
	else
		printk(KERN_INFO "[VIB] android vib clk is successful\n");

	sec_vibetonz = device_create(sec_class, NULL, 0, NULL, "sec_vibetonz");
	device_create_file(sec_vibetonz, &dev_attr_MND_M);
	device_create_file(sec_vibetonz, &dev_attr_MND_N);
	device_create_file(sec_vibetonz, &dev_attr_MND_D);
	device_create_file(sec_vibetonz, &dev_attr_MND_P);
	device_create_file(sec_vibetonz, &dev_attr_MND_SET);
	device_create_file(sec_vibetonz, &dev_attr_MND_CLK);

	vibetonz_start();

	return 0;

register_err:
#ifdef IMPLEMENT_AS_CHAR_DRIVER
	unregister_chrdev(g_nmajor, MODULE_NAME);
#else
	misc_deregister(&miscdev);
#endif
platform_data_err:
	return ret;
}
Ejemplo n.º 17
0
int init_module(void)
{
	int nRet, i;   /* initialized below */
	nRet = 0;

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

	nRet = platform_device_register(&platdev);
	if (nRet) {
		printk(KERN_ERR "tspdrv: platform_device_register failed.\n");
		goto err_platform_dev_reg;
	}

	nRet = platform_driver_register(&platdrv);
	if (nRet) {
		printk(KERN_ERR "tspdrv: platform_driver_register failed.\n");
		goto err_platform_drv_reg;
	}

	DbgRecorderInit(());

	vibetonz_clk_on(&platdev.dev);

	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;
	}

	wake_lock_init(&vib_wake_lock, WAKE_LOCK_SUSPEND, "vib_present");

#ifdef CONFIG_FEATURE_TGS2
	if (device_create_file(&platdev.dev, &dev_attr_vibrator_level_max) < 0) {
		printk(KERN_ERR "Failed to create device file(%s)!\n", dev_attr_vibrator_level_max.attr.name);
	}
	if (device_create_file(&platdev.dev, &dev_attr_vibrator_level) < 0) {
		printk(KERN_ERR "Failed to create device file(%s)!\n", dev_attr_vibrator_level.attr.name);
	}
#endif

	return 0;

err_platform_drv_reg:
	platform_device_unregister(&platdev);
err_platform_dev_reg:
#ifdef IMPLEMENT_AS_CHAR_DRIVER
	unregister_chrdev(g_nMajor, MODULE_NAME);
#else
	misc_deregister(&miscdev);
#endif
	return nRet;
}
Ejemplo n.º 18
0
static int vibrator_suspend(struct platform_device *pdev,
			pm_message_t state)
{
	vibetonz_clk_on(&pdev->dev, false);
	return 0;
}
static int max77828_haptic_probe(struct platform_device *pdev)
{
	int error = 0;
	struct max77828_dev *max77828 = dev_get_drvdata(pdev->dev.parent);
	struct max77828_platform_data *max77828_pdata
		= dev_get_platdata(max77828->dev);
	struct max77828_haptic_platform_data *pdata
		= max77828_pdata->haptic_data;
	struct max77828_haptic_data *hap_data;

	pr_info("[VIB] ++ %s\n", __func__);

#if defined(CONFIG_OF)
	if (pdata == NULL) {
		pdata = of_max77828_haptic_dt(&pdev->dev);
		if (!pdata) {
			pr_err("[VIB] max77828-haptic : %s not found haptic dt!\n",
					__func__);
			return -1;
		}
	}
#else
	if (pdata == NULL) {
		pr_err("%s: no pdata\n", __func__);
		return -ENODEV;
	}
#endif /* CONFIG_OF */

	hap_data = kzalloc(sizeof(struct max77828_haptic_data), GFP_KERNEL);
	if (!hap_data)
		return -ENOMEM;

	platform_set_drvdata(pdev, hap_data);
	g_hap_data = hap_data;
	hap_data->max77828 = max77828;
	hap_data->i2c = max77828->i2c;
	hap_data->pdata = pdata;

	hap_data->workqueue = create_singlethread_workqueue("hap_work");
	INIT_WORK(&(hap_data->work), haptic_work);
	spin_lock_init(&(hap_data->lock));

	hap_data->pwm = pwm_request(hap_data->pdata->pwm_id, "vibrator");
	if (IS_ERR(hap_data->pwm)) {
		pr_err("[VIB] Failed to request pwm\n");
		error = -EFAULT;
		goto err_pwm_request;
	}

	pwm_config(hap_data->pwm, pdata->period / 2, pdata->period);
	prev_duty = pdata->period / 2;

	vibetonz_clk_on(&pdev->dev, true);
	if (pdata->init_hw)
		pdata->init_hw();
	else
		hap_data->regulator
			= regulator_get(NULL, pdata->regulator_name);

	if (IS_ERR(hap_data->regulator)) {
		pr_err("[VIB] Failed to get vmoter regulator.\n");
		error = -EFAULT;
		goto err_regulator_get;
	}
	/* hrtimer init */
	hrtimer_init(&hap_data->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
	hap_data->timer.function = haptic_timer_func;

	/* timed_output_dev init*/
	hap_data->tout_dev.name = "vibrator";
	hap_data->tout_dev.get_time = haptic_get_time;
	hap_data->tout_dev.enable = haptic_enable;

#ifdef CONFIG_ANDROID_TIMED_OUTPUT
	error = timed_output_dev_register(&hap_data->tout_dev);
	if (error < 0) {
		pr_err("[VIB] Failed to register timed_output : %d\n", error);
		error = -EFAULT;
		goto err_timed_output_register;
	}
#endif

	pr_debug("[VIB] -- %s\n", __func__);

	return error;

err_timed_output_register:
	regulator_put(hap_data->regulator);
err_regulator_get:
	pwm_free(hap_data->pwm);
err_pwm_request:
	kfree(hap_data);
	g_hap_data = NULL;
	return error;
}
Ejemplo n.º 20
0
static __devinit int tspdrv_probe(struct platform_device *pdev)
{
	struct vibrator_platform_data *pdata;
	int ret, i;   /* initialized below */

	DbgOut((KERN_INFO "tspdrv: tspdrv_probe.\n"));

	/* This condition will be removed,after all board files changes done */
	if (pdev->dev.platform_data == NULL) {
		vibrator_drvdata.is_pmic_vib_en = 0;
#if defined(CONFIG_MACH_M2_ATT) || defined(CONFIG_MACH_M2_VZW) || \
defined(CONFIG_MACH_M2_SPR) || defined(CONFIG_MACH_M2_DCM) || \
defined(CONFIG_MACH_M2_SKT) || defined(CONFIG_MACH_JAGUAR) || \
defined(CONFIG_MACH_AEGIS2) || defined(CONFIG_MACH_COMANCHE)
		vibrator_drvdata.vib_pwm_gpio = GPIO_VIB_PWM;
		vibrator_drvdata.vib_en_gpio = GPIO_VIB_ON;
		vibrator_drvdata.haptic_pwr_en_gpio = GPIO_HAPTIC_PWR_EN;
		vibrator_drvdata.vib_model = HAPTIC_PWM;
#endif
#if defined(CONFIG_MACH_APEXQ) || defined(CONFIG_MACH_JASPER) || \
defined(CONFIG_MACH_GOGH) || defined(CONFIG_MACH_ESPRESSO_ATT)
		vibrator_drvdata.vib_pwm_gpio = GPIO_MOTOR_EN;
		vibrator_drvdata.vib_en_gpio = GPIO_MOTOR_EN;
		vibrator_drvdata.haptic_pwr_en_gpio = GPIO_MOTOR_EN;
		vibrator_drvdata.vib_model = HAPTIC_MOTOR;
#endif
#ifdef CONFIG_MACH_M2_ATT
		if (system_rev >= BOARD_REV04) {
			vibrator_drvdata.vib_en_gpio = PM8921_GPIO_PM_TO_SYS(\
						PMIC_GPIO_VIB_ON);
			vibrator_drvdata.is_pmic_vib_en = 1;
		}
		if (system_rev >= BOARD_REV08) {
			vibrator_drvdata.haptic_pwr_en_gpio = PM8921_GPIO_PM_TO_SYS(\
						PMIC_GPIO_HAPTIC_PWR_EN);
			vibrator_drvdata.is_pmic_haptic_pwr_en = 1;
		}
#endif
#ifdef CONFIG_MACH_M2_VZW
		if (system_rev >= BOARD_REV09) {
			vibrator_drvdata.vib_en_gpio = PM8921_GPIO_PM_TO_SYS(\
						PMIC_GPIO_VIB_ON);
			vibrator_drvdata.is_pmic_vib_en = 1;
		}
#endif
#ifdef CONFIG_MACH_M2_SPR
	if (system_rev >= BOARD_REV03) {
			vibrator_drvdata.vib_en_gpio = PM8921_GPIO_PM_TO_SYS(\
						PMIC_GPIO_VIB_ON);
			vibrator_drvdata.is_pmic_vib_en = 1;
		}
#endif
#ifdef CONFIG_MACH_M2_DCM
	if (system_rev >= BOARD_REV01) {
			vibrator_drvdata.vib_en_gpio = PM8921_GPIO_PM_TO_SYS(\
						PMIC_GPIO_VIB_ON);
			vibrator_drvdata.is_pmic_vib_en = 1;
		}
#endif
#ifdef CONFIG_MACH_AEGIS2
	if (system_rev >= BOARD_REV01) {
			vibrator_drvdata.vib_en_gpio = PM8921_GPIO_PM_TO_SYS(\
						PMIC_GPIO_VIB_ON);
			vibrator_drvdata.is_pmic_vib_en = 1;
		}
#endif
	} else {
		pdata = pdev->dev.platform_data;
		vibrator_drvdata.vib_model = pdata->vib_model;
		vibrator_drvdata.is_pmic_haptic_pwr_en = \
						pdata->is_pmic_haptic_pwr_en;
		if (pdata->is_pmic_haptic_pwr_en)
			vibrator_drvdata.haptic_pwr_en_gpio = \
			PM8921_GPIO_PM_TO_SYS(pdata->haptic_pwr_en_gpio);
		else
			vibrator_drvdata.haptic_pwr_en_gpio = \
				pdata->haptic_pwr_en_gpio;
		if (pdata->vib_model == HAPTIC_PWM) {
			vibrator_drvdata.vib_pwm_gpio = pdata->vib_pwm_gpio;
			vibrator_drvdata.is_pmic_vib_en = \
				pdata->is_pmic_vib_en;
			if (pdata->is_pmic_vib_en)
				vibrator_drvdata.vib_en_gpio = \
				PM8921_GPIO_PM_TO_SYS(pdata->vib_en_gpio);
			else
				vibrator_drvdata.vib_en_gpio = \
						pdata->vib_en_gpio;
		}
	}
#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"));
		ret = g_nmajor;
		goto register_err;
	}
#else
	ret = misc_register(&miscdev);
	if (ret) {
		DbgOut((KERN_ERR "tspdrv: misc_register failed.\n"));
		goto register_err;
	}
#endif

	DbgRecorderInit(());

	vibetonz_clk_on(&pdev->dev);

	ImmVibeSPI_ForceOut_Initialize();
	VibeOSKernelLinuxInitTimer();

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

		/* Append version information and get buffer length */
		strncat(szName, VERSION_STR, sizeof(VERSION_STR));
		g_cchdevice_name += strnlen(szName, sizeof(szName));

		g_samples_buffer[i].nindex_playing_buffer = -1;/* Not playing */
		g_samples_buffer[i].actuator_samples[0].nbuffer_size = 0;
		g_samples_buffer[i].actuator_samples[1].nbuffer_size = 0;
	}
	wake_lock_init(&vib_wake_lock, WAKE_LOCK_SUSPEND, "vib_present");

	vibetonz_start();

	return 0;

register_err:
#ifdef IMPLEMENT_AS_CHAR_DRIVER
	unregister_chrdev(g_nmajor, MODULE_NAME);
#else
	misc_deregister(&miscdev);
#endif

	return ret;
}
Ejemplo n.º 21
0
int init_module(void)
{
    int nRet, i;   /* initialized below */

	nRet = 0;

	if (system_rev < 0x5){
		pr_notice("%s : Vibrator  not support HW Rev =[%d] !!!\n",__func__,system_rev);
		return 0;
	}

	DbgOut((KERN_INFO "tspdrv: init_module.\n"));

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

	nRet = platform_device_register(&platdev);
	if (nRet) {
		printk(KERN_ERR "tspdrv: platform_device_register failed.\n");
		goto err_platform_dev_reg;
	}

	nRet = platform_driver_register(&platdrv);
	if (nRet) {
		printk(KERN_ERR "tspdrv: platform_driver_register failed.\n");
		goto err_platform_drv_reg;
	}

	DbgRecorderInit(());

	vibetonz_clk_on(&platdev.dev);

	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;
	}

    return 0;
err_platform_drv_reg:
	platform_device_unregister(&platdev);
err_platform_dev_reg:
#ifdef IMPLEMENT_AS_CHAR_DRIVER
	unregister_chrdev(g_nMajor, MODULE_NAME);
#else
	misc_deregister(&miscdev);
#endif
	return nRet;
}