elanspi: preliminary support for 04f3:3104

Also adds "quirk" flags to driver_data so other special case things
can be handled with less effort going forwards.
This commit is contained in:
Matthew Mirvish
2022-05-03 21:02:26 -04:00
parent eda8d13927
commit 46591d7bfa
2 changed files with 199 additions and 36 deletions

View File

@@ -63,6 +63,7 @@ struct _FpiDeviceElanSpi
guint16 gdac_step;
guint16 best_gdac;
guint16 best_meandiff;
guint16 target_mean;
} hv_data;
};
@@ -408,6 +409,10 @@ elanspi_determine_sensor (FpiDeviceElanSpi *self, GError **err)
self->frame_width = self->sensor_width;
self->frame_height = self->sensor_height > ELANSPI_MAX_FRAME_HEIGHT ? ELANSPI_MAX_FRAME_HEIGHT : self->sensor_height;
}
/* check x571 flag */
if (self->sensor_id == 0xe)
self->hv_data.target_mean = (fpi_device_get_driver_data (FP_DEVICE (self)) & ELANSPI_QUIRK_X571 ? ELANSPI_HV_X571_CALIBRATION_TARGET_MEAN : ELANSPI_HV_CALIBRATION_TARGET_MEAN);
}
static void
@@ -542,7 +547,7 @@ elanspi_write_regtable (FpiDeviceElanSpi *self, const struct elanspi_regtable *
for (int i = 0; table->entries[i].table; i += 1)
{
if (table->entries[i].sid == self->sensor_id)
if (table->entries[i].sid == self->sensor_id && table->entries[i].quirk == (fpi_device_get_driver_data (FP_DEVICE (self)) & ELANSPI_QUIRK_MASK))
{
starting_entry = table->entries[i].table;
break;
@@ -692,6 +697,8 @@ static void
elanspi_capture_hv_image_handler (FpiSpiTransfer *transfer, FpDevice *dev, gpointer unused_data, GError *error)
{
FpiDeviceElanSpi *self = FPI_DEVICE_ELANSPI (dev);
ptrdiff_t outptr = 0, inptr = 0;
guint16 value = 0;
if (error)
{
@@ -699,24 +706,39 @@ elanspi_capture_hv_image_handler (FpiSpiTransfer *transfer, FpDevice *dev, gpoin
return;
}
int i, outptr;
guint16 value = 0;
for (i = 0, outptr = 0; i < transfer->length_rd && outptr < (self->sensor_height * self->sensor_width * 2); i += 1)
if (fpi_device_get_driver_data (dev) & ELANSPI_QUIRK_X571)
{
if (transfer->buffer_rd[i] != 0xff)
/* decode image in x571 mode (just copy and fix endian) */
for (int y = 0; y < self->sensor_height; y += 1)
{
if (outptr % 2)
inptr += 2; /* 2 dummy bytes per line at start */
for (int x = 0; x < self->sensor_width; x += 1)
{
value <<= 8;
value |= transfer->buffer_rd[i];
self->last_image[outptr / 2] = value;
self->last_image[outptr / 2] = transfer->buffer_rd[inptr] + transfer->buffer_rd[inptr + 1] * 0x100;
inptr += 2;
outptr += 2;
}
else
}
}
else
{
/* decode image (normal case; with weird 0xff checks) */
for (inptr = 0, outptr = 0; inptr < transfer->length_rd && outptr < (self->sensor_height * self->sensor_width * 2); inptr += 1)
{
if (transfer->buffer_rd[inptr] != 0xff)
{
value = transfer->buffer_rd[i];
if (outptr % 2)
{
value <<= 8;
value |= transfer->buffer_rd[inptr];
self->last_image[outptr / 2] = value;
}
else
{
value = transfer->buffer_rd[inptr];
}
outptr += 1;
}
outptr += 1;
}
}
@@ -774,12 +796,14 @@ elanspi_capture_hv_handler (FpiSsm *ssm, FpDevice *dev)
return;
}
/* otherwise, read the image
* the hv sensors seem to use 128 bytes of padding(?) this is only tested on the 0xe sensors */
* the hv sensors seem to use variable-length padding(?) this is only tested on the 0xe sensors
*
* in the x571 mode, the padding appears to be disabled and it just has 2 bytes of junk */
xfer = fpi_spi_transfer_new (dev, self->spi_fd);
xfer->ssm = ssm;
fpi_spi_transfer_write (xfer, 2);
xfer->buffer_wr[0] = 0x10; /* receieve line */
fpi_spi_transfer_read (xfer, self->sensor_height * (self->sensor_width * 2 + 48));
xfer->buffer_wr[0] = 0x10; /* receieve line/image */
fpi_spi_transfer_read (xfer, self->sensor_height * (self->sensor_width * 2 + (fpi_device_get_driver_data (dev) & ELANSPI_QUIRK_X571 ? 2 : 48)));
fpi_spi_transfer_submit (xfer, fpi_device_get_cancellable (dev), elanspi_capture_hv_image_handler, NULL);
return;
}
@@ -873,7 +897,7 @@ elanspi_calibrate_hv_handler (FpiSsm *ssm, FpDevice *dev)
case ELANSPI_CALIBHV_PROCESS:
/* compute mean */
mean_diff = abs (elanspi_mean_image (self, self->last_image) - ELANSPI_HV_CALIBRATION_TARGET_MEAN);
mean_diff = abs (elanspi_mean_image (self, self->last_image) - self->hv_data.target_mean);
if (mean_diff < 100)
{
fp_dbg ("<calibhv> calibration ok (mdiff < 100 w/ gdac=%04x)", self->hv_data.gdac_value);
@@ -896,7 +920,7 @@ elanspi_calibrate_hv_handler (FpiSsm *ssm, FpDevice *dev)
return;
}
/* update gdac */
if (elanspi_mean_image (self, self->last_image) < ELANSPI_HV_CALIBRATION_TARGET_MEAN)
if (elanspi_mean_image (self, self->last_image) < self->hv_data.target_mean)
self->hv_data.gdac_value -= self->hv_data.gdac_step;
else
self->hv_data.gdac_value += self->hv_data.gdac_step;

View File

@@ -71,6 +71,7 @@ struct elanspi_regtable
struct
{
unsigned char sid;
unsigned quirk;
const struct elanspi_reg_entry *table;
} entries[];
};
@@ -172,11 +173,11 @@ static const struct elanspi_reg_entry elanspi_calibration_table_id0[] = {
static const struct elanspi_regtable elanspi_calibration_table_old = {
.other = elanspi_calibration_table_default,
.entries = {
{ .sid = 0x0, .table = elanspi_calibration_table_id0 },
{ .sid = 0x5, .table = elanspi_calibration_table_id57 },
{ .sid = 0x6, .table = elanspi_calibration_table_id6 },
{ .sid = 0x7, .table = elanspi_calibration_table_id57 },
{ .sid = 0x0, .table = NULL }
{ .sid = 0x0, .quirk = 0, .table = elanspi_calibration_table_id0 },
{ .sid = 0x5, .quirk = 0, .table = elanspi_calibration_table_id57 },
{ .sid = 0x6, .quirk = 0, .table = elanspi_calibration_table_id6 },
{ .sid = 0x7, .quirk = 0, .table = elanspi_calibration_table_id57 },
{ .sid = 0x0, .quirk = 0, .table = NULL }
}
};
@@ -312,20 +313,133 @@ static const struct elanspi_reg_entry elanspi_calibration_table_page1_id14[] = {
{0xff, 0xff}
};
static const struct elanspi_regtable elanspi_calibration_table_new_page0 = {
.other = NULL,
.entries = {
{ .sid = 0xe, .table = elanspi_calibration_table_page0_id14 },
{ .sid = 0x0, .table = NULL }
}
static const struct elanspi_reg_entry elanspi_calibration_table_page0_id14_x571[] = {
{0x00, 0x5a},
{0x01, 0x00},
{0x02, 0x4f},
{0x03, 0x00},
{0x09, 0x04},
{0x04, 0x4f},
{0x05, 0xa0},
{0x06, 0x57},
{0x07, 0x02},
{0x08, 0x00},
{0x0a, 0x63},
{0x0b, 0x01},
{0x0c, 0x08},
{0x0d, 0x00},
{0x0e, 0x00},
{0x0f, 0x13},
{0x10, 0x38},
{0x11, 0x01},
{0x12, 0x04},
{0x13, 0x00},
{0x14, 0x00},
{0x15, 0x04},
{0x16, 0x02},
{0x17, 0x00},
{0x18, 0x01},
{0x19, 0xf4},
{0x1a, 0x00},
{0x1b, 0x00},
{0x1c, 0x00},
{0x1d, 0x00},
{0x1e, 0x00},
{0x1f, 0x00},
{0x20, 0x00},
{0x21, 0x00},
{0x22, 0x06},
{0x23, 0x00},
{0x24, 0x00},
{0x25, 0x00},
{0x26, 0x00},
{0x27, 0xff},
{0x28, 0x00},
{0x29, 0x04},
{0x2b, 0xe2},
{0x2e, 0xd0},
{0x2f, 0x40},
{0x30, 0x01},
{0x31, 0x38},
{0x32, 0x00},
{0x33, 0x00},
{0x34, 0x00},
{0x35, 0x1f},
{0x36, 0xff},
{0x37, 0x00},
{0x38, 0x00},
{0x39, 0x00},
{0x3a, 0x00},
{0x2a, 0x5f},
{0x2c, 0x10},
{0xff, 0xff}
};
static const struct elanspi_regtable elanspi_calibration_table_new_page1 = {
.other = NULL,
.entries = {
{ .sid = 0xe, .table = elanspi_calibration_table_page1_id14 },
{ .sid = 0x0, .table = NULL }
}
static const struct elanspi_reg_entry elanspi_calibration_table_page1_id14_x571[] = {
{0x00, 0xfb},
{0x01, 0xff},
{0x02, 0x7f},
{0x03, 0xd4},
{0x04, 0x7d},
{0x05, 0x19},
{0x06, 0x80},
{0x07, 0x40},
{0x08, 0x11},
{0x09, 0x00},
{0x0a, 0x00},
{0x0b, 0x00},
{0x0c, 0x00},
{0x0d, 0x00},
{0x0e, 0x32},
{0x0f, 0x00},
{0x10, 0x00},
{0x11, 0x32},
{0x12, 0x02},
{0x13, 0x08},
{0x14, 0x5c},
{0x15, 0x01},
{0x16, 0x15},
{0x17, 0x01},
{0x18, 0x14},
{0x19, 0x01},
{0x1a, 0x14},
{0x1b, 0x01},
{0x1c, 0x16},
{0x1d, 0x01},
{0x1e, 0x0b},
{0x1f, 0x01},
{0x20, 0x0b},
{0x21, 0x02},
{0x22, 0x08},
{0x23, 0x29},
{0x24, 0x00},
{0x25, 0x0c},
{0x26, 0x1b},
{0x27, 0x15},
{0x28, 0x1b},
{0x29, 0x15},
{0x2a, 0x00},
{0x2b, 0x00},
{0x2c, 0x01},
{0x2d, 0x16},
{0x2e, 0x01},
{0x2f, 0x16},
{0x30, 0x04},
{0x31, 0x44},
{0x32, 0x04},
{0x33, 0x44},
{0x34, 0x14},
{0x35, 0x00},
{0x36, 0x00},
{0x37, 0x00},
{0x38, 0x00},
{0x39, 0x03},
{0x3a, 0xfe},
{0x3b, 0x00},
{0x3c, 0x00},
{0x3d, 0x02},
{0x3e, 0x00},
{0x3f, 0x00}
};
#define ELANSPI_NO_ROTATE 0
@@ -335,10 +449,33 @@ static const struct elanspi_regtable elanspi_calibration_table_new_page1 = {
#define ELANSPI_HV_FLIPPED 1
#define ELANSPI_ROTATE_MASK 3
#define ELANSPI_QUIRK_X571 (1 << 2)
#define ELANSPI_QUIRK_MASK (ELANSPI_QUIRK_X571)
#define ELANSPI_UDEV_TYPES FPI_DEVICE_UDEV_SUBTYPE_SPIDEV | FPI_DEVICE_UDEV_SUBTYPE_HIDRAW
#define ELANSPI_TP_VID 0x04f3
// using checkargs ACPI:HIDPID
static const struct elanspi_regtable elanspi_calibration_table_new_page0 = {
.other = NULL,
.entries = {
{ .sid = 0xe, .quirk = 0, .table = elanspi_calibration_table_page0_id14 },
{ .sid = 0xe, .quirk = ELANSPI_QUIRK_X571, .table = elanspi_calibration_table_page0_id14_x571 },
{ .sid = 0x0, .table = NULL }
}
};
static const struct elanspi_regtable elanspi_calibration_table_new_page1 = {
.other = NULL,
.entries = {
{ .sid = 0xe, .quirk = 0, .table = elanspi_calibration_table_page1_id14 },
{ .sid = 0xe, .quirk = ELANSPI_QUIRK_X571, .table = elanspi_calibration_table_page1_id14_x571 },
{ .sid = 0x0, .table = NULL }
}
};
static const FpIdEntry elanspi_id_table[] = {
{.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN7001", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x3057}, .driver_data = ELANSPI_180_ROTATE},
{.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN7001", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x3087}, .driver_data = ELANSPI_180_ROTATE},
@@ -348,6 +485,7 @@ static const FpIdEntry elanspi_id_table[] = {
{.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN7001", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x30b2}, .driver_data = ELANSPI_NO_ROTATE},
{.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN70A1", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x30b2}, .driver_data = ELANSPI_NO_ROTATE},
{.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN7001", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x309f}, .driver_data = ELANSPI_180_ROTATE},
{.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN7001", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x3104}, .driver_data = ELANSPI_QUIRK_X571 | ELANSPI_90RIGHT_ROTATE},
{.udev_types = 0}
};
@@ -357,6 +495,7 @@ static const FpIdEntry elanspi_id_table[] = {
#define ELANSPI_MAX_OLD_STAGE2_CALBIRATION_MEAN 8000
#define ELANSPI_HV_CALIBRATION_TARGET_MEAN 3000
#define ELANSPI_HV_X571_CALIBRATION_TARGET_MEAN 7000
#define ELANSPI_MIN_EMPTY_INVALID_PERCENT 6
#define ELANSPI_MAX_REAL_INVALID_PERCENT 3