Exemplo n.º 1
0
static int __devinit atmel_tsadcc_probe(struct platform_device *pdev)
{
    struct atmel_tsadcc	*ts_dev;
    struct input_dev	*input_dev;
    struct resource		*res;
    int		err = 0;
    unsigned int	prsc;
    unsigned int	reg;

    res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    if (!res) {
        dev_err(&pdev->dev, "no mmio resource defined.\n");
        return -ENXIO;
    }

    /* Allocate memory for device */
    ts_dev = kzalloc(sizeof(struct atmel_tsadcc), GFP_KERNEL);
    if (!ts_dev) {
        dev_err(&pdev->dev, "failed to allocate memory.\n");
        return -ENOMEM;
    }
    platform_set_drvdata(pdev, ts_dev);

    input_dev = input_allocate_device();
    if (!input_dev) {
        dev_err(&pdev->dev, "failed to allocate input device.\n");
        err = -EBUSY;
        goto err_free_mem;
    }

    ts_dev->irq = platform_get_irq(pdev, 0);
    if (ts_dev->irq < 0) {
        dev_err(&pdev->dev, "no irq ID is designated.\n");
        err = -ENODEV;
        goto err_free_dev;
    }

    if (!request_mem_region(res->start, resource_size(res),
                            "atmel tsadcc regs")) {
        dev_err(&pdev->dev, "resources is unavailable.\n");
        err = -EBUSY;
        goto err_free_dev;
    }

    tsc_base = ioremap(res->start, resource_size(res));
    if (!tsc_base) {
        dev_err(&pdev->dev, "failed to map registers.\n");
        err = -ENOMEM;
        goto err_release_mem;
    }

    err = request_irq(ts_dev->irq, atmel_tsadcc_interrupt, IRQF_DISABLED,
                      pdev->dev.driver->name, ts_dev);
    if (err) {
        dev_err(&pdev->dev, "failed to allocate irq.\n");
        goto err_unmap_regs;
    }

    ts_dev->clk = clk_get(&pdev->dev, "tsc_clk");
    if (IS_ERR(ts_dev->clk)) {
        dev_err(&pdev->dev, "failed to get ts_clk\n");
        err = PTR_ERR(ts_dev->clk);
        goto err_free_irq;
    }

    ts_dev->input = input_dev;
    ts_dev->bufferedmeasure = 0;

    snprintf(ts_dev->phys, sizeof(ts_dev->phys),
             "%s/input0", dev_name(&pdev->dev));

    input_dev->name = "atmel touch screen controller";
    input_dev->phys = ts_dev->phys;
    input_dev->dev.parent = &pdev->dev;

    input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
    input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);

    input_set_abs_params(input_dev, ABS_X, 0, 0x3FF, 0, 0);
    input_set_abs_params(input_dev, ABS_Y, 0, 0x3FF, 0, 0);

    /* clk_enable() always returns 0, no need to check it */
    clk_enable(ts_dev->clk);

    prsc = clk_get_rate(ts_dev->clk);
    dev_info(&pdev->dev, "Master clock is set at: %d Hz\n", prsc);

    prsc = prsc / ADC_CLOCK / 2 - 1;

    reg = ATMEL_TSADCC_TSAMOD_TS_ONLY_MODE		|
          ((0x00 << 5) & ATMEL_TSADCC_SLEEP)	|	/* Normal Mode */
          ((0x01 << 6) & ATMEL_TSADCC_PENDET)	|	/* Enable Pen Detect */
          ((prsc << 8) & ATMEL_TSADCC_PRESCAL)	|	/* PRESCAL */
          ((0x13 << 16) & ATMEL_TSADCC_STARTUP)	|	/* STARTUP */
          ((0x0F << 28) & ATMEL_TSADCC_PENDBC);		/* PENDBC */

    atmel_tsadcc_write(ATMEL_TSADCC_CR, ATMEL_TSADCC_SWRST);
    atmel_tsadcc_write(ATMEL_TSADCC_MR, reg);
    atmel_tsadcc_write(ATMEL_TSADCC_TRGR, ATMEL_TSADCC_TRGMOD_NONE);
    atmel_tsadcc_write(ATMEL_TSADCC_TSR, (0x3 << 24) & ATMEL_TSADCC_TSSHTIM);

    atmel_tsadcc_read(ATMEL_TSADCC_SR);
    atmel_tsadcc_write(ATMEL_TSADCC_IER, ATMEL_TSADCC_PENCNT);

    /* All went ok, so register to the input system */
    err = input_register_device(input_dev);
    if (err)
        goto err_fail;

    return 0;

