int print_line_cmcs(int mode, s16 *buf16, char *buf)
{
	int i, j;
	int idx;
	int type;
	int count = 0;
	int key_index[5] = { 0, };
	int key_cnt = 0;
	char msg[128];

	CMCS_INFO *cmcs = (CMCS_INFO *)&ts_cmcs->cmcs;

	int tx_num = cmcs->ch.tx_num;
	int rx_num = cmcs->ch.rx_num;

	if ((mode == CMCS_FLAG_CM_SLOPE0) || (mode == CMCS_FLAG_CM_SLOPE1)) {
		if (cmcs->ch.key_rx)
			rx_num--;
		else
			tx_num--;
	}

	for (i = 0; i < tx_num; i++) {
		for (j = 0; j < rx_num; j++) {
			type = check_tsp_type(i, j);
			if ((type == TSP_CH_UNKNOWN) || (type == TSP_CH_UNUSED))
				continue;   // Ignore

			if ((mode == CMCS_FLAG_CM_SLOPE0) && (j == (rx_num - 1)))
				continue;
			else if ((mode == CMCS_FLAG_CM_SLOPE1) && (i == (tx_num - 1)))
				continue;

			idx = (i * cmcs->ch.rx_num) + j;

			if (type == TSP_CH_KEY) {
				key_index[key_cnt++] = idx;
				continue;
			}

			count += sprintf(msg, "%5d ", buf16[idx]);
			strcat(buf, msg);
		}
	}

	tsp_info("key cnt: %d\n", key_cnt);
	if ((mode != CMCS_FLAG_CM_SLOPE0) && (mode != CMCS_FLAG_CM_SLOPE1)) {
		tsp_info("key cnt: %d\n", key_cnt);
		for (i = 0; i < key_cnt; i++) {
			count += sprintf(msg, "%5d ", buf16[key_index[i]]);
			strcat(buf, msg);
		}
	}

	count += sprintf(msg, "\n");
	strcat(buf, msg);

	return count;
}
/* sysfs: /sys/class/touch/cmcs/cm_result */
ssize_t ist30xx_cm_result_show(struct device *dev, struct device_attribute *attr,
			       char *buf)
{
	int i, j;
	int type, idx, err_cnt = 0;
	int min_spec, max_spec;
	int count = 0;
	short cm;
	char msg[128];

	CMCS_INFO *cmcs = (CMCS_INFO *)&ts_cmcs->cmcs;

	if (cmcs_ready == CMCS_NOT_READY)
		return sprintf(buf, "CMCS test is not work!!\n");

	if ((cmcs->cmd.mode) && !(cmcs->cmd.mode & FLAG_ENABLE_CM))
		return 0;

	for (i = 0; i < cmcs->ch.tx_num; i++) {
		for (j = 0; j < cmcs->ch.rx_num; j++) {
			idx = (i * cmcs->ch.rx_num) + j;

			type = check_tsp_type(i, j);
			if ((type == TSP_CH_UNKNOWN) || (type == TSP_CH_UNUSED))
				continue;

			min_spec = max_spec = ts_cmcs_buf->spec[idx];
			if (type == TSP_CH_SCREEN) {
				min_spec -= (min_spec * cmcs->spec_cm.screen_min / 100);
				max_spec += (min_spec * cmcs->spec_cm.screen_max / 100);
			} else {    // TSP_CH_KEY
				min_spec -= (min_spec * cmcs->spec_cm.key_min / 100);   // = -> -=
				max_spec += (min_spec * cmcs->spec_cm.key_max / 100); // = -> +=

			}

			cm = ts_cmcs_buf->cm[idx];
			if ((cm > min_spec) && (cm < max_spec))
				continue; // OK

			count += sprintf(msg, "%2d,%2d:%4d (%4d~%4d)\n",
					 i, j, cm, min_spec, max_spec);
			strcat(buf, msg);

			err_cnt++;
		}
	}

	/* Check error count */
	if (err_cnt == 0)
		count += sprintf(msg, "OK\n");
	else
		count += sprintf(msg, "Fail, node count: %d\n", err_cnt);
	strcat(buf, msg);

	return count;
}
int print_cs_result(s16 *buf16, char *buf, int cs_num)
{
	int i, j;
	int type, idx;
	int count = 0, err_cnt = 0;
	int min_spec, max_spec;

	char msg[128];

	CMCS_INFO *cmcs = (CMCS_INFO *)&ts_cmcs->cmcs;
	struct CMCS_SPEC_INFO *spec;

	if (cs_num == 0)
		spec = (struct CMCS_SPEC_INFO *)&cmcs->spec_cs0;
	else
		spec = (struct CMCS_SPEC_INFO *)&cmcs->spec_cs1;

	count = sprintf(msg, "Spec: screen(%d~%d), key(%d~%d)\n",
			spec->screen_min, spec->screen_max, spec->key_min, spec->key_max);
	strcat(buf, msg);

	for (i = 0; i < cmcs->ch.tx_num; i++) {
		for (j = 0; j < cmcs->ch.rx_num; j++) {
			idx = (i * cmcs->ch.rx_num) + j;

			type = check_tsp_type(i, j);
			if ((type == TSP_CH_UNKNOWN) || (type == TSP_CH_UNUSED))
				continue;   // Ignore

			if (type == TSP_CH_SCREEN) {
				min_spec = spec->screen_min;
				max_spec = spec->screen_max;
			} else {    // TSP_CH_KEY
				min_spec = spec->key_min;
				max_spec = spec->key_max;
			}

			if ((buf16[idx] > min_spec) && (buf16[idx] < max_spec))
				continue;   // OK

			count += sprintf(msg, "%2d,%2d:%4d\n", i, j, buf16[idx]);
			strcat(buf, msg);

			err_cnt++;
		}
	}

	/* Check error count */
	if (err_cnt == 0)
		count += sprintf(msg, "OK\n");
	else
		count += sprintf(msg, "Fail, node count: %d\n", err_cnt);
	strcat(buf, msg);

	return count;
}
int print_cm_slope_result(u8 flag, s16 *buf16, char *buf)
{
	int i, j;
	int type, idx;
	int count = 0, err_cnt = 0;
	int min_spec, max_spec;

	char msg[128];

	CMCS_INFO *cmcs = (CMCS_INFO *)&ts_cmcs->cmcs;
	struct CMCS_SLOPE_INFO *spec = (struct CMCS_SLOPE_INFO *)&cmcs->slope;

	if (flag == CMCS_FLAG_CM_SLOPE0) {
		min_spec = spec->x_min;
		max_spec = spec->x_max;
	} else if (flag == CMCS_FLAG_CM_SLOPE1) {
		min_spec = spec->y_min;
		max_spec = spec->y_max;
	} else {
		count = sprintf(msg, "Unknown flag: %d\n", flag);
		strcat(buf, msg);
		return count;
	}

	min_spec *= -1;

	count = sprintf(msg, "Spec: %d ~ %d\n", min_spec, max_spec);
	strcat(buf, msg);

	for (i = 0; i < cmcs->ch.tx_num; i++) {
		for (j = 0; j < cmcs->ch.rx_num; j++) {
			idx = (i * cmcs->ch.rx_num) + j;

			type = check_tsp_type(i, j);
			if ((type == TSP_CH_UNKNOWN) || (type == TSP_CH_UNUSED))
				continue;   // Ignore

			if ((buf16[idx] > min_spec) && (buf16[idx] < max_spec))
				continue;   // OK

			count += sprintf(msg, "%2d,%2d:%4d\n", i, j, buf16[idx]);
			strcat(buf, msg);

			err_cnt++;
		}
	}

	/* Check error count */
	if (err_cnt == 0)
		count += sprintf(msg, "OK\n");
	else
		count += sprintf(msg, "Fail, node count: %d\n", err_cnt);
	strcat(buf, msg);

	return count;
}
int print_cm_key_slope_result(s16 *buf16, char *buf, bool print)
{
	int i, j;
	int type, idx;
	int count = 0;
	int min_spec, max_spec;
	int key_num = 0;
	s16 key_cm[5] = { 0, };
	s16 slope_result;

	char msg[128];

	CMCS_INFO *cmcs = (CMCS_INFO *)&ts_cmcs->cmcs;
	struct CMCS_SLOPE_INFO *spec = (struct CMCS_SLOPE_INFO *)&cmcs->slope;

	min_spec = spec->key_min;
	max_spec = spec->key_max;

	min_spec *= -1;
	if (print) {
		count = sprintf(msg, "Spec: %d ~ %d\n", min_spec, max_spec);
		strcat(buf, msg);
	}

	for (i = 0; i < cmcs->ch.tx_num; i++) {
		for (j = 0; j < cmcs->ch.rx_num; j++) {
			idx = (i * cmcs->ch.rx_num) + j;

			type = check_tsp_type(i, j);
			if (type == TSP_CH_KEY)
				key_cm[key_num++] = buf16[idx];
		}
	}

	/* Check key slope */
	slope_result = key_cm[0] - key_cm[1];

	if (print) {
		if ((slope_result > min_spec) && (slope_result < max_spec))
			count += sprintf(msg, "OK (%d)\n", slope_result);
		else
			count += sprintf(msg, "Fail (%d)\n", slope_result);
	} else {
		count += sprintf(msg, "%d\n",
				 (slope_result > 0 ? slope_result : -slope_result));
	}

	strcat(buf, msg);

	return count;
}
int print_cm_result(struct ist30xx_data *data, char *buf)
{
	int i, j;
	int type, idx, err_cnt = 0;
	int min_spec, max_spec;
	int count = 0;
	short cm;
	char msg[128];
	CMCS_INFO *cmcs = (CMCS_INFO *)&data->cmcs->cmcs;

	for (i = 0; i < cmcs->ch.tx_num; i++) {
		for (j = 0; j < cmcs->ch.rx_num; j++) {
			idx = (i * cmcs->ch.rx_num) + j;

			type = check_tsp_type(data, i, j);
			//tsp_info("CH: %d (%d, %d) - %d\n", idx, i, j, type);
			if ((type == TSP_CH_UNKNOWN) || (type == TSP_CH_UNUSED))
				continue;

			min_spec = max_spec = data->cmcs_buf->spec[idx];
			if (type == TSP_CH_SCREEN) {
				min_spec -= (min_spec * cmcs->spec_cm.screen_min / 100);
				max_spec += (min_spec * cmcs->spec_cm.screen_max / 100);
			} else {    // TSP_CH_KEY
				min_spec -= (min_spec * cmcs->spec_cm.key_min / 100);
				max_spec += (min_spec * cmcs->spec_cm.key_max / 100);
			}

			cm = data->cmcs_buf->cm[idx];
			if ((cm > min_spec) && (cm < max_spec))
				continue; // OK

			count += sprintf(msg, "%2d,%2d:%4d (%4d~%4d)\n",
					 i, j, cm, min_spec, max_spec);
			strcat(buf, msg);

			err_cnt++;
		}
	}

	/* Check error count */
	if (err_cnt == 0)
		count += sprintf(msg, "OK\n");
	else
		count += sprintf(msg, "Fail, node count: %d\n", err_cnt);
	strcat(buf, msg);

	return count;
}