예제 #1
0
static int AMI304_SetMode(int newmode)
{
	int mode = 0;

	read_lock(&ami304_data.lock);
	mode = ami304_data.mode;
	read_unlock(&ami304_data.lock);

	if (mode == newmode)
		return 0;

	return AMI304_Init(newmode);
}
예제 #2
0
static int ami304_resume(struct device *device)
{
	struct ecom_platform_data* ecom_pdata;
	ecom_pdata = ami304_i2c_client->dev.platform_data;

	if (AMI304_DEBUG_FUNC_TRACE & ami304_debug_mask)
		AMID("AMI304 resume....!\n");

	ecom_pdata->power(1);
	AMI304_Init(ami304_data.mode);

	return 0;
}
예제 #3
0
/**
 * All the device spefic initializations happen here.
 */
static NvS32 __init ami304_probe(struct platform_device *pdev)
{

	struct i2c_client *new_client = ami304_i2c_client;
	struct tegra_compass_device_data *compass = NULL;
	struct input_dev *input_dev = NULL;
	struct device *dev = &pdev->dev;
	NvS32 err;

#if DEBUG_AMI304
	printk("[%s:%d] Compass Sensor \n", __FUNCTION__, __LINE__);
#endif
	compass = kzalloc(sizeof(*compass), GFP_KERNEL);
	if (compass == NULL) {
		err = -ENOMEM;
		pr_err("ami304_probe: Failed to memory\n");
		goto allocate_dev_fail;
	}
	compass_dev = compass;


	input_dev = input_allocate_device();
	if (input_dev == NULL) {
		err = -ENOMEM;
		pr_err("tegra_com_ami304_probe: Failed to allocate input device\n");
		goto allocate_dev_fail;
	}
	compass_dev->input_dev 	= input_dev;


	err = open_def_odm_compass();
	if (!err) {
		pr_err("open_def_odm_comp: Failed \n");
		goto exit_alloc_data_failed;
	}
	msleep(1);
	//	mdelay(50); //to waiting time(50ms) from PowerOFF to Stand-by
	//On soft reset
	AMI304_Reset_Init();

	AMI304_Init(AMI304_FORCE_MODE); // default is Force State
#if DEBUG_AMI304
	printk("[%s:%d] Compass Sensor: AMI304 registered driver! \n", __FUNCTION__, __LINE__);
#endif

	err = misc_register(&ami304_device);
	if (err) {
		printk(KERN_ERR
				"ami304_device register failed\n");
		goto exit_misc_device_register_failed;
	}
#if 1
	platform_set_drvdata(pdev, compass);
	set_bit(EV_ABS, compass_dev->input_dev->evbit);
	/* yaw */
	input_set_abs_params(compass_dev->input_dev, ABS_RX, 0, 360, 0, 0);
	/* pitch */
	input_set_abs_params(compass_dev->input_dev, ABS_RY, -180, 180, 0, 0);
	/* roll */
	input_set_abs_params(compass_dev->input_dev, ABS_RZ, -90, 90, 0, 0);
	/* status of magnetic sensor */
	input_set_abs_params(compass_dev->input_dev, ABS_RUDDER, 0, 5, 0, 0);

	/* x-axis acceleration */
	input_set_abs_params(compass_dev->input_dev, ABS_X, -2000, 2000, 0, 0);
	/* y-axis acceleration */
	input_set_abs_params(compass_dev->input_dev, ABS_Y, -2000, 2000, 0, 0);
	/* z-axis acceleration */
	input_set_abs_params(compass_dev->input_dev, ABS_Z, -2000, 2000, 0, 0);

	/* x-axis of raw magnetic vector */
	//input_set_abs_params(compass_dev->input_dev, ABS_HAT0X, -3000, 3000, 0, 0);
	/* y-axis of raw magnetic vector */
	//input_set_abs_params(compass_dev->input_dev, ABS_HAT0Y, -3000, 3000, 0, 0);
	/* z-axis of raw magnetic vector */
	//input_set_abs_params(compass_dev->input_dev, ABS_BRAKE, -3000, 3000, 0, 0);
	/* status of acceleration sensor */
	input_set_abs_params(compass_dev->input_dev, ABS_WHEEL, 0, 5, 0, 0);

#if DEBUG_AMI304
	printk("[%s:%d] Compass Sensor \n", __FUNCTION__, __LINE__);
#endif
	compass_dev->input_dev->name = "Acompass";
	err = input_register_device(input_dev);
	if (err) {
		pr_err("tegra_compass_probe: Unable to register %s\
				input device\n", input_dev->name);
		goto exit_input_register_device_failed;
	}

	err = sysfs_create_group(&dev->kobj, &ami304_attribute_group);

#else
	platform_set_drvdata(pdev, compass);

	input_dev->name = "accelerometer_tegra";
	err = input_register_device(input_dev);
	if (err) {
		pr_err("tegra_compass_probe: Unable to register %s\
				input device\n", input_dev->name);
		goto input_register_device_failed;
	}

	err = add_sysfs_entry();
	err = sysfs_create_group(&compass_dev->input_dev, &ami304_attribute_group);
	if (err)
		printk("goto err1;\n");

#endif
	err = misc_register(&ami304daemon_device);
	if (err) {
		printk(KERN_ERR
				"ami304daemon_device register failed\n");
		goto exit_misc_device_register_failed;
	}

	err = misc_register(&ami304hal_device);
	if (err) {
		printk(KERN_ERR
				"ami304hal_device register failed\n");
		goto exit_misc_device_register_failed;
	}
#ifdef CONFIG_HAS_EARLYSUSPEND // wkkim : temporary early suspend apply
	early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
	early_suspend.suspend = compass_early_suspend;
	early_suspend.resume = compass_late_resume;
	register_early_suspend(&early_suspend);
#endif

	return 0;
exit_input_register_device_failed:
	input_free_device(compass_dev->input_dev);
exit_misc_device_register_failed:
	//exit_kfree:
	kfree(compass_dev);
allocate_dev_fail:
exit_input_dev_alloc_failed:
exit_alloc_data_failed:
	close_odm_compass();
	input_free_device(input_dev);
	kfree(compass);
	compass = 0;
	err = -ENOMEM;
exit:
	return err;
}
예제 #4
0
static int ami304_ioctl(struct inode *inode, struct file *file, unsigned int cmd,unsigned long arg)
{
	char strbuf[AMI304_BUFSIZE];
	int controlbuf[10];
	void __user *data;
	int retval=0;
	int mode=0;
#if DEBUG_AMI304
	printk(KERN_ERR  "ami304 - %s \n",__FUNCTION__);
#endif

	//check the authority is root or not
	if (!capable(CAP_SYS_ADMIN)) {
		retval = -EPERM;
		goto err_out;
	}

	switch (cmd) {
		case AMI304_IOCTL_INIT:
			read_lock(&ami304_data.lock);
			mode = ami304_data.mode;
			read_unlock(&ami304_data.lock);
			AMI304_Init(mode);
			break;

		case AMI304_IOCTL_READ_CHIPINFO:
			data = (void __user *) arg;
			if (data == NULL)
				break;
			AMI304_ReadChipInfo(strbuf, AMI304_BUFSIZE);
			if (copy_to_user(data, strbuf, strlen(strbuf) + 1)) {
				retval = -EFAULT;
				goto err_out;
			}
			break;

		case AMI304_IOCTL_READ_SENSORDATA:
			data = (void __user *) arg;
			if (data == NULL)
				break;
			AMI304_ReadSensorData(strbuf, AMI304_BUFSIZE);
			if (copy_to_user(data, strbuf, strlen(strbuf) + 1)) {
				retval = -EFAULT;
				goto err_out;
			}
			break;

		case AMI304_IOCTL_READ_POSTUREDATA:
			data = (void __user *) arg;
			if (data == NULL)
				break;
			AMI304_ReadPostureData(strbuf, AMI304_BUFSIZE);
			if (copy_to_user(data, strbuf, strlen(strbuf) + 1)) {
				retval = -EFAULT;
				goto err_out;
			}
			break;

		case AMI304_IOCTL_READ_CALIDATA:
			data = (void __user *) arg;
			if (data == NULL)
				break;
			AMI304_ReadCaliData(strbuf, AMI304_BUFSIZE);
			if (copy_to_user(data, strbuf, strlen(strbuf) + 1)) {
				retval = -EFAULT;
				goto err_out;
			}
			break;

		case AMI304_IOCTL_READ_CONTROL:
			read_lock(&ami304mid_data.ctrllock);
			memcpy(controlbuf, &ami304mid_data.controldata[0], sizeof(controlbuf));
			read_unlock(&ami304mid_data.ctrllock);
			data = (void __user *) arg;
			if (data == NULL)
				break;
			if (copy_to_user(data, controlbuf, sizeof(controlbuf))) {
				retval = -EFAULT;
				goto err_out;
			}
			break;

		case AMI304_IOCTL_SET_CONTROL:
			data = (void __user *) arg;
			if (data == NULL)
				break;
			if (copy_from_user(controlbuf, data, sizeof(controlbuf))) {
				retval = -EFAULT;
				goto err_out;
			}
			write_lock(&ami304mid_data.ctrllock);
			memcpy(&ami304mid_data.controldata[0], controlbuf, sizeof(controlbuf));
			write_unlock(&ami304mid_data.ctrllock);
			break;

		case AMI304_IOCTL_SET_MODE:
			data = (void __user *) arg;
			if (data == NULL)
				break;
			if (copy_from_user(&mode, data, sizeof(mode))) {
				retval = -EFAULT;
				goto err_out;
			}
			AMI304_SetMode(mode);
			break;

		default:
			printk(KERN_ERR "%s not supported = 0x%04x", __FUNCTION__, cmd);
			retval = -ENOIOCTLCMD;
			break;
	}

err_out:
	return retval;
}
예제 #5
0
static int __init ami304_probe(struct i2c_client *client, const struct i2c_device_id * devid)
{
	int err = 0;
	struct ami304_i2c_data *data;
	struct ecom_platform_data* ecom_pdata;

	if (AMI304_DEBUG_FUNC_TRACE & ami304_debug_mask)
		AMID("motion start....!\n");

	if(!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
		AMIE("adapter can NOT support I2C_FUNC_I2C.\n");
		return -ENODEV;
	}

	if (!(data = kmalloc(sizeof(struct ami304_i2c_data), GFP_KERNEL))) {
		err = -ENOMEM;
		goto exit;
	}
	memset(data, 0, sizeof(struct ami304_i2c_data));

	i2c_set_clientdata(client, data);
	ami304_i2c_client = client;

	ecom_pdata = ami304_i2c_client->dev.platform_data;
	ecom_pdata->power(1);
	AMI304_Init(AMI304_FORCE_MODE); // default is Force State

	atomic_set(&o_status, 0);
	atomic_set(&m_status, 0);
	atomic_set(&a_status, 0);

#if defined(CONFIG_HAS_EARLYSUSPEND)
	ami304_sensor_early_suspend.suspend = ami304_early_suspend;
	ami304_sensor_early_suspend.resume = ami304_late_resume;
	register_early_suspend(&ami304_sensor_early_suspend);

	atomic_set(&ami304_report_enabled, 1);
#endif

	data->input_dev = input_allocate_device();
	if (!data->input_dev) {
		err = -ENOMEM;
		AMIE("ami304_i2c_detect: Failed to allocate input device\n");
		goto exit_input_dev_alloc_failed;
	}

	set_bit(EV_ABS, data->input_dev->evbit);
	/* yaw */
	input_set_abs_params(data->input_dev, ABS_RX, 0, 360, 0, 0);
	/* pitch */
	input_set_abs_params(data->input_dev, ABS_RY, -180, 180, 0, 0);
	/* roll */
	input_set_abs_params(data->input_dev, ABS_RZ, -90, 90, 0, 0);
	/* status of magnetic sensor */
	input_set_abs_params(data->input_dev, ABS_RUDDER, 0, 5, 0, 0);

	/* x-axis acceleration */
	input_set_abs_params(data->input_dev, ABS_X, -2000, 2000, 0, 0);
	/* y-axis acceleration */
	input_set_abs_params(data->input_dev, ABS_Y, -2000, 2000, 0, 0);
	/* z-axis acceleration */
	input_set_abs_params(data->input_dev, ABS_Z, -2000, 2000, 0, 0);

	/* x-axis of raw magnetic vector */
	input_set_abs_params(data->input_dev, ABS_HAT0X, -3000, 3000, 0, 0);
	/* y-axis of raw magnetic vector */
	input_set_abs_params(data->input_dev, ABS_HAT0Y, -3000, 3000, 0, 0);
	/* z-axis of raw magnetic vector */
	input_set_abs_params(data->input_dev, ABS_BRAKE, -3000, 3000, 0, 0);
	/* status of acceleration sensor */
	input_set_abs_params(data->input_dev, ABS_WHEEL, 0, 5, 0, 0);

	data->input_dev->name = "Acompass";

	err = input_register_device(data->input_dev);
	if (err) {
		AMIE("ami304_i2c_detect: Unable to register input device: %s\n",
		       data->input_dev->name);
		goto exit_input_register_device_failed;
	}
	if (AMI304_DEBUG_FUNC_TRACE & ami304_debug_mask)
	        AMID("register input device successfully!!!\n");

	err = misc_register(&ami304_device);
	if (err) {
		AMIE("ami304_device register failed\n");
		goto exit_misc_device_register_failed;
	}
	err = device_create_file(&client->dev, &dev_attr_chipinfo);
	err = device_create_file(&client->dev, &dev_attr_sensordata);
	err = device_create_file(&client->dev, &dev_attr_posturedata);
	err = device_create_file(&client->dev, &dev_attr_calidata);
	err = device_create_file(&client->dev, &dev_attr_midcontrol);
	err = device_create_file(&client->dev, &dev_attr_mode);
	/* Test mode attribute */
	err = device_create_file(&client->dev, &dev_attr_pitch);
	err = device_create_file(&client->dev, &dev_attr_roll);

	err = misc_register(&ami304daemon_device);
	if (err) {
		AMIE("ami304daemon_device register failed\n");
		goto exit_misc_device_register_failed;
	}

	err = misc_register(&ami304hal_device);
	if (err) {
		AMIE("ami304hal_device register failed\n");
		goto exit_misc_device_register_failed;
	}

	return 0;
exit_misc_device_register_failed:
exit_input_register_device_failed:
	input_free_device(data->input_dev);
exit_input_dev_alloc_failed:
	kfree(data);
exit:
	return err;
}
예제 #6
0
static int ami304_ioctl(struct inode *inode, struct file *file, unsigned int cmd,unsigned long arg)
{
	char strbuf[AMI304_BUFSIZE];
	int controlbuf[10];
	void __user *data;
	int retval=0;
	int mode=0;

        //LGE_CHANGE_S, [[email protected]], 2010-12-31, <Block Root Authorization Check>
        //check the authority is root or not
        //      if(!capable(CAP_SYS_ADMIN)) {
        //        retval = -EPERM;
        //        goto err_out;
        //	}
        //LGE_CHANGE_E, [[email protected]], 2010-12-31, <Block Root Authorization Check>

	switch (cmd) {
		case AMI304_IOCTL_INIT:
			read_lock(&ami304_data.lock);
			mode = ami304_data.mode;
			read_unlock(&ami304_data.lock);
			AMI304_Init(mode);
			break;

		case AMI304_IOCTL_READ_CHIPINFO:
			data = (void __user *) arg;
			if (data == NULL)
				break;
			AMI304_ReadChipInfo(strbuf, AMI304_BUFSIZE);
			if (copy_to_user(data, strbuf, strlen(strbuf)+1)) {
				retval = -EFAULT;
				goto err_out;
			}
			break;

		case AMI304_IOCTL_READ_SENSORDATA:
			data = (void __user *) arg;
			if (data == NULL)
				break;
			AMI304_ReadSensorData(strbuf, AMI304_BUFSIZE);
			if (copy_to_user(data, strbuf, strlen(strbuf)+1)) {
				retval = -EFAULT;
				goto err_out;
			}
			break;

		case AMI304_IOCTL_READ_POSTUREDATA:
			data = (void __user *) arg;
			if (data == NULL)
				break;
			AMI304_ReadPostureData(strbuf, AMI304_BUFSIZE);
			if (copy_to_user(data, strbuf, strlen(strbuf)+1)) {
				retval = -EFAULT;
				goto err_out;
			}
			break;

	        case AMI304_IOCTL_READ_CALIDATA:
			data = (void __user *) arg;
			if (data == NULL)
				break;
			AMI304_ReadCaliData(strbuf, AMI304_BUFSIZE);
			if (copy_to_user(data, strbuf, strlen(strbuf)+1)) {
				retval = -EFAULT;
				goto err_out;
			}
	        	break;

	        case AMI304_IOCTL_READ_CONTROL:
			read_lock(&ami304mid_data.ctrllock);
			memcpy(controlbuf, &ami304mid_data.controldata[0], sizeof(controlbuf));
			read_unlock(&ami304mid_data.ctrllock);
			data = (void __user *) arg;
			if (data == NULL)
				break;
			if (copy_to_user(data, controlbuf, sizeof(controlbuf))) {
				retval = -EFAULT;
				goto err_out;
			}
	        	break;

		case AMI304_IOCTL_SET_CONTROL:
			data = (void __user *) arg;
			if (data == NULL)
				break;
			if (copy_from_user(controlbuf, data, sizeof(controlbuf))) {
				retval = -EFAULT;
				goto err_out;
			}
			write_lock(&ami304mid_data.ctrllock);
			memcpy(&ami304mid_data.controldata[0], controlbuf, sizeof(controlbuf));
			write_unlock(&ami304mid_data.ctrllock);
			break;

		case AMI304_IOCTL_SET_MODE:
			data = (void __user *) arg;
			if (data == NULL)
				break;
			if (copy_from_user(&mode, data, sizeof(mode))) {
				retval = -EFAULT;
				goto err_out;
			}
			AMI304_SetMode(mode);
			break;

		default:
			if (AMI304_DEBUG_USER_ERROR & ami304_debug_mask)
				AMIE("not supported command= 0x%04x\n", cmd);
			retval = -ENOIOCTLCMD;
			break;
	}

err_out:
	return retval;
}
static int ami304_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
	struct i2c_client *new_client;
	struct ami304_i2c_data *data;
	int err = 0;

	printk(KERN_INFO "\n\nEnter ami304_i2c_detect!!\n");
	if (!(data = kmalloc(sizeof(struct ami304_i2c_data), GFP_KERNEL))) {
		err = -ENOMEM;
		goto exit;
	}
	memset(data, 0, sizeof(struct ami304_i2c_data));

	new_client = client;
	i2c_set_clientdata(new_client, data);
	new_client->flags = 0;

	strlcpy(new_client->name, "ami304_i2c", I2C_NAME_SIZE);

	data->client = new_client;
	g_ami304_data = data;

	AMI304_Init(AMI304_FORCE_MODE); // default is Force State	
	printk(KERN_INFO "AMI304 registered I2C driver!\n");

	data->input_dev = input_allocate_device();
	if (!data->input_dev) {
		err = -ENOMEM;
		printk(KERN_ERR
		       "ami304_i2c_detect: Failed to allocate input device\n");
		goto exit_input_dev_alloc_failed;
	}

	set_bit(EV_ABS, data->input_dev->evbit);
	/* yaw */
	input_set_abs_params(data->input_dev, ABS_RX, 0, 360, 0, 0);
	/* pitch */
	input_set_abs_params(data->input_dev, ABS_RY, -180, 180, 0, 0);
	/* roll */
	input_set_abs_params(data->input_dev, ABS_RZ, -90, 90, 0, 0);
	/* status of magnetic sensor */	
	input_set_abs_params(data->input_dev, ABS_RUDDER, 0, 5, 0, 0);

	/* x-axis acceleration */
	input_set_abs_params(data->input_dev, ABS_X, -2000, 2000, 0, 0);
	/* y-axis acceleration */
	input_set_abs_params(data->input_dev, ABS_Y, -2000, 2000, 0, 0);
	/* z-axis acceleration */
	input_set_abs_params(data->input_dev, ABS_Z, -2000, 2000, 0, 0);

	/* x-axis of raw magnetic vector */
	input_set_abs_params(data->input_dev, ABS_HAT0X, -3000, 3000, 0, 0);
	/* y-axis of raw magnetic vector */
	input_set_abs_params(data->input_dev, ABS_HAT0Y, -3000, 3000, 0, 0);
	/* z-axis of raw magnetic vector */
	input_set_abs_params(data->input_dev, ABS_BRAKE, -3000, 3000, 0, 0);
	/* status of acceleration sensor */
	input_set_abs_params(data->input_dev, ABS_WHEEL, 0, 5, 0, 0);	

	data->input_dev->name = "Acompass";

	err = input_register_device(data->input_dev);
	if (err) {
		printk(KERN_ERR
		       "ami304_i2c_detect: Unable to register input device: %s\n",
		       data->input_dev->name);
		goto exit_input_register_device_failed;
	}
	    printk(KERN_ERR
		       "register input device successfully!!!\n");

	err = misc_register(&ami304_device);
	if (err) {
		printk(KERN_ERR
		       "ami304_device register failed\n");
		goto exit_misc_device_register_failed;
	}	
	err = device_create_file(&new_client->dev, &dev_attr_chipinfo);
	err = device_create_file(&new_client->dev, &dev_attr_sensordata);
	err = device_create_file(&new_client->dev, &dev_attr_posturedata);
	err = device_create_file(&new_client->dev, &dev_attr_calidata);
	err = device_create_file(&new_client->dev, &dev_attr_midcontrol);
	err = device_create_file(&new_client->dev, &dev_attr_mode);

	err = misc_register(&ami304daemon_device);
	if (err) {
		printk(KERN_ERR
		       "ami304daemon_device register failed\n");
		goto exit_misc_device_register_failed;
	}	

	err = misc_register(&ami304hal_device);
	if (err) {
		printk(KERN_ERR
		       "ami304hal_device register failed\n");
		goto exit_misc_device_register_failed;
	}	
	
	return 0;
