static int vib_signal_init(struct vib_signal *vibs)
{
	struct vib_of_signal *of = &vibs->of;
	int ret;

	switch (of->type) {
	case SIGNAL_GPIO:
		ret = vib_ctrl_gpio_init(vibs);
		vibs->ops = &vib_ctrl_gpio_ops;
		break;
	default:
		zfprintk("%s unknown signal type %d\n", vibs->name, of->type);
		of->type = 0;
		ret = -1;
	}
	return ret;
}
static int vib_ctrl_gpio_activate(struct vib_signal *vibs)
{
	struct vib_ctrl_gpio *gpioc = &vibs->gpioc;
	struct vib_of_signal *of = &vibs->of;
	int ret;
	dvib_tprint("g+ %s\n", vibs->name);
	if (!gpioc->active_us)
		return 0;
	ret = gpio_direction_output(of->gpio, of->active_level);
	if (ret) {
		zfprintk("gpio %d output %d failed %d\n", of->gpio,
			of->active_level, ret);
		return ret;
	}
	gpioc->stage = GPIO_STAGE_ACTIVE;
	ret = hrtimer_start(&gpioc->hrtimer,
		ns_to_ktime((u64) gpioc->active_us * NSEC_PER_USEC),
		HRTIMER_MODE_REL);
	if (ret)
		dvib_tprint("started timer %p while active.\n",
				&gpioc->hrtimer);
	return 0;
}
void __init mmi_vibrator_init(void)
{
	int i, count;
	struct vibrator *vib;
	struct vib_timed *vib_timed;
	for (i = 0, count = 0; i < MAX_VIBS; i++) {
		vib = &vibrators[count];
		vib_timed = &vib_timeds[count];

		if (vib_of_init(vib, i)) {
			zfprintk("DT vibrator settings not found,"
					" using defaults\n");
			if (vib_of_init_default(vib, i))
				continue;
		}
		vib_timed->dev_data = vib;
		vib_timed->min_timeout = vib->min_us / USEC_PER_MSEC;
		vib_timed->max_timeout = vib->max_us / USEC_PER_MSEC;
		vib_timed->init = vibrator_init;
		vib_timed->exit = vibrator_exit;
		vib_timed->power_on = vibrator_power_on;
		vib_timed->power_off = vibrator_power_off;
		vib_timed->dump = vibrator_dump;
		vib_timed->name = vib_name[count];
		wake_lock_init(&vib->wakelock, WAKE_LOCK_SUSPEND,
				vib_timed->name);
		count++;
		dprintk("%s type 0x%x min %d max %d\n",
			vib_timed->name, vib->type,
			vib_timed->min_timeout, vib_timed->max_timeout);
	}
	if (count) {
		vib_timed_pdata.count = count;
		platform_device_register(&vib_timed_dev);
	}
}
static int vib_of_init(struct vibrator *vib, int vib_nr)
{
	struct device_node *node;
	const void *prop = NULL;
	int len = 0;
	char dt_path_vib[sizeof(DT_PATH_VIB) + 3];

	snprintf(dt_path_vib, sizeof(DT_PATH_VIB) + 2, "%s%1d",
		DT_PATH_VIB, vib_nr % MAX_VIBS);
	node = of_find_node_by_path(dt_path_vib);
	if (!node)
		return -ENODEV;

	prop = of_get_property(node, DT_PROP_VIB_TYPE, &len);
	if (prop && len)
		vib->type = *((int *)prop);
	else
		return -ENODEV;

	if ((vib->type != VIB_TYPE_GENENIC_ROTARY)
		&& (vib->type != VIB_TYPE_GENENIC_LINEAR))
		return -ENODEV;

	prop = of_get_property(node, VIB_EN, &len);
	if (prop && len) {
		vib->ctrl.vib_en.of = *((struct vib_of_signal *)prop);
		vib->ctrl.vib_en.name = VIB_EN;
		vib->ctrl.vib_en.signal_type = SIGNAL_ENABLE;
		if (vib_signal_init(&vib->ctrl.vib_en)) {
			zfprintk("vib_en init failed\n");
			return -ENODEV;
		}
	} else {
		zfprintk("vib_en not found in %s\n", dt_path_vib);
		return -ENODEV;
	}

	prop = of_get_property(node, "pwm", &len);
	if (prop && len) {
		int i, j = len / sizeof(struct vib_pwm);
		dprintk("pwm len %d size %d\n", len,
				len/sizeof(struct vib_pwm));
		if (j > MAX_PWMS)
			j = MAX_PWMS;
		for (i = 0; i < j; i++)
			vib->ctrl.vib_pwm[i] = *(((struct vib_pwm *)prop) + i);
	} else {
		zfprintk("pwm not found in %s\n", dt_path_vib);
		return -ENODEV;
	}

	prop = of_get_property(node, VIB_DIR, &len);
	if (prop && len) {
		vib->ctrl.vib_dir.of = *((struct vib_of_signal *)prop);
		vib->ctrl.vib_dir.name = VIB_DIR;
		vib->ctrl.vib_dir.signal_type = SIGNAL_DIRECTION;
		if (vib_signal_init(&vib->ctrl.vib_dir)) {
			zfprintk("vib_dir init failed\n");
			return -ENODEV;
		}
	} else {
		if (vib->type == VIB_TYPE_GENENIC_LINEAR) {
			zfprintk("vib_dir not found in %s\n", dt_path_vib);
			return -ENODEV;
		}
	}

	prop = of_get_property(node, "regulator", &len);
	if (prop && len) {
		strncpy(vib->reg.name, (char *)prop,
				REGULATOR_NAME_SIZE - 1);
		vib->reg.name[REGULATOR_NAME_SIZE - 1] = '\0';

		prop = of_get_property(node, "deferred_off", &len);
		if (prop && len) {
			vib->reg.deferred_off = *(u32 *)prop;
			zfprintk("deferred_off %u\n", vib->reg.deferred_off);
		}
		vib->reg.volt[0].time =  MAX_TIMEOUT;
		vib->reg.volt[0].min_uV = 2800000;
		vib->reg.volt[0].max_uV = 2800000;

		prop = of_get_property(node, "voltage", &len);
		if (prop && len) {
			int i, j = len / sizeof(struct vib_voltage);
			dprintk("voltage len %d size %d\n", len,
				len/sizeof(struct vib_voltage));
			if (j > MAX_VOLT)
				j = MAX_VOLT;
			for (i = 0; i < j; i++)
				vib->reg.volt[i] =
					*(((struct vib_voltage *)prop) + i);
		}
	}

	prop = of_get_property(node, "min", &len);
	if (prop && len)
		vib->min_us = *((unsigned int *)prop);
	else
		vib->min_us = MIN_TIMEOUT;

	prop = of_get_property(node, "max", &len);
	if (prop && len)
		vib->max_us = *((unsigned int *)prop);
	else
		vib->max_us = MAX_TIMEOUT;

	of_node_put(node);
	return 0;
}
static int vib_of_init(struct vibrator *vib, int vib_nr)
{
	struct device_node *node;
	const void *prop = NULL;
	const char *name;
	int len = 0 ;
	char dt_path_vib[sizeof(DT_PATH_VIB) + 3];

	snprintf(dt_path_vib, sizeof(DT_PATH_VIB) + 2, "%s%1d",
		DT_PATH_VIB, vib_nr % MAX_VIBS);
	node = of_find_node_by_path(dt_path_vib);
	if (!node)
		return -ENODEV;

	if (of_property_read_u32(node, DT_PROP_VIB_TYPE, &vib->type)) {
		zfprintk("DT vibrator type read error\n");
		return -ENODEV;
	}
	if ((vib->type != VIB_TYPE_GENENIC_ROTARY)
		&& (vib->type != VIB_TYPE_GENENIC_LINEAR))
		return -ENODEV;

	if (of_property_read_u32_array(node, VIB_EN,
					(u32 *)(&vib->ctrl.vib_en.of), 4)) {
		zfprintk("DT vibrator VIB_EN settings read error\n");
		return -ENODEV;
	}
	vib->ctrl.vib_en.name = VIB_EN;
	vib->ctrl.vib_en.signal_type = SIGNAL_ENABLE;
	if (vib_signal_init(&vib->ctrl.vib_en)) {
		zfprintk("vib_en init failed\n");
		return -ENODEV;
	}
	prop = of_get_property(node, "pwm", &len);
	if (prop && len) {
		int j = len / sizeof(struct vib_pwm);
		if (j > MAX_PWMS)
			j = MAX_PWMS;
		if (of_property_read_u32_array(node, "pwm",
					(u32 *)(&vib->ctrl.vib_pwm), j*4)) {
			zfprintk("DT vibrator PWM settings read error\n");
			return -ENODEV;
		}
	} else {
		zfprintk("pwm not found in %s\n", dt_path_vib);
		return -ENODEV;
	}

	if (of_property_read_u32_array(node, VIB_DIR,
					(u32 *)(&vib->ctrl.vib_dir.of), 4)) {
		zfprintk("DT vibrator VIB_DIR settings read error\n");
		if (vib->type == VIB_TYPE_GENENIC_LINEAR) {
			zfprintk("vib_dir not found in %s\n", dt_path_vib);
			return -ENODEV;
		}
	} else {
		vib->ctrl.vib_dir.name = VIB_DIR;
		vib->ctrl.vib_dir.signal_type = SIGNAL_DIRECTION;
		if (vib_signal_init(&vib->ctrl.vib_dir)) {
			zfprintk("vib_dir init failed\n");
			return -ENODEV;
		}
	}

	if (!of_property_read_string(node, "regulator", &name)) {
		strlcpy(vib->reg.name, name, sizeof(vib->reg.name));
		of_property_read_u32(node, "deferred_off",
					&vib->reg.deferred_off);
		vib->reg.volt[0].time =  MAX_TIMEOUT;
		vib->reg.volt[0].min_uV = 2800000;
		vib->reg.volt[0].max_uV = 2800000;

		prop = of_get_property(node, "voltage", &len);
		if (prop && len) {
			int j = len / sizeof(struct vib_voltage);
			if (j > MAX_VOLT)
				j = MAX_VOLT;
			of_property_read_u32_array(node, "voltage",
					(u32 *)(&vib->reg.volt), j*3);
		}
	}

	if (of_property_read_u32(node, "min", &vib->min_us))
		vib->min_us = MIN_TIMEOUT;

	if (of_property_read_u32(node, "max", &vib->max_us))
		vib->max_us = MAX_TIMEOUT;
	of_node_put(node);
	return 0;
}