err_fail:
    clk_disable(ts_dev->clk);
    clk_put(ts_dev->clk);
err_free_irq:
    free_irq(ts_dev->irq, ts_dev);
err_unmap_regs:
    iounmap(tsc_base);
err_release_mem:
    release_mem_region(res->start, resource_size(res));
err_free_dev:
    input_free_device(ts_dev->input);
err_free_mem:
    kfree(ts_dev);
    return err;
}
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        
	}
Exemplo n.º 3
0
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;

    unsigned int status;
    unsigned int reg;

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

    if (status & ATMEL_TSADCC_NOCNT) {
        /* Contact lost */
        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_EOC(3) | ATMEL_TSADCC_NOCNT);
        atmel_tsadcc_write(ATMEL_TSADCC_IER, ATMEL_TSADCC_PENCNT);

        input_report_key(input_dev, BTN_TOUCH, 0);
        ts_dev->bufferedmeasure = 0;
        input_sync(input_dev);

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

        atmel_tsadcc_write(ATMEL_TSADCC_IDR, ATMEL_TSADCC_PENCNT);
        atmel_tsadcc_write(ATMEL_TSADCC_MR, reg);
        atmel_tsadcc_write(ATMEL_TSADCC_IER,
                           ATMEL_TSADCC_EOC(3) | ATMEL_TSADCC_NOCNT);
        atmel_tsadcc_write(ATMEL_TSADCC_TRGR,
                           ATMEL_TSADCC_TRGMOD_PERIOD | (0x0FFF << 16));

    } else if (status & ATMEL_TSADCC_EOC(3)) {
        /* Conversion finished */

        if (ts_dev->bufferedmeasure) {
            /* Last measurement is always discarded, since it can
             * be erroneous.
             * Always report previous measurement */
            input_report_abs(input_dev, ABS_X, ts_dev->prev_absx);
            input_report_abs(input_dev, ABS_Y, ts_dev->prev_absy);
            input_report_key(input_dev, BTN_TOUCH, 1);
            input_sync(input_dev);
        } else
            ts_dev->bufferedmeasure = 1;

        /* Now make new measurement */
        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);
    }

    return IRQ_HANDLED;
}
Exemplo n.º 4
0
static int __devinit atmel_tsadcc_probe(struct platform_device *pdev)
{
	struct atmel_tsadcc	*ts_dev;
	struct input_dev	*input_dev;
	struct resource		*res;
	struct at91_tsadcc_data *pdata = pdev->dev.platform_data;
	int		err = 0;
	unsigned int	prsc;
	unsigned int	reg;

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res) {
		dev_err(&pdev->dev, "no mmio resource defined.\n");
		return -ENXIO;
	}

	/* Allocate memory for device */
	ts_dev = kzalloc(sizeof(struct atmel_tsadcc), GFP_KERNEL);
	if (!ts_dev) {
		dev_err(&pdev->dev, "failed to allocate memory.\n");
		return -ENOMEM;
	}
	platform_set_drvdata(pdev, ts_dev);

	input_dev = input_allocate_device();
	if (!input_dev) {
		dev_err(&pdev->dev, "failed to allocate input device.\n");
		err = -EBUSY;
		goto err_free_mem;
	}

	ts_dev->irq = platform_get_irq(pdev, 0);
	if (ts_dev->irq < 0) {
		dev_err(&pdev->dev, "no irq ID is designated.\n");
		err = -ENODEV;
		goto err_free_dev;
	}

	if (!request_mem_region(res->start, resource_size(res),
				"atmel tsadcc regs")) {
		dev_err(&pdev->dev, "resources is unavailable.\n");
		err = -EBUSY;
		goto err_free_dev;
	}

	tsc_base = ioremap(res->start, resource_size(res));
	if (!tsc_base) {
		dev_err(&pdev->dev, "failed to map registers.\n");
		err = -ENOMEM;
		goto err_release_mem;
	}

	err = request_irq(ts_dev->irq, atmel_tsadcc_interrupt, IRQF_DISABLED,
			pdev->dev.driver->name, ts_dev);
	if (err) {
		dev_err(&pdev->dev, "failed to allocate irq.\n");
		goto err_unmap_regs;
	}

	ts_dev->clk = clk_get(&pdev->dev, "tsc_clk");
	if (IS_ERR(ts_dev->clk)) {
		dev_err(&pdev->dev, "failed to get ts_clk\n");
		err = PTR_ERR(ts_dev->clk);
		goto err_free_irq;
	}

	ts_dev->input = input_dev;
	ts_dev->bufferedmeasure = 0;

	snprintf(ts_dev->phys, sizeof(ts_dev->phys),
		 "%s/input0", dev_name(&pdev->dev));

	input_dev->name = "atmel touch screen controller";
	input_dev->phys = ts_dev->phys;
	input_dev->dev.parent = &pdev->dev;

	__set_bit(EV_ABS, input_dev->evbit);
	input_set_abs_params(input_dev, ABS_X, 0, 0x3FF, 0, 0);
	input_set_abs_params(input_dev, ABS_Y, 0, 0x3FF, 0, 0);

	input_set_capability(input_dev, EV_KEY, BTN_TOUCH);

	/* clk_enable() always returns 0, no need to check it */
	clk_enable(ts_dev->clk);

	prsc = clk_get_rate(ts_dev->clk);
	dev_info(&pdev->dev, "Master clock is set at: %d Hz\n", prsc);

	if (!pdata)
		goto err_fail;

	if (!pdata->adc_clock)
		pdata->adc_clock = ADC_DEFAULT_CLOCK;

	prsc = (prsc / (2 * pdata->adc_clock)) - 1;

	/* saturate if this value is too high */
	if (cpu_is_at91sam9rl()) {
		if (prsc > PRESCALER_VAL(ATMEL_TSADCC_PRESCAL))
			prsc = PRESCALER_VAL(ATMEL_TSADCC_PRESCAL);
	} else {
		if (prsc > PRESCALER_VAL(ATMEL_TSADCC_EPRESCAL))
			prsc = PRESCALER_VAL(ATMEL_TSADCC_EPRESCAL);
	}

	dev_info(&pdev->dev, "Prescaler is set at: %d\n", prsc);

	reg = ATMEL_TSADCC_TSAMOD_TS_ONLY_MODE		|
		((0x00 << 5) & ATMEL_TSADCC_SLEEP)	|	/* Normal Mode */
		((0x01 << 6) & ATMEL_TSADCC_PENDET)	|	/* Enable Pen Detect */
		(prsc << 8)				|
		((0x26 << 16) & ATMEL_TSADCC_STARTUP)	|
		((pdata->pendet_debounce << 28) & ATMEL_TSADCC_PENDBC);

	atmel_tsadcc_write(ATMEL_TSADCC_CR, ATMEL_TSADCC_SWRST);
	atmel_tsadcc_write(ATMEL_TSADCC_MR, reg);
	atmel_tsadcc_write(ATMEL_TSADCC_TRGR, ATMEL_TSADCC_TRGMOD_NONE);
	atmel_tsadcc_write(ATMEL_TSADCC_TSR,
		(pdata->ts_sample_hold_time << 24) & ATMEL_TSADCC_TSSHTIM);

	atmel_tsadcc_read(ATMEL_TSADCC_SR);
	atmel_tsadcc_write(ATMEL_TSADCC_IER, ATMEL_TSADCC_PENCNT);

	/* All went ok, so register to the input system */
	err = input_register_device(input_dev);
	if (err)
		goto err_fail;

	return 0;

err_fail:
	clk_disable(ts_dev->clk);
	clk_put(ts_dev->clk);
err_free_irq:
	free_irq(ts_dev->irq, ts_dev);
err_unmap_regs:
	iounmap(tsc_base);
err_release_mem:
	release_mem_region(res->start, resource_size(res));
err_free_dev:
	input_free_device(input_dev);
err_free_mem:
	kfree(ts_dev);
	return err;
}