static ssize_t calibration_store(struct device *dev,
		struct device_attribute *attr, const char *buf, size_t count)
{
	bool do_calib;
	int ret;
	struct ssp_data *data = dev_get_drvdata(dev);

	if (sysfs_streq(buf, "1"))
		do_calib = true;
	else if (sysfs_streq(buf, "0"))
		do_calib = false;
	else {
		pr_info("[SSP]: %s - invalid value %d\n", __func__, *buf);
		return -EINVAL;
	}

	ret = do_calibrate(data, do_calib);
	if (ret < 0) {
		pr_err("[SSP]: %s - do_calibrate fail(%d)\n",
			__func__, ret);
		goto exit;
	}

	ret = save_caldata(data);
	if (ret < 0) {
		pr_err("[SSP]: %s - save_caldata fail(%d)\n",
			__func__, ret);
		goto exit;
	}

	pr_info("[SSP]: %s - %u success!\n", __func__, do_calib);

exit:

	if (data->gripcal.cap_main && (ret >= 0))
		data->gripcal.calibrated = true;
	else
		data->gripcal.calibrated = false;

	return count;
}
static irqreturn_t atmel_tsadcc_interrupt(int irq, void *dev)
{
	struct atmel_tsadcc	*ts_dev = (struct atmel_tsadcc *)dev;
	struct input_dev	*input_dev = ts_dev->input;
	struct at91_tsadcc_data *pdata = input_dev->dev.parent->platform_data;
	static int count = 0;

	unsigned int status;
	unsigned int reg;
	unsigned int x, y;
	unsigned int z1, z2;
	unsigned int Rxp = 1;
	unsigned int factor = 1000;

#if defined(CONFIG_MACH_AT91SAM9M10G45EK) || defined(CONFIG_MACH_AT91SAM9G45EKES) || defined(CONFIG_MACH_AT91SAM9M10EKES)
	static unsigned int point_buffer_x[COUNT_MAX];
	static unsigned int point_buffer_y[COUNT_MAX];
#endif

	status = atmel_tsadcc_read(ATMEL_TSADCC_SR);
	status &= atmel_tsadcc_read(ATMEL_TSADCC_IMR);

	if (status & ATMEL_TSADCC_NOCNT) {
		/* Contact lost */
		if (cpu_has_9x5_adc()) {
			/* 9X5 using TSMR to set PENDBC time */
			reg = atmel_tsadcc_read(ATMEL_TSADCC_TSMR) | ((pdata->pendet_debounce << 28) & ATMEL_TSADCC_PENDBC);
			atmel_tsadcc_write(ATMEL_TSADCC_TSMR, reg);
		} else {
			reg = atmel_tsadcc_read(ATMEL_TSADCC_MR) | ATMEL_TSADCC_PENDBC;
			atmel_tsadcc_write(ATMEL_TSADCC_MR, reg);
		}
		atmel_tsadcc_write(ATMEL_TSADCC_TRGR, ATMEL_TSADCC_TRGMOD_NONE);
		atmel_tsadcc_write(ATMEL_TSADCC_IDR,
				   ATMEL_TSADCC_CONVERSION_END | ATMEL_TSADCC_NOCNT);
		atmel_tsadcc_write(ATMEL_TSADCC_IER, ATMEL_TSADCC_PENCNT);

		input_report_key(input_dev, BTN_TOUCH, 0);
		input_report_abs(input_dev, ABS_PRESSURE, 0);
		input_sync(input_dev);

	} else if (status & ATMEL_TSADCC_PENCNT) {
		/* Pen detected */
		if (cpu_has_9x5_adc()) {
			reg = atmel_tsadcc_read(ATMEL_TSADCC_TSMR);
			reg &= ~ATMEL_TSADCC_PENDBC;
			atmel_tsadcc_write(ATMEL_TSADCC_TSMR, reg);
		} else {
			reg = atmel_tsadcc_read(ATMEL_TSADCC_MR);
			reg &= ~ATMEL_TSADCC_PENDBC;
			atmel_tsadcc_write(ATMEL_TSADCC_MR, reg);
		}

		atmel_tsadcc_write(ATMEL_TSADCC_IDR, ATMEL_TSADCC_PENCNT);
		atmel_tsadcc_write(ATMEL_TSADCC_IER,
				   ATMEL_TSADCC_CONVERSION_END | ATMEL_TSADCC_NOCNT);
		if (cpu_has_9x5_adc()) {
		    atmel_tsadcc_write(ATMEL_TSADCC_TRGR,
				   ATMEL_TSADCC_TRGMOD_PERIOD | (0x00D0 << 16));
		}else{
		    atmel_tsadcc_write(ATMEL_TSADCC_TRGR,
				   ATMEL_TSADCC_TRGMOD_PERIOD | (trigger_period << 16));
		}

              count = 0;

	} else if ((status & ATMEL_TSADCC_CONVERSION_END) == ATMEL_TSADCC_CONVERSION_END) {
		/* Conversion finished */
		
		/* make new measurement */
 		if (cpu_has_9x5_adc()) {
            unsigned int xscale, yscale;
			
			/* calculate position */
			reg = atmel_tsadcc_read(ATMEL_TSADCC_XPOSR);
			ts_dev->prev_absx = (reg & ATMEL_TSADCC_XPOS) << 10;
			xscale = (reg & ATMEL_TSADCC_XSCALE) >> 16;
			ts_dev->prev_absx /= xscale ? xscale: 1;

			reg = atmel_tsadcc_read(ATMEL_TSADCC_YPOSR);
			ts_dev->prev_absy = (reg & ATMEL_TSADCC_YPOS) << 10;
			yscale = (reg & ATMEL_TSADCC_YSCALE) >> 16;
			ts_dev->prev_absy /= yscale ? yscale: 1 << 10;

            /* calculate the pressure */
			reg = atmel_tsadcc_read(ATMEL_TSADCC_PRESSR);
			z1 = reg & ATMEL_TSADCC_PRESSR_Z1;
			z2 = (reg & ATMEL_TSADCC_PRESSR_Z2) >> 16;

			if (z1 != 0)
				ts_dev->prev_absz = Rxp * (ts_dev->prev_absx * factor / 1024) * (z2 * factor / z1 - factor) / factor;
			else
				ts_dev->prev_absz = 0;

		} else {
			ts_dev->prev_absx = atmel_tsadcc_read(ATMEL_TSADCC_CDR3) << 10;
			ts_dev->prev_absx /= atmel_tsadcc_read(ATMEL_TSADCC_CDR2);

			ts_dev->prev_absy = atmel_tsadcc_read(ATMEL_TSADCC_CDR1) << 10;
			ts_dev->prev_absy /= atmel_tsadcc_read(ATMEL_TSADCC_CDR0);
		}

#if defined(CONFIG_MACH_AT91SAM9M10G45EK) || defined(CONFIG_MACH_AT91SAM9G45EKES) || defined(CONFIG_MACH_AT91SAM9M10EKES)
		if (count < COUNT_MAX) {
			point_buffer_x[count] = ts_dev->prev_absx;
			point_buffer_y[count] = ts_dev->prev_absy;
			count++;
		} else {
			
			count = 0;
			x =  do_filter(point_buffer_x, COUNT_MAX, COUNT_MAX * 3 / 4);
			y =  do_filter(point_buffer_y, COUNT_MAX, COUNT_MAX * 3 / 4);

			do_calibrate(&x,&y);
			input_report_abs(input_dev, ABS_X, x);
			input_report_abs(input_dev, ABS_Y, y);
			input_report_key(input_dev, BTN_TOUCH, 1);
			input_report_abs(input_dev, ABS_PRESSURE, 7500);
			input_sync(input_dev);
		}
#endif

#if defined(CONFIG_MACH_AT91SAM9X5EK)
				/* report measurement to input layer */
		if (ts_dev->prev_absz < ZTHRESHOLD) {
			dev_dbg(&input_dev->dev,
					"x = %d, y = %d, pressure = %d\n",
					ts_dev->prev_absx, ts_dev->prev_absy,
					ts_dev->prev_absz);
			x = ts_dev->prev_absx;
			y = ts_dev->prev_absy; 
			
			do_calibrate(&x,&y);		
			input_report_abs(input_dev, ABS_X, x);			
			input_report_abs(input_dev, ABS_Y, y);
			if (cpu_has_9x5_adc())
				input_report_abs(input_dev, ABS_PRESSURE, ts_dev->prev_absz);
			input_report_key(input_dev, BTN_TOUCH, 1);
			input_sync(input_dev);
		} else {
			dev_dbg(&input_dev->dev,
					"pressure too low: not reporting\n");
		}
#endif        
	}