int fpc1020_capture_wait_finger_down(fpc1020_data_t *fpc1020)
{
    int error = 0;
    int thold = 32;
    int addthred = 30;

    if( fpc1020->setup.finger_auto_threshold ){
        error = fpc1020_read_irq(fpc1020, true);
        if (error < 0)
            goto out_error;
        error = fpc1020_cmd(fpc1020,
                FPC1020_CMD_FINGER_PRESENT_QUERY,
                FPC_1020_IRQ_REG_BIT_COMMAND_DONE);
        if (error < 0)
            goto out_error;
        error = fpc1020_capture_set_crop(fpc1020,fpc1020->setup.wakeup_detect_cols[0],1,fpc1020->setup.wakeup_detect_rows[0],8);
        if (error < 0)
            goto out_error;
        error = cal_thredhold(fpc1020);
        if (error < 0)
            goto out_error;
        thold = error;
        error = fpc1020_capture_set_crop(fpc1020,fpc1020->setup.wakeup_detect_cols[1],1,fpc1020->setup.wakeup_detect_rows[1],8);
        if (error < 0)
            goto out_error;
        error = cal_thredhold(fpc1020);
        if (error < 0)
            goto out_error;
        if(error > thold)
            thold = error;
        thold += addthred;
        if(thold < fpc1020->fp_thredhold && thold >= addthred)
            fpc1020->fp_thredhold = thold;
        printk("fingerprint fp_thredhold =%d default_hold=%d det1=[%d,1,%d,8] det2=[%d,1,%d,8]\n",\
                fpc1020->fp_thredhold,fpc1020->setup.finger_detect_threshold,\
                fpc1020->setup.wakeup_detect_cols[0],fpc1020->setup.wakeup_detect_rows[0],\
                fpc1020->setup.wakeup_detect_cols[1],fpc1020->setup.wakeup_detect_rows[1]);
        fpc1020_wake_up(fpc1020);
        fpc1020_write_sensor_setup(fpc1020);
    }

    error = fpc1020_wait_finger_present(fpc1020);

     fpc1020_read_irq(fpc1020, true);

out_error:
    return (error >= 0) ? 0 : error;
}
int fpc1020_capture_set_crop_selftest(fpc1020_data_t *fpc1020)
{
    int first_column;
    int num_columns;
    int first_row;
    int num_rows;
    int error;

       switch(fpc1020->chip.type){

          case FPC1020_CHIP_1020A:
               first_column=0;
               num_columns=24;
               first_row=0;
               num_rows=192;
               break;
          case FPC1020_CHIP_1021A:
          case FPC1020_CHIP_1021B:
               first_column=0;
               num_columns=20;
               first_row=0;
               num_rows=160;
               break;
          case FPC1020_CHIP_1150A:
          case FPC1020_CHIP_1150B:
               first_column=0;
               num_columns=10;
               first_row=0;
               num_rows=208;
               break;
         default:
               first_column=0;
               num_columns=20;
               first_row=0;
               num_rows=160;
               break;
      }

    error = fpc1020_capture_set_crop(fpc1020,first_column,num_columns,first_row,num_rows);

    return error;
}
Beispiel #3
0
int fpc1020_capture_task(fpc1020_data_t *fpc1020)
{
	struct timespec ts_t1, ts_t2, ts_t3, ts_delta;
	int time_settings_us[FPC1020_BUFFER_MAX_IMAGES];
	int time_capture_us[FPC1020_BUFFER_MAX_IMAGES];
	int time_capture_sum_us;
	int error = 0;
	bool wait_finger_down = false;
	bool wait_finger_up = false;
	bool adjust_settings;
	fpc1020_capture_mode_t mode = fpc1020->capture.current_mode;
	int current_capture, capture_count;
	int image_offset;
	size_t image_byte_size;

	fpc1020->capture.state = FPC1020_CAPTURE_STATE_WRITE_SETTINGS;

	error = fpc1020_wake_up(fpc1020);
	if (error < 0)
		goto out_error;

	switch (mode) {
	case FPC1020_MODE_WAIT_AND_CAPTURE:
		wait_finger_down =
		wait_finger_up   = true;

	case FPC1020_MODE_SINGLE_CAPTURE:
	case FPC1020_MODE_SINGLE_CAPTURE_CAL:
		capture_count = fpc1020->setup.capture_count;
		adjust_settings = true;
		error = fpc1020_write_capture_setup(fpc1020);
		break;

	case FPC1020_MODE_CHECKERBOARD_TEST_NORM:
		capture_count = 1;
		adjust_settings = false;
		error = fpc1020_write_cb_test_setup(fpc1020, false);
		break;

	case FPC1020_MODE_CHECKERBOARD_TEST_INV:
		capture_count = 1;
		adjust_settings = false;
		error = fpc1020_write_cb_test_setup(fpc1020, true);
		break;

	case FPC1020_MODE_BOARD_TEST_ONE:
		capture_count = 1;
		adjust_settings = false;
		error = fpc1020_write_test_setup(fpc1020, 0xffff);
		break;

	case FPC1020_MODE_BOARD_TEST_ZERO:
		capture_count = 1;
		adjust_settings = false;
		error = fpc1020_write_test_setup(fpc1020, 0x0000);
		break;

	case FPC1020_MODE_WAIT_FINGER_DOWN:
		wait_finger_down = true;
		capture_count = 0;
		adjust_settings = false;
		error = fpc1020_write_capture_setup(fpc1020);
		break;

	case FPC1020_MODE_WAIT_FINGER_UP:
		wait_finger_up = true;
		capture_count = 0;
		adjust_settings = false;
		error = fpc1020_write_capture_setup(fpc1020);
		break;

	case FPC1020_MODE_IDLE:
	default:
		capture_count = 0;
		adjust_settings = false;
		error = -EINVAL;
		break;
	}

	if (error < 0)
		goto out_error;

	error = fpc1020_capture_set_crop(fpc1020,
					fpc1020->setup.capture_col_start,
					fpc1020->setup.capture_col_groups,
					fpc1020->setup.capture_row_start,
					fpc1020->setup.capture_row_count);
	if (error < 0)
		goto out_error;

	image_byte_size = fpc1020_calc_image_size(fpc1020);

	dev_dbg(&fpc1020->spi->dev,
		"Start capture, mode %d, (%d frames)\n",
		mode,
		capture_count);

	if (!wait_finger_down)
		fpc1020->capture.deferred_finger_up = false;

	if (wait_finger_down) {
		error = fpc1020_capture_finger_detect_settings(fpc1020);
		if (error < 0)
			goto out_error;
	}

	if (wait_finger_down && fpc1020->capture.deferred_finger_up) {
		fpc1020->capture.state =
				FPC1020_CAPTURE_STATE_WAIT_FOR_FINGER_UP;

		dev_dbg(&fpc1020->spi->dev, "Waiting for (deferred) finger up\n");

		error = fpc1020_capture_wait_finger_up(fpc1020);

		if (error < 0)
			goto out_error;

		dev_dbg(&fpc1020->spi->dev, "Finger up\n");

		fpc1020->capture.deferred_finger_up = false;
	}

	if (wait_finger_down) {
		fpc1020->capture.state =
				FPC1020_CAPTURE_STATE_WAIT_FOR_FINGER_DOWN;

		error = fpc1020_capture_wait_finger_down(fpc1020);

		if (error < 0)
			goto out_error;

		dev_dbg(&fpc1020->spi->dev, "Finger down\n");

		if (mode == FPC1020_MODE_WAIT_FINGER_DOWN) {

			fpc1020->capture.available_bytes = 4;
			fpc1020->huge_buffer[0] = 'F';
			fpc1020->huge_buffer[1] = ':';
			fpc1020->huge_buffer[2] = 'D';
			fpc1020->huge_buffer[3] = 'N';
		}
	}

	current_capture = 0;
	image_offset = 0;

	fpc1020->diag.last_capture_time = 0;

	if (mode == FPC1020_MODE_SINGLE_CAPTURE_CAL) {
		error = fpc1020_capture_set_sample_mode(fpc1020, true);
		if (error)
			goto out_error;
	}

	while (capture_count && (error >= 0))
	{
		getnstimeofday(&ts_t1);

		fpc1020->capture.state = FPC1020_CAPTURE_STATE_ACQUIRE;

		dev_dbg(&fpc1020->spi->dev,
			"Capture, frame #%d \n",
			current_capture + 1);

		error =	(!adjust_settings) ? 0 :
			fpc1020_capture_settings(fpc1020, current_capture);

		if (error < 0)
			goto out_error;

		getnstimeofday(&ts_t2);

		error = fpc1020_cmd(fpc1020,
				FPC1020_CMD_CAPTURE_IMAGE,
				FPC_1020_IRQ_REG_BIT_FIFO_NEW_DATA);

		if (error < 0)
			goto out_error;

		fpc1020->capture.state = FPC1020_CAPTURE_STATE_FETCH;

		error = fpc1020_fetch_image(fpc1020,
					    fpc1020->huge_buffer,
					    image_offset,
					    image_byte_size,
					    (size_t)fpc1020->huge_buffer_size);
		if (error < 0)
			goto out_error;

		fpc1020->capture.available_bytes += (error >= 0) ?
							(int)image_byte_size : 0;
		fpc1020->capture.last_error = error;

		getnstimeofday(&ts_t3);

		ts_delta = timespec_sub(ts_t2, ts_t1);
		time_settings_us[current_capture] =
			ts_delta.tv_sec * USEC_PER_SEC +
			(ts_delta.tv_nsec / NSEC_PER_USEC);

		ts_delta = timespec_sub(ts_t3, ts_t2);
		time_capture_us[current_capture] =
			ts_delta.tv_sec * USEC_PER_SEC +
			(ts_delta.tv_nsec / NSEC_PER_USEC);

		capture_count--;
		current_capture++;
		image_offset += (int)image_byte_size;
	}


	error = fpc1020_capture_set_sample_mode(fpc1020, false);
	if (error)
		goto out_error;


	if (mode != FPC1020_MODE_WAIT_FINGER_UP)
		wake_up_interruptible(&fpc1020->capture.wq_data_avail);

	if (wait_finger_up) {
		fpc1020->capture.state =
				FPC1020_CAPTURE_STATE_WAIT_FOR_FINGER_UP;

		error = fpc1020_capture_finger_detect_settings(fpc1020);
		if (error < 0)
			goto out_error;

		error = fpc1020_capture_wait_finger_up(fpc1020);

		if(error == -EINTR) {
			dev_dbg(&fpc1020->spi->dev, "Finger up check interrupted\n");
			fpc1020->capture.deferred_finger_up = true;
			goto out_interrupted;

		} else if (error < 0)
			goto out_error;

		if (mode == FPC1020_MODE_WAIT_FINGER_UP) {
			fpc1020->capture.available_bytes = 4;
			fpc1020->huge_buffer[0] = 'F';
			fpc1020->huge_buffer[1] = ':';
			fpc1020->huge_buffer[2] = 'U';
			fpc1020->huge_buffer[3] = 'P';

			wake_up_interruptible(&fpc1020->capture.wq_data_avail);
		}

		dev_dbg(&fpc1020->spi->dev, "Finger up\n");
	}

out_interrupted:

	capture_count = 0;
	time_capture_sum_us = 0;

	while (current_capture){

		current_capture--;

		dev_dbg(&fpc1020->spi->dev,
			"Frame #%d acq. time %d+%d=%d (us)\n",
			capture_count + 1,
			time_settings_us[capture_count],
			time_capture_us[capture_count],
			time_settings_us[capture_count] +
				time_capture_us[capture_count]);

		time_capture_sum_us += time_settings_us[capture_count];
		time_capture_sum_us += time_capture_us[capture_count];

		capture_count++;
	}
	fpc1020->diag.last_capture_time = time_capture_sum_us / 1000;

	dev_dbg(&fpc1020->spi->dev,
		"Total acq. time %d (us)\n", time_capture_sum_us);

out_error:
	fpc1020->capture.last_error = error;

	if (error) {
		fpc1020->capture.state = FPC1020_CAPTURE_STATE_FAILED;
		dev_err(&fpc1020->spi->dev, "%s %s %d\n", __func__,
			(error == -EINTR) ? "TERMINATED" : "FAILED", error);
	} else {
		fpc1020->capture.state = FPC1020_CAPTURE_STATE_COMPLETED;
		dev_dbg(&fpc1020->spi->dev, "%s OK\n", __func__);
	}
	return error;
}
/* -------------------------------------------------------------------- */
int fpc1020_capture_task(fpc1020_data_t *fpc1020)
{
    int error = 0;
    bool wait_finger_down = false;
    bool wait_finger_up = false;
    bool adjust_settings;
    fpc1020_capture_mode_t mode = fpc1020->capture.current_mode;
    int current_capture, capture_count;
    int image_offset;

    size_t image_byte_size;

    fpc1020->capture.state = FPC1020_CAPTURE_STATE_WRITE_SETTINGS;

    error = fpc1020_wake_up(fpc1020);
    if (error < 0)
        goto out_error;
    switch (mode) {
    case FPC1020_MODE_WAIT_AND_CAPTURE:
        wait_finger_down =
        wait_finger_up   = true;

    case FPC1020_MODE_SINGLE_CAPTURE:
    case FPC1020_MODE_WAIT_FINGER_UP_AND_CAPTURE:
        capture_count = fpc1020->setup.capture_count;
        adjust_settings = true;
        error = fpc1020_write_capture_setup(fpc1020);
        break;

    case FPC1020_MODE_CHECKERBOARD_TEST_NORM:
        capture_count = 1;
        adjust_settings = false;
        error = fpc1020_write_test_setup(fpc1020, 0xaa55);
        break;

    case FPC1020_MODE_CHECKERBOARD_TEST_INV:
        capture_count = 1;
        adjust_settings = false;
        error = fpc1020_write_test_setup(fpc1020, 0x55aa);
        break;

    case FPC1020_MODE_BOARD_TEST_ONE:
        capture_count = 1;
        adjust_settings = false;
        error = fpc1020_write_test_setup(fpc1020, 0xffff);
        break;

    case FPC1020_MODE_BOARD_TEST_ZERO:
        capture_count = 1;
        adjust_settings = false;
        error = fpc1020_write_test_setup(fpc1020, 0x0000);
        break;

    case FPC1020_MODE_WAIT_FINGER_DOWN:
        wait_finger_down = true;
        capture_count = 0;
        adjust_settings = false;
        error = fpc1020_write_capture_setup(fpc1020);
        break;

    case FPC1020_MODE_WAIT_FINGER_UP:
        wait_finger_up = true;
        capture_count = 0;
        adjust_settings = false;
        error = fpc1020_write_capture_setup(fpc1020);
        break;

    case FPC1020_MODE_IDLE:
    default:
        capture_count = 0;
        adjust_settings = false;
        error = -EINVAL;
        break;
    }

    if (error < 0)
        goto out_error;

    if(mode == FPC1020_MODE_CHECKERBOARD_TEST_NORM ||
            mode == FPC1020_MODE_CHECKERBOARD_TEST_INV ||
            mode == FPC1020_MODE_BOARD_TEST_ONE ||
            mode == FPC1020_MODE_BOARD_TEST_ZERO){
        error = fpc1020_capture_set_crop_selftest(fpc1020);
        image_byte_size = fpc1020_calc_image_size_selftest(fpc1020);
    }
    else{
        error = fpc1020_capture_set_crop(fpc1020,
                    fpc1020->setup.capture_col_start,
                    fpc1020->setup.capture_col_groups,
                    fpc1020->setup.capture_row_start,
                    fpc1020->setup.capture_row_count);
        image_byte_size = fpc1020_calc_image_size(fpc1020);
    }
    if (error < 0)
        goto out_error;

    dev_dbg(&fpc1020->spi->dev,
        "Start capture, mode %d, (%d frames)\n",
        mode,
        capture_count);

    if (wait_finger_down) {
        fpc1020->capture.state =
                FPC1020_CAPTURE_STATE_WAIT_FOR_FINGER_DOWN;

        error = fpc1020_capture_wait_finger_down(fpc1020);

        if (error < 0)
            goto out_error;

        dev_dbg(&fpc1020->spi->dev, "Finger down\n");

        if (mode == FPC1020_MODE_WAIT_FINGER_DOWN) {

            fpc1020->capture.available_bytes = 4;
            fpc1020->huge_buffer[0] = 'F';
            fpc1020->huge_buffer[1] = ':';
            fpc1020->huge_buffer[2] = 'D';
            fpc1020->huge_buffer[3] = 'N';
        }
    }

    current_capture = 0;
    image_offset = 0;
    if(mode != FPC1020_MODE_WAIT_FINGER_DOWN && mode !=FPC1020_MODE_WAIT_FINGER_UP){
        while (capture_count && (error >= 0))
        {
            fpc1020->capture.state = FPC1020_CAPTURE_STATE_ACQUIRE;

            dev_dbg(&fpc1020->spi->dev,"Capture, frame %d \n",current_capture + 1);

            error = (!adjust_settings) ? 0 :
                fpc1020_capture_settings(fpc1020, current_capture);

            if (error < 0)
                goto out_error;

            error = fpc1020_cmd(fpc1020,
                    FPC1020_CMD_CAPTURE_IMAGE,
                    FPC_1020_IRQ_REG_BIT_FIFO_NEW_DATA);

            if (error < 0)
                goto out_error;

            fpc1020->capture.state = FPC1020_CAPTURE_STATE_FETCH;

            error = fpc1020_fetch_image(fpc1020,
                            fpc1020->huge_buffer,
                            image_offset,
                            image_byte_size,
                            (size_t)fpc1020->huge_buffer_size);
            if (error < 0)
                goto out_error;

            fpc1020->capture.available_bytes += (int)image_byte_size;
            fpc1020->capture.last_error = error;

            capture_count--;
            current_capture++;
            image_offset += (int)image_byte_size;
        }
    }
    if (mode != FPC1020_MODE_WAIT_FINGER_UP)
        wake_up_interruptible(&fpc1020->capture.wq_data_avail);

    if (wait_finger_up) {
        fpc1020->capture.state =
                FPC1020_CAPTURE_STATE_WAIT_FOR_FINGER_UP;

        error = fpc1020_capture_wait_finger_up(fpc1020);
        if (error < 0)
            goto out_error;

        if (mode == FPC1020_MODE_WAIT_FINGER_UP) {
            fpc1020->capture.available_bytes = 4;
            fpc1020->huge_buffer[0] = 'F';
            fpc1020->huge_buffer[1] = ':';
            fpc1020->huge_buffer[2] = 'U';
            fpc1020->huge_buffer[3] = 'P';

            wake_up_interruptible(&fpc1020->capture.wq_data_avail);
        }

        dev_dbg(&fpc1020->spi->dev, "Finger up\n");
    }

out_error:
    fpc1020->capture.last_error = error;

    if (error < 0) {
        fpc1020->capture.state = FPC1020_CAPTURE_STATE_FAILED;
        dev_err(&fpc1020->spi->dev, "%s FAILED %d\n", __func__, error);
    } else {
        fpc1020->capture.state = FPC1020_CAPTURE_STATE_COMPLETED;
        dev_err(&fpc1020->spi->dev, "%s OK\n", __func__);
    }
    return error;
}
/* -------------------------------------------------------------------- */
static int fpc1020_write_nav_setup(fpc1020_data_t* fpc1020)
{
    const int mux = 2;
    int error = 0;
    u16 temp_u16;
    u32 temp_u32;
    u8 temp_u8;
    fpc1020_reg_access_t reg;

    dev_dbg(&fpc1020->spi->dev, "%s %d\n", __func__, mux);
#if 1
    error = fpc1020_wake_up(fpc1020);
    if (error)
    { goto out; }

    error = fpc1020_write_sensor_setup(fpc1020);
    if (error)
    { goto out; }
#endif

#if 0
    temp_u16 = fpc1020->setup.adc_shift[mux];
    temp_u16 <<= 8;
    temp_u16 |= fpc1020->setup.adc_gain[mux];
#else
    temp_u16 = 8;
    temp_u16 <<= 8;
    temp_u16 |= 5;
#endif
    FPC1020_MK_REG_WRITE(reg, FPC102X_REG_ADC_SHIFT_GAIN, &temp_u16);
    error = fpc1020_reg_access(fpc1020, &reg);
    if (error)
    { goto out; }

    //temp_u16 = fpc1020->setup.pxl_ctrl[mux];
    temp_u16 = 0x0f1f;
    FPC1020_MK_REG_WRITE(reg, FPC102X_REG_PXL_CTRL, &temp_u16);
    error = fpc1020_reg_access(fpc1020, &reg);
    if (error)
    { goto out; }

    error = fpc1020_capture_set_crop(fpc1020,
                                     NAV_IMG_CROP_X / fpc1020->chip.adc_group_size,
                                     NAV_IMG_CROP_W / fpc1020->chip.adc_group_size, NAV_IMG_CROP_Y,
                                     NAV_IMG_CROP_H);
    if (error)
    { goto out; }

    // Setup skipping of rows
    switch (NAV_IMG_ROW_SKIP)
    {
        case 1:
            temp_u32 = 0;
            break;
        case 2:
            temp_u32 = 1;
            break;
        case 4:
            temp_u32 = 2;
            break;
        case 8:
            temp_u32 = 3;
            break;
        default:
            error = -EINVAL;
            break;
    }
    if (error)
    { goto out; }

    temp_u32 <<= 8;

    // Setup masking of columns
    switch (NAV_IMG_COL_MASK)
    {
        case 1:
            temp_u32 |= 0xff;
            break;
        case 2:
            temp_u32 |= 0xcc;
            break;
        case 4:
            temp_u32 |= 0x88;
            break;
        case 8:
            temp_u32 |= 0x80;
            break;
        default:
            error = -EINVAL;
            break;
    }
    if (error)
    { goto out; }

    temp_u32 <<= 8;
    temp_u32 |= 0; // No multisampling
    FPC1020_MK_REG_WRITE(reg, FPC102X_REG_IMG_SMPL_SETUP, &temp_u32);
    error = fpc1020_reg_access(fpc1020, &reg);
    if (error)
    { goto out; }

    temp_u8 = 0x08;
    FPC1020_MK_REG_WRITE(reg, FPC1020_REG_FNGR_DET_THRES, &temp_u8);
    error = fpc1020_reg_access(fpc1020, &reg);

    dev_dbg(&fpc1020->spi->dev, "%s, (%d, %d, %d, %d)\n", __func__,
            fpc1020->nav.image_nav_col_start, fpc1020->nav.image_nav_col_groups,
            fpc1020->nav.image_nav_row_start, fpc1020->nav.image_nav_row_count);

out:
    return error;
}