static int cm36686_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { int ret = -ENODEV; struct cm36686_data *cm36686 = NULL; struct cm36686_platform_data *pdata = NULL; int err; pr_info("[SENSOR] %s: Probe Start!\n", __func__); if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { pr_err("[SENSOR] %s: i2c functionality check failed!\n", __func__); return ret; } cm36686 = kzalloc(sizeof(struct cm36686_data), GFP_KERNEL); if (!cm36686) { pr_err ("[SENSOR] %s: failed to alloc memory for RGB sensor module data\n", __func__); return -ENOMEM; } if(client->dev.of_node) { pdata = devm_kzalloc (&client->dev , sizeof(struct cm36686_platform_data ), GFP_KERNEL); if(!pdata) { dev_err(&client->dev, "Failed to allocate memory\n"); if(cm36686) kfree(cm36686); return -ENOMEM; } err = cm36686_parse_dt(&client->dev, pdata); if(err) goto err_devicetree; } else pdata = client->dev.platform_data; if (!pdata) { pr_err("%s: missing pdata!\n", __func__); if(cm36686) kfree(cm36686); return ret; } prox_regulator_onoff(&client->dev,1); cm36686->pdata = pdata; cm36686->i2c_client = client; i2c_set_clientdata(client, cm36686); mutex_init(&cm36686->power_lock); mutex_init(&cm36686->read_lock); /* wake lock init for proximity sensor */ wake_lock_init(&cm36686->prx_wake_lock, WAKE_LOCK_SUSPEND, "prx_wake_lock"); #if defined(CONFIG_SENSORS_CM36686_LEDA_EN_GPIO) /* setup leden_gpio */ ret = cm36686_setup_leden_gpio(cm36686); if (ret) { pr_err("%s: could not setup leden_gpio\n", __func__); goto err_setup_leden_gpio; } cm36686_leden_gpio_onoff(cm36686, 1); #else prox_led_onoff(cm36686, 1); #endif /* Check if the device is there or not. */ ret = cm36686_i2c_write_word(cm36686, REG_CS_CONF1, 0x0001); if (ret < 0) { pr_err("[SENSOR] %s: cm36686 is not connected.(%d)\n", __func__, ret); goto err_setup_reg; } /* setup initial registers */ ret = cm36686_setup_reg(cm36686); if (ret < 0) { pr_err("[SENSOR] %s: could not setup regs\n", __func__); goto err_setup_reg; } #if defined(CONFIG_SENSORS_CM36686_LEDA_EN_GPIO) cm36686_leden_gpio_onoff(cm36686, 0); #else prox_led_onoff(cm36686, 0); #endif /* allocate proximity input_device */ cm36686->proximity_input_dev = input_allocate_device(); if (!cm36686->proximity_input_dev) { pr_err("%s: could not allocate proximity input device\n", __func__); goto err_input_allocate_device_proximity; } input_set_drvdata(cm36686->proximity_input_dev, cm36686); cm36686->proximity_input_dev->name = "proximity_sensor"; input_set_capability(cm36686->proximity_input_dev, EV_ABS, ABS_DISTANCE); input_set_abs_params(cm36686->proximity_input_dev, ABS_DISTANCE, 0, 1, 0, 0); ret = input_register_device(cm36686->proximity_input_dev); if (ret < 0) { input_free_device(cm36686->proximity_input_dev); pr_err("[SENSOR] %s: could not register input device\n", __func__); goto err_input_register_device_proximity; } ret = sensors_create_symlink(&cm36686->proximity_input_dev->dev.kobj, cm36686->proximity_input_dev->name); if (ret < 0) { pr_err("[SENSOR] %s: create_symlink error\n", __func__); goto err_sensors_create_symlink_prox; } ret = sysfs_create_group(&cm36686->proximity_input_dev->dev.kobj, &proximity_attribute_group); if (ret) { pr_err("[SENSOR] %s: could not create sysfs group\n", __func__); goto err_sysfs_create_group_proximity; } /* setup irq */ ret = cm36686_setup_irq(cm36686); if (ret) { pr_err("%s: could not setup irq\n", __func__); goto err_setup_irq; } /* For factory test mode, we use timer to get average proximity data. */ /* prox_timer settings. we poll for light values using a timer. */ hrtimer_init(&cm36686->prox_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); cm36686->prox_poll_delay = ns_to_ktime(2000 * NSEC_PER_MSEC);/*2 sec*/ cm36686->prox_timer.function = cm36686_prox_timer_func; /* the timer just fires off a work queue request. we need a thread to read the i2c (can be slow and blocking). */ cm36686->prox_wq = create_singlethread_workqueue("cm36686_prox_wq"); if (!cm36686->prox_wq) { ret = -ENOMEM; pr_err("[SENSOR] %s: could not create prox workqueue\n", __func__); goto err_create_prox_workqueue; } /* this is the thread function we run on the work queue */ INIT_WORK(&cm36686->work_prox, cm36686_work_func_prox); /* allocate lightsensor input_device */ cm36686->light_input_dev = input_allocate_device(); if (!cm36686->light_input_dev) { pr_err("%s: could not allocate light input device\n", __func__); goto err_input_allocate_device_light; } input_set_drvdata(cm36686->light_input_dev, cm36686); cm36686->light_input_dev->name = "light_sensor"; input_set_capability(cm36686->light_input_dev, EV_REL, REL_MISC); input_set_capability(cm36686->light_input_dev, EV_REL, REL_DIAL); input_set_capability(cm36686->light_input_dev, EV_REL, REL_WHEEL); ret = input_register_device(cm36686->light_input_dev); if (ret < 0) { input_free_device(cm36686->light_input_dev); pr_err("%s: could not register input device\n", __func__); goto err_input_register_device_light; } ret = sensors_create_symlink(&cm36686->light_input_dev->dev.kobj, cm36686->light_input_dev->name); if (ret < 0) { pr_err("[SENSOR] %s: create_symlink error\n", __func__); goto err_sensors_create_symlink_light; } ret = sysfs_create_group(&cm36686->light_input_dev->dev.kobj, &light_attribute_group); if (ret) { pr_err("[SENSOR] %s: could not create sysfs group\n", __func__); goto err_sysfs_create_group_light; } /* light_timer settings. we poll for light values using a timer. */ hrtimer_init(&cm36686->light_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); cm36686->light_poll_delay = ns_to_ktime(200 * NSEC_PER_MSEC); cm36686->light_timer.function = cm36686_light_timer_func; /* the timer just fires off a work queue request. we need a thread to read the i2c (can be slow and blocking). */ cm36686->light_wq = create_singlethread_workqueue("cm36686_light_wq"); if (!cm36686->light_wq) { ret = -ENOMEM; pr_err("[SENSOR] %s: could not create light workqueue\n", __func__); goto err_create_light_workqueue; } /* this is the thread function we run on the work queue */ INIT_WORK(&cm36686->work_light, cm36686_work_func_light); /* set sysfs for proximity sensor */ ret = sensors_register(cm36686->proximity_dev, cm36686, prox_sensor_attrs, "proximity_sensor"); if (ret) { pr_err("[SENSOR] %s: cound not register\ proximity sensor device(%d).\n", __func__, ret); goto prox_sensor_register_failed; } /* set sysfs for light sensor */ ret = sensors_register(cm36686->light_dev, cm36686, light_sensor_attrs, "light_sensor"); if (ret) { pr_err("[SENSOR] %s: cound not register\ light sensor device(%d).\n", __func__, ret); goto light_sensor_register_failed; } pr_info("[SENSOR] %s is success.\n", __func__); goto done; err_devicetree: printk("\n error in device tree"); /* error, unwind it all */ light_sensor_register_failed: sensors_unregister(cm36686->proximity_dev, prox_sensor_attrs); prox_sensor_register_failed: destroy_workqueue(cm36686->light_wq); err_create_light_workqueue: sysfs_remove_group(&cm36686->light_input_dev->dev.kobj, &light_attribute_group); err_sysfs_create_group_light: sensors_remove_symlink(&cm36686->light_input_dev->dev.kobj, cm36686->light_input_dev->name); err_sensors_create_symlink_light: input_unregister_device(cm36686->light_input_dev); err_input_register_device_light: err_input_allocate_device_light: destroy_workqueue(cm36686->prox_wq); err_create_prox_workqueue: free_irq(cm36686->irq, cm36686); gpio_free(cm36686->pdata->irq); err_setup_irq: sysfs_remove_group(&cm36686->proximity_input_dev->dev.kobj, &proximity_attribute_group); err_sysfs_create_group_proximity: sensors_remove_symlink(&cm36686->proximity_input_dev->dev.kobj, cm36686->proximity_input_dev->name); err_sensors_create_symlink_prox: input_unregister_device(cm36686->proximity_input_dev); err_input_register_device_proximity: err_input_allocate_device_proximity: err_setup_reg: #if defined(CONFIG_SENSORS_CM36686_LEDA_EN_GPIO) cm36686_leden_gpio_onoff(cm36686, 0); gpio_free(cm36686->pdata->leden_gpio); err_setup_leden_gpio: #else prox_led_onoff(cm36686, 0); #endif wake_lock_destroy(&cm36686->prx_wake_lock); mutex_destroy(&cm36686->read_lock); mutex_destroy(&cm36686->power_lock); kfree(cm36686); prox_regulator_onoff(&client->dev,0); done: return ret; }
static int cm36686_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { int ret = -ENODEV; struct cm36686_data *cm36686 = NULL; pr_info("%s is called.\n", __func__); if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { pr_err("%s: i2c functionality check failed!\n", __func__); return ret; } cm36686 = kzalloc(sizeof(struct cm36686_data), GFP_KERNEL); if (!cm36686) { pr_err("%s: failed to alloc memory for cm36686 module data\n", __func__); return -ENOMEM; } cm36686->pdata = client->dev.platform_data; cm36686->i2c_client = client; i2c_set_clientdata(client, cm36686); mutex_init(&cm36686->power_lock); mutex_init(&cm36686->read_lock); if(cm36686->pdata->cm36686_light_power != NULL) { cm36686->cm36686_light_vddpower = cm36686->pdata->cm36686_light_power; if (cm36686->cm36686_light_vddpower) cm36686->cm36686_light_vddpower(true); } if(cm36686->pdata->cm36686_proxi_power != NULL) { cm36686->cm36686_proxi_vddpower = cm36686->pdata->cm36686_proxi_power; if (cm36686->cm36686_proxi_vddpower) cm36686->cm36686_proxi_vddpower(true); } /* wake lock init for proximity sensor */ wake_lock_init(&cm36686->prx_wake_lock, WAKE_LOCK_SUSPEND, "prx_wake_lock"); if (cm36686->pdata->cm36686_led_on) { cm36686->pdata->cm36686_led_on(true); msleep(20); } /* Check if the device is there or not. */ ret = cm36686_i2c_write_word(cm36686, REG_CS_CONF1, 0x0001); if (ret < 0) { pr_err("%s: cm36686 is not connected.(%d)\n", __func__, ret); goto err_setup_reg; } /* setup initial registers */ ret = cm36686_setup_reg(cm36686); if (ret < 0) { pr_err("%s: could not setup regs\n", __func__); goto err_setup_reg; } if (cm36686->pdata->cm36686_led_on) cm36686->pdata->cm36686_led_on(false); if (cm36686->cm36686_light_vddpower) cm36686->cm36686_light_vddpower(false); if (cm36686->cm36686_proxi_vddpower) cm36686->cm36686_proxi_vddpower(false); /* allocate proximity input_device */ cm36686->proximity_input_dev = input_allocate_device(); if (!cm36686->proximity_input_dev) { pr_err("%s: could not allocate proximity input device\n", __func__); goto err_input_allocate_device_proximity; } input_set_drvdata(cm36686->proximity_input_dev, cm36686); cm36686->proximity_input_dev->name = "proximity_sensor"; input_set_capability(cm36686->proximity_input_dev, EV_ABS, ABS_DISTANCE); input_set_abs_params(cm36686->proximity_input_dev, ABS_DISTANCE, 0, 1, 0, 0); ret = input_register_device(cm36686->proximity_input_dev); if (ret < 0) { input_free_device(cm36686->proximity_input_dev); pr_err("%s: could not register input device\n", __func__); goto err_input_register_device_proximity; } ret = sysfs_create_group(&cm36686->proximity_input_dev->dev.kobj, &proximity_attribute_group); if (ret) { pr_err("%s: could not create sysfs group\n", __func__); goto err_sysfs_create_group_proximity; } #if defined(CONFIG_SENSOR_USE_SYMLINK) ret = sensors_initialize_symlink(cm36686->proximity_input_dev); if (ret < 0) { pr_err("%s - proximity_sensors_initialize_symlink error(%d).\n", __func__, ret); goto err_setup_irq; } #endif /* setup irq */ ret = cm36686_setup_irq(cm36686); if (ret) { pr_err("%s: could not setup irq\n", __func__); goto err_setup_irq; } /* For factory test mode, we use timer to get average proximity data. */ /* prox_timer settings. we poll for light values using a timer. */ hrtimer_init(&cm36686->prox_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); cm36686->prox_poll_delay = ns_to_ktime(2000 * NSEC_PER_MSEC);/*2 sec*/ cm36686->prox_timer.function = cm36686_prox_timer_func; /* the timer just fires off a work queue request. we need a thread to read the i2c (can be slow and blocking). */ cm36686->prox_wq = create_singlethread_workqueue("cm36686_prox_wq"); if (!cm36686->prox_wq) { ret = -ENOMEM; pr_err("%s: could not create prox workqueue\n", __func__); goto err_create_prox_workqueue; } /* this is the thread function we run on the work queue */ INIT_WORK(&cm36686->work_prox, cm36686_work_func_prox); /* allocate lightsensor input_device */ cm36686->light_input_dev = input_allocate_device(); if (!cm36686->light_input_dev) { pr_err("%s: could not allocate light input device\n", __func__); goto err_input_allocate_device_light; } input_set_drvdata(cm36686->light_input_dev, cm36686); cm36686->light_input_dev->name = "light_sensor"; input_set_capability(cm36686->light_input_dev, EV_REL, REL_MISC); input_set_capability(cm36686->light_input_dev, EV_REL, REL_DIAL); input_set_capability(cm36686->light_input_dev, EV_REL, REL_WHEEL); ret = input_register_device(cm36686->light_input_dev); if (ret < 0) { input_free_device(cm36686->light_input_dev); pr_err("%s: could not register input device\n", __func__); goto err_input_register_device_light; } ret = sysfs_create_group(&cm36686->light_input_dev->dev.kobj, &light_attribute_group); if (ret) { pr_err("%s: could not create sysfs group\n", __func__); goto err_sysfs_create_group_light; } #if defined(CONFIG_SENSOR_USE_SYMLINK) ret = sensors_initialize_symlink(cm36686->light_input_dev); if (ret < 0) { pr_err("%s - light_sensors_initialize_symlink error(%d).\n", __func__, ret); goto err_create_light_workqueue; } #endif /* light_timer settings. we poll for light values using a timer. */ hrtimer_init(&cm36686->light_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); cm36686->light_poll_delay = ns_to_ktime(200 * NSEC_PER_MSEC); cm36686->light_timer.function = cm36686_light_timer_func; /* the timer just fires off a work queue request. we need a thread to read the i2c (can be slow and blocking). */ cm36686->light_wq = create_singlethread_workqueue("cm36686_light_wq"); if (!cm36686->light_wq) { ret = -ENOMEM; pr_err("%s: could not create light workqueue\n", __func__); goto err_create_light_workqueue; } /* this is the thread function we run on the work queue */ INIT_WORK(&cm36686->work_light, cm36686_work_func_light); /* set sysfs for proximity sensor */ cm36686->proximity_dev = sensors_classdev_register("proximity_sensor"); if (IS_ERR(cm36686->proximity_dev)) { pr_err("%s: could not create proximity_dev\n", __func__); goto err_proximity_device_create; } if (device_create_file(cm36686->proximity_dev, &dev_attr_state) < 0) { pr_err("%s: could not create device file(%s)!\n", __func__, dev_attr_state.attr.name); goto err_proximity_device_create_file1; } if (device_create_file(cm36686->proximity_dev, &attr_prox_raw) < 0) { pr_err("%s: could not create device file(%s)!\n", __func__, attr_prox_raw.attr.name); goto err_proximity_device_create_file2; } #ifdef CM36686_CANCELATION if (device_create_file(cm36686->proximity_dev, &dev_attr_prox_cal) < 0) { pr_err("%s: could not create device file(%s)!\n", __func__, dev_attr_prox_cal.attr.name); goto err_proximity_device_create_file3; } if (device_create_file(cm36686->proximity_dev, &dev_attr_prox_offset_pass) < 0) { pr_err("%s: could not create device file(%s)!\n", __func__, dev_attr_prox_offset_pass.attr.name); goto err_proximity_device_create_file4; } #endif if (device_create_file(cm36686->proximity_dev, &dev_attr_prox_avg) < 0) { pr_err("%s: could not create device file(%s)!\n", __func__, dev_attr_prox_avg.attr.name); goto err_proximity_device_create_file5; } if (device_create_file(cm36686->proximity_dev, &dev_attr_thresh_high) < 0) { pr_err("%s: could not create device file(%s)!\n", __func__, dev_attr_thresh_high.attr.name); goto err_proximity_device_create_file6; } if (device_create_file(cm36686->proximity_dev, &dev_attr_vendor) < 0) { pr_err("%s: could not create device file(%s)!\n", __func__, dev_attr_vendor.attr.name); goto err_proximity_device_create_file7; } if (device_create_file(cm36686->proximity_dev, &dev_attr_name) < 0) { pr_err("%s: could not create device file(%s)!\n", __func__, dev_attr_name.attr.name); goto err_proximity_device_create_file8; } if (device_create_file(cm36686->proximity_dev, &dev_attr_thresh_low) < 0) { pr_err("%s: could not create device file(%s)!\n", __func__, dev_attr_thresh_low.attr.name); goto err_proximity_device_create_file9; } dev_set_drvdata(cm36686->proximity_dev, cm36686); /* set sysfs for light sensor */ cm36686->light_dev = sensors_classdev_register("light_sensor"); if (IS_ERR(cm36686->light_dev)) { pr_err("%s: could not create light_dev\n", __func__); goto err_light_device_create; } if (device_create_file(cm36686->light_dev, &dev_attr_lux) < 0) { pr_err("%s: could not create device file(%s)!\n", __func__, dev_attr_lux.attr.name); goto err_light_device_create_file1; } if (device_create_file(cm36686->light_dev, &dev_attr_raw_data) < 0) { pr_err("%s: could not create device file(%s)!\n", __func__, dev_attr_raw_data.attr.name); goto err_light_device_create_file2; } if (device_create_file(cm36686->light_dev, &dev_attr_vendor) < 0) { pr_err("%s: could not create device file(%s)!\n", __func__, dev_attr_vendor.attr.name); goto err_light_device_create_file3; } if (device_create_file(cm36686->light_dev, &dev_attr_name) < 0) { pr_err("%s: could not create device file(%s)!\n", __func__, dev_attr_name.attr.name); goto err_light_device_create_file4; } dev_set_drvdata(cm36686->light_dev, cm36686); pr_info("%s is success.\n", __func__); goto done; /* error, unwind it all */ err_light_device_create_file4: device_remove_file(cm36686->light_dev, &dev_attr_vendor); err_light_device_create_file3: device_remove_file(cm36686->light_dev, &dev_attr_raw_data); err_light_device_create_file2: device_remove_file(cm36686->light_dev, &dev_attr_lux); err_light_device_create_file1: sensors_classdev_unregister(cm36686->light_dev); err_light_device_create: device_remove_file(cm36686->proximity_dev, &dev_attr_thresh_low); err_proximity_device_create_file9: device_remove_file(cm36686->proximity_dev, &dev_attr_name); err_proximity_device_create_file8: device_remove_file(cm36686->proximity_dev, &dev_attr_vendor); err_proximity_device_create_file7: device_remove_file(cm36686->proximity_dev, &dev_attr_thresh_high); err_proximity_device_create_file6: device_remove_file(cm36686->proximity_dev, &dev_attr_prox_avg); err_proximity_device_create_file5: #ifdef CM36686_CANCELATION device_remove_file(cm36686->proximity_dev, &dev_attr_prox_offset_pass); err_proximity_device_create_file4: device_remove_file(cm36686->proximity_dev, &dev_attr_prox_cal); err_proximity_device_create_file3: #endif device_remove_file(cm36686->proximity_dev, &attr_prox_raw); err_proximity_device_create_file2: device_remove_file(cm36686->proximity_dev, &dev_attr_state); err_proximity_device_create_file1: sensors_classdev_unregister(cm36686->proximity_dev); err_proximity_device_create: destroy_workqueue(cm36686->light_wq); err_create_light_workqueue: sysfs_remove_group(&cm36686->light_input_dev->dev.kobj, &light_attribute_group); err_sysfs_create_group_light: input_unregister_device(cm36686->light_input_dev); err_input_register_device_light: err_input_allocate_device_light: destroy_workqueue(cm36686->prox_wq); err_create_prox_workqueue: free_irq(cm36686->irq, cm36686); gpio_free(cm36686->pdata->irq); err_setup_irq: sysfs_remove_group(&cm36686->proximity_input_dev->dev.kobj, &proximity_attribute_group); err_sysfs_create_group_proximity: input_unregister_device(cm36686->proximity_input_dev); err_input_register_device_proximity: err_input_allocate_device_proximity: err_setup_reg: if (cm36686->pdata->cm36686_led_on) cm36686->pdata->cm36686_led_on(false); if (cm36686->cm36686_light_vddpower) cm36686->cm36686_light_vddpower(false); if (cm36686->cm36686_proxi_vddpower) cm36686->cm36686_proxi_vddpower(false); wake_lock_destroy(&cm36686->prx_wake_lock); mutex_destroy(&cm36686->read_lock); mutex_destroy(&cm36686->power_lock); kfree(cm36686); done: return ret; }