exit_misc_device_register_failed:
exit_input_register_device_failed:
	input_free_device(data->input_dev);
exit_input_dev_alloc_failed:
exit_alloc_data_failed:
	kfree(data);
	g_ami304_data = NULL;
exit:
	return err;
}
예제 #8
0
static int ami304_ioctl(struct inode *inode, struct file *file, unsigned int cmd,unsigned long arg)
{
	char strbuf[AMI304_BUFSIZE];
	int controlbuf[10];
	void __user *data;
	int retval=0;
	int mode=0;

	switch (cmd) {
		case AMI304_IOCTL_INIT:
			read_lock(&ami304_data.lock);
			mode = ami304_data.mode;
			read_unlock(&ami304_data.lock);
			AMI304_Init(mode);
			break;

		case AMI304_IOCTL_READ_CHIPINFO:
			data = (void __user *) arg;
			if (data == NULL)
				break;
			AMI304_ReadChipInfo(strbuf, AMI304_BUFSIZE);
			if (copy_to_user(data, strbuf, strlen(strbuf)+1)) {
				retval = -EFAULT;
				goto err_out;
			}
			break;

		case AMI304_IOCTL_READ_SENSORDATA:
			data = (void __user *) arg;
			if (data == NULL)
				break;
			AMI304_ReadSensorData(strbuf, AMI304_BUFSIZE);
			if (copy_to_user(data, strbuf, strlen(strbuf)+1)) {
				retval = -EFAULT;
				goto err_out;
			}
			break;

		case AMI304_IOCTL_READ_POSTUREDATA:
			data = (void __user *) arg;
			if (data == NULL)
				break;
			AMI304_ReadPostureData(strbuf, AMI304_BUFSIZE);
			if (copy_to_user(data, strbuf, strlen(strbuf)+1)) {
				retval = -EFAULT;
				goto err_out;
			}
			break;

	        case AMI304_IOCTL_READ_CALIDATA:
			data = (void __user *) arg;
			if (data == NULL)
				break;
			AMI304_ReadCaliData(strbuf, AMI304_BUFSIZE);
			if (copy_to_user(data, strbuf, strlen(strbuf)+1)) {
				retval = -EFAULT;
				goto err_out;
			}
	        	break;

	        case AMI304_IOCTL_READ_CONTROL:
			read_lock(&ami304mid_data.ctrllock);
			memcpy(controlbuf, &ami304mid_data.controldata[0], sizeof(controlbuf));
			read_unlock(&ami304mid_data.ctrllock);
			data = (void __user *) arg;
			if (data == NULL)
				break;
			if (copy_to_user(data, controlbuf, sizeof(controlbuf))) {
				retval = -EFAULT;
				goto err_out;
			}
	        	break;

		case AMI304_IOCTL_SET_CONTROL:
			data = (void __user *) arg;
			if (data == NULL)
				break;
			if (copy_from_user(controlbuf, data, sizeof(controlbuf))) {
				retval = -EFAULT;
				goto err_out;
			}
			write_lock(&ami304mid_data.ctrllock);
			memcpy(&ami304mid_data.controldata[0], controlbuf, sizeof(controlbuf));
			write_unlock(&ami304mid_data.ctrllock);
			break;

		case AMI304_IOCTL_SET_MODE:
			data = (void __user *) arg;
			if (data == NULL)
				break;
			if (copy_from_user(&mode, data, sizeof(mode))) {
				retval = -EFAULT;
				goto err_out;
			}
			AMI304_SetMode(mode);
			break;

		default:
			if (AMI304_DEBUG_USER_ERROR & ami304_debug_mask)
				AMIE("not supported command= 0x%04x\n", cmd);
			retval = -ENOIOCTLCMD;
			break;
	}

err_out:
	return retval;
}