/* * Copyright (C) 2012, Samsung Electronics Co. Ltd. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * */ #include #include #include #include "adsp.h" #define VENDOR "AMS" #define CHIP_ID "TCS3701" #define ASCII_TO_DEC(x) (x - 48) int brightness; #ifdef CONFIG_SUPPORT_BHL_COMPENSATION_FOR_LIGHT_SENSOR enum { OPTION_TYPE_COPR_ENABLE, OPTION_TYPE_BOLED_ENABLE, OPTION_TYPE_LCD_ONOFF, OPTION_TYPE_GET_COPR, OPTION_TYPE_GET_CHIP_ID, OPTION_TYPE_MAX }; #endif /*************************************************************************/ /* factory Sysfs */ /*************************************************************************/ static ssize_t light_vendor_show(struct device *dev, struct device_attribute *attr, char *buf) { return snprintf(buf, PAGE_SIZE, "%s\n", VENDOR); } static ssize_t light_name_show(struct device *dev, struct device_attribute *attr, char *buf) { return snprintf(buf, PAGE_SIZE, "%s\n", CHIP_ID); } int get_light_sidx(struct adsp_data *data) { return MSG_LIGHT; } static ssize_t light_raw_data_show(struct device *dev, struct device_attribute *attr, char *buf) { struct adsp_data *data = dev_get_drvdata(dev); uint16_t light_idx = get_light_sidx(data); uint8_t cnt = 0; mutex_lock(&data->light_factory_mutex); adsp_unicast(NULL, 0, light_idx, 0, MSG_TYPE_GET_RAW_DATA); while (!(data->ready_flag[MSG_TYPE_GET_RAW_DATA] & 1 << light_idx) && cnt++ < TIMEOUT_CNT) usleep_range(500, 550); data->ready_flag[MSG_TYPE_GET_RAW_DATA] &= ~(1 << light_idx); if (cnt >= TIMEOUT_CNT) { pr_err("[FACTORY] %s: Timeout\n", __func__); mutex_unlock(&data->light_factory_mutex); return snprintf(buf, PAGE_SIZE, "0,0,0,0,0,0\n"); } mutex_unlock(&data->light_factory_mutex); return snprintf(buf, PAGE_SIZE, "%d,%d,%d,%d,%d,%d\n", data->msg_buf[light_idx][0], data->msg_buf[light_idx][1], data->msg_buf[light_idx][2], data->msg_buf[light_idx][3], data->msg_buf[light_idx][4], data->msg_buf[light_idx][5]); } static ssize_t light_get_dhr_sensor_info_show(struct device *dev, struct device_attribute *attr, char *buf) { struct adsp_data *data = dev_get_drvdata(dev); uint16_t light_idx = get_light_sidx(data); uint8_t cnt = 0; pr_info("[FACTORY] %s: start\n", __func__); mutex_lock(&data->light_factory_mutex); adsp_unicast(NULL, 0, light_idx, 0, MSG_TYPE_GET_DHR_INFO); while (!(data->ready_flag[MSG_TYPE_GET_DHR_INFO] & 1 << light_idx) && cnt++ < TIMEOUT_CNT) usleep_range(500, 550); data->ready_flag[MSG_TYPE_GET_DHR_INFO] &= ~(1 << light_idx); if (cnt >= TIMEOUT_CNT) pr_err("[FACTORY] %s: Timeout\n", __func__); mutex_unlock(&data->light_factory_mutex); return data->msg_buf[light_idx][0]; } static ssize_t light_brightness_show(struct device *dev, struct device_attribute *attr, char *buf) { pr_info("[FACTORY] %s: %d\n", __func__, brightness); return snprintf(buf, PAGE_SIZE, "%d\n", brightness); } static ssize_t light_brightness_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { struct adsp_data *data = dev_get_drvdata(dev); uint16_t light_idx = get_light_sidx(data); brightness = ASCII_TO_DEC(buf[0]) * 100 + ASCII_TO_DEC(buf[1]) * 10 + ASCII_TO_DEC(buf[2]); pr_info("[FACTORY] %s: %d\n", __func__, brightness); adsp_unicast(&brightness, sizeof(brightness), light_idx, 0, MSG_TYPE_SET_CAL_DATA); pr_info("[FACTORY] %s: done\n", __func__); return size; } #ifdef CONFIG_SUPPORT_BHL_COMPENSATION_FOR_LIGHT_SENSOR /* static ssize_t light_read_copr_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { struct adsp_data *data = dev_get_drvdata(dev); uint16_t light_idx = get_light_sidx(data); int32_t msg_buf[2]; int new_value; if (sysfs_streq(buf, "0")) new_value = 0; else if (sysfs_streq(buf, "1")) new_value = 1; else return size; pr_info("[FACTORY] %s: new_value %d\n", __func__, new_value); msg_buf[0] = OPTION_TYPE_COPR_ENABLE; msg_buf[1] = new_value; mutex_lock(&data->light_factory_mutex); adsp_unicast(msg_buf, sizeof(msg_buf), light_idx, 0, MSG_TYPE_OPTION_DEFINE); mutex_unlock(&data->light_factory_mutex); return size; } static ssize_t light_read_copr_show(struct device *dev, struct device_attribute *attr, char *buf) { struct adsp_data *data = dev_get_drvdata(dev); int32_t cmd = OPTION_TYPE_GET_COPR; uint16_t light_idx = get_light_sidx(data); uint8_t cnt = 0; mutex_lock(&data->light_factory_mutex); adsp_unicast(&cmd, sizeof(cmd), light_idx, 0, MSG_TYPE_GET_CAL_DATA); while (!(data->ready_flag[MSG_TYPE_GET_CAL_DATA] & 1 << light_idx) && cnt++ < TIMEOUT_CNT) usleep_range(500, 550); data->ready_flag[MSG_TYPE_GET_CAL_DATA] &= ~(1 << light_idx); if (cnt >= TIMEOUT_CNT) { pr_err("[FACTORY] %s: Timeout\n", __func__); mutex_unlock(&data->light_factory_mutex); return snprintf(buf, PAGE_SIZE, "-1\n"); } pr_info("[FACTORY] %s: %d\n", __func__, data->msg_buf[light_idx][4]); mutex_unlock(&data->light_factory_mutex); return snprintf(buf, PAGE_SIZE, "%d\n", data->msg_buf[light_idx][4]); } static ssize_t light_copr_roix_show(struct device *dev, struct device_attribute *attr, char *buf) { struct adsp_data *data = dev_get_drvdata(dev); uint16_t light_idx = get_light_sidx(data); uint8_t cnt = 0; mutex_lock(&data->light_factory_mutex); adsp_unicast(NULL, 0, light_idx, 0, MSG_TYPE_GET_DUMP_REGISTER); while (!(data->ready_flag[MSG_TYPE_GET_DUMP_REGISTER] & 1 << light_idx) && cnt++ < TIMEOUT_CNT) usleep_range(500, 550); data->ready_flag[MSG_TYPE_GET_DUMP_REGISTER] &= ~(1 << light_idx); if (cnt >= TIMEOUT_CNT) { pr_err("[FACTORY] %s: Timeout\n", __func__); mutex_unlock(&data->light_factory_mutex); return snprintf(buf, PAGE_SIZE, "-1,-1,-1,-1\n"); } pr_info("[FACTORY] %s: %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n", __func__, data->msg_buf[light_idx][0], data->msg_buf[light_idx][1], data->msg_buf[light_idx][2], data->msg_buf[light_idx][3], data->msg_buf[light_idx][4], data->msg_buf[light_idx][5], data->msg_buf[light_idx][6], data->msg_buf[light_idx][7], data->msg_buf[light_idx][8], data->msg_buf[light_idx][9], data->msg_buf[light_idx][10], data->msg_buf[light_idx][11]); mutex_unlock(&data->light_factory_mutex); return snprintf(buf, PAGE_SIZE, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n", data->msg_buf[light_idx][0], data->msg_buf[light_idx][1], data->msg_buf[light_idx][2], data->msg_buf[light_idx][3], data->msg_buf[light_idx][4], data->msg_buf[light_idx][5], data->msg_buf[light_idx][6], data->msg_buf[light_idx][7], data->msg_buf[light_idx][8], data->msg_buf[light_idx][9], data->msg_buf[light_idx][10], data->msg_buf[light_idx][11]); } static ssize_t light_test_copr_show(struct device *dev, struct device_attribute *attr, char *buf) { struct adsp_data *data = dev_get_drvdata(dev); int32_t cmd = OPTION_TYPE_GET_COPR; uint16_t light_idx = get_light_sidx(data); uint8_t cnt = 0; mutex_lock(&data->light_factory_mutex); adsp_unicast(&cmd, sizeof(cmd), light_idx, 0, MSG_TYPE_GET_CAL_DATA); while (!(data->ready_flag[MSG_TYPE_GET_CAL_DATA] & 1 << light_idx) && cnt++ < TIMEOUT_CNT) usleep_range(500, 550); data->ready_flag[MSG_TYPE_GET_CAL_DATA] &= ~(1 << light_idx); if (cnt >= TIMEOUT_CNT) { pr_err("[FACTORY] %s: Timeout\n", __func__); mutex_unlock(&data->light_factory_mutex); return snprintf(buf, PAGE_SIZE, "-1,-1,-1,-1\n"); } pr_info("[FACTORY] %s: %d,%d,%d,%d\n", __func__, data->msg_buf[light_idx][0], data->msg_buf[light_idx][1], data->msg_buf[light_idx][2], data->msg_buf[light_idx][3]); mutex_unlock(&data->light_factory_mutex); return snprintf(buf, PAGE_SIZE, "%d,%d,%d,%d\n", data->msg_buf[light_idx][0], data->msg_buf[light_idx][1], data->msg_buf[light_idx][2], data->msg_buf[light_idx][3]); } static ssize_t light_ddi_spi_check_show(struct device *dev, struct device_attribute *attr, char *buf) { struct adsp_data *data = dev_get_drvdata(dev); int32_t cmd = OPTION_TYPE_GET_CHIP_ID; uint16_t light_idx = get_light_sidx(data); uint8_t cnt = 0; mutex_lock(&data->light_factory_mutex); adsp_unicast(&cmd, sizeof(cmd), light_idx, 0, MSG_TYPE_GET_CAL_DATA); while (!(data->ready_flag[MSG_TYPE_GET_CAL_DATA] & 1 << light_idx) && cnt++ < TIMEOUT_CNT) usleep_range(500, 550); data->ready_flag[MSG_TYPE_GET_CAL_DATA] &= ~(1 << light_idx); if (cnt >= TIMEOUT_CNT) { pr_err("[FACTORY] %s: Timeout\n", __func__); mutex_unlock(&data->light_factory_mutex); return snprintf(buf, PAGE_SIZE, "-1\n"); } pr_info("[FACTORY] %s: %d\n", __func__, data->msg_buf[light_idx][0]); mutex_unlock(&data->light_factory_mutex); return snprintf(buf, PAGE_SIZE, "%d\n", data->msg_buf[light_idx][0]); } static ssize_t light_boled_enable_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { struct adsp_data *data = dev_get_drvdata(dev); uint16_t light_idx = get_light_sidx(data); int32_t msg_buf[2]; int new_value; if (sysfs_streq(buf, "0")) new_value = 0; else if (sysfs_streq(buf, "1")) new_value = 1; else return size; pr_info("[FACTORY] %s: new_value %d\n", __func__, new_value); msg_buf[0] = OPTION_TYPE_BOLED_ENABLE; msg_buf[1] = new_value; mutex_lock(&data->light_factory_mutex); adsp_unicast(msg_buf, sizeof(msg_buf), light_idx, 0, MSG_TYPE_OPTION_DEFINE); mutex_unlock(&data->light_factory_mutex); return size; } */ static ssize_t light_lcd_onoff_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { struct adsp_data *data = dev_get_drvdata(dev); uint16_t light_idx = get_light_sidx(data); int32_t msg_buf[2]; int new_value; if (sysfs_streq(buf, "0")) new_value = 0; else if (sysfs_streq(buf, "1")) new_value = 1; else return size; pr_info("[FACTORY] %s: new_value %d\n", __func__, new_value); msg_buf[0] = OPTION_TYPE_LCD_ONOFF; msg_buf[1] = new_value; adsp_unicast(msg_buf, sizeof(msg_buf), light_idx, 0, MSG_TYPE_OPTION_DEFINE); pr_info("[FACTORY] %s: done\n", __func__); return size; } static ssize_t light_circle_show(struct device *dev, struct device_attribute *attr, char *buf) { #if defined(CONFIG_SEC_A70Q_PROJECT) || defined(CONFIG_SEC_A70S_PROJECT) return snprintf(buf, PAGE_SIZE, "53.34 2.89 1.8\n"); #elif defined(CONFIG_SEC_A90Q_PROJECT) return snprintf(buf, PAGE_SIZE, "24.16 36.36 1.8\n"); #elif defined(CONFIG_SEC_A70SQ_PROJECT) || defined(CONFIG_SEC_A71_PROJECT) return snprintf(buf, PAGE_SIZE, "53.20 2.41 1.8\n"); #else return snprintf(buf, PAGE_SIZE, "0 0 0\n"); #endif } static ssize_t light_register_read_show(struct device *dev, struct device_attribute *attr, char *buf) { struct adsp_data *data = dev_get_drvdata(dev); uint16_t light_idx = get_light_sidx(data); int cnt = 0; int32_t msg_buf[1]; msg_buf[0] = data->msg_buf[light_idx][MSG_LIGHT_MAX - 1]; mutex_lock(&data->light_factory_mutex); adsp_unicast(msg_buf, sizeof(msg_buf), light_idx, 0, MSG_TYPE_GET_REGISTER); while (!(data->ready_flag[MSG_TYPE_GET_REGISTER] & 1 << light_idx) && cnt++ < TIMEOUT_CNT) usleep_range(500, 550); data->ready_flag[MSG_TYPE_GET_REGISTER] &= ~(1 << light_idx); if (cnt >= TIMEOUT_CNT) pr_err("[FACTORY] %s: Timeout\n", __func__); pr_info("[FACTORY] %s: [0x%x]: 0x%x\n", __func__, data->msg_buf[light_idx][MSG_LIGHT_MAX - 1], data->msg_buf[light_idx][0]); mutex_unlock(&data->light_factory_mutex); return snprintf(buf, PAGE_SIZE, "[0x%x]: 0x%x\n", data->msg_buf[light_idx][MSG_LIGHT_MAX - 1], data->msg_buf[light_idx][0]); } static ssize_t light_register_read_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { int reg = 0; struct adsp_data *data = dev_get_drvdata(dev); uint16_t light_idx = get_light_sidx(data); if (sscanf(buf, "%3x", ®) != 1) { pr_err("[FACTORY]: %s - The number of data are wrong\n", __func__); return -EINVAL; } data->msg_buf[light_idx][MSG_LIGHT_MAX - 1] = reg; pr_info("[FACTORY] %s: [0x%x]\n", __func__, data->msg_buf[light_idx][MSG_LIGHT_MAX - 1]); return size; } static ssize_t light_register_write_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { struct adsp_data *data = dev_get_drvdata(dev); uint16_t light_idx = get_light_sidx(data); int cnt = 0; int32_t msg_buf[2]; if (sscanf(buf, "%3x,%3x", &msg_buf[0], &msg_buf[1]) != 2) { pr_err("[FACTORY]: %s - The number of data are wrong\n", __func__); return -EINVAL; } mutex_lock(&data->light_factory_mutex); adsp_unicast(msg_buf, sizeof(msg_buf), light_idx, 0, MSG_TYPE_SET_REGISTER); while (!(data->ready_flag[MSG_TYPE_SET_REGISTER] & 1 << light_idx) && cnt++ < TIMEOUT_CNT) usleep_range(500, 550); data->ready_flag[MSG_TYPE_SET_REGISTER] &= ~(1 << light_idx); if (cnt >= TIMEOUT_CNT) pr_err("[FACTORY] %s: Timeout\n", __func__); data->msg_buf[light_idx][MSG_LIGHT_MAX - 1] = msg_buf[0]; pr_info("[FACTORY] %s: 0x%x - 0x%x\n", __func__, msg_buf[0], data->msg_buf[light_idx][0]); mutex_unlock(&data->light_factory_mutex); return size; } static DEVICE_ATTR(lcd_onoff, 0220, NULL, light_lcd_onoff_store); /* static DEVICE_ATTR(read_copr, 0664, light_read_copr_show, light_read_copr_store); static DEVICE_ATTR(test_copr, 0444, light_test_copr_show, NULL); static DEVICE_ATTR(copr_roix, 0444, light_copr_roix_show, NULL); static DEVICE_ATTR(sensorhub_ddi_spi_check, 0444, light_ddi_spi_check_show, NULL); static DEVICE_ATTR(boled_enable, 0220, NULL, light_boled_enable_store); */ static DEVICE_ATTR(light_circle, 0444, light_circle_show, NULL); static DEVICE_ATTR(register_write, 0220, NULL, light_register_write_store); static DEVICE_ATTR(register_read, 0664, light_register_read_show, light_register_read_store); #endif static DEVICE_ATTR(vendor, 0444, light_vendor_show, NULL); static DEVICE_ATTR(name, 0444, light_name_show, NULL); static DEVICE_ATTR(lux, 0444, light_raw_data_show, NULL); static DEVICE_ATTR(raw_data, 0444, light_raw_data_show, NULL); static DEVICE_ATTR(dhr_sensor_info, 0444, light_get_dhr_sensor_info_show, NULL); static DEVICE_ATTR(brightness, 0664, light_brightness_show, light_brightness_store); static struct device_attribute *light_attrs[] = { &dev_attr_vendor, &dev_attr_name, &dev_attr_lux, &dev_attr_raw_data, &dev_attr_dhr_sensor_info, &dev_attr_brightness, #ifdef CONFIG_SUPPORT_BHL_COMPENSATION_FOR_LIGHT_SENSOR &dev_attr_lcd_onoff, /* &dev_attr_read_copr, &dev_attr_test_copr, &dev_attr_copr_roix, &dev_attr_sensorhub_ddi_spi_check, &dev_attr_boled_enable, */ &dev_attr_light_circle, &dev_attr_register_write, &dev_attr_register_read, #endif NULL, }; static int __init tcs3701_light_factory_init(void) { adsp_factory_register(MSG_LIGHT, light_attrs); pr_info("[FACTORY] %s\n", __func__); brightness = 0; return 0; } static void __exit tcs3701_light_factory_exit(void) { adsp_factory_unregister(MSG_LIGHT); pr_info("[FACTORY] %s\n", __func__); } module_init(tcs3701_light_factory_init); module_exit(tcs3701_light_factory_exit);