Compare commits

...

2 Commits

Author SHA1 Message Date
Matthew Mirvish
b50cba1fa4 fixup! elanspi: preliminary support for 04f3:3104 2022-05-23 13:16:21 -04:00
Matthew Mirvish
46591d7bfa 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.
2022-05-03 21:02:26 -04:00
2 changed files with 202 additions and 36 deletions

View File

@@ -63,6 +63,7 @@ struct _FpiDeviceElanSpi
guint16 gdac_step; guint16 gdac_step;
guint16 best_gdac; guint16 best_gdac;
guint16 best_meandiff; guint16 best_meandiff;
guint16 target_mean;
} hv_data; } hv_data;
}; };
@@ -408,6 +409,10 @@ elanspi_determine_sensor (FpiDeviceElanSpi *self, GError **err)
self->frame_width = self->sensor_width; self->frame_width = self->sensor_width;
self->frame_height = self->sensor_height > ELANSPI_MAX_FRAME_HEIGHT ? ELANSPI_MAX_FRAME_HEIGHT : self->sensor_height; 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 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) 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; starting_entry = table->entries[i].table;
break; break;
@@ -692,6 +697,8 @@ static void
elanspi_capture_hv_image_handler (FpiSpiTransfer *transfer, FpDevice *dev, gpointer unused_data, GError *error) elanspi_capture_hv_image_handler (FpiSpiTransfer *transfer, FpDevice *dev, gpointer unused_data, GError *error)
{ {
FpiDeviceElanSpi *self = FPI_DEVICE_ELANSPI (dev); FpiDeviceElanSpi *self = FPI_DEVICE_ELANSPI (dev);
ptrdiff_t outptr = 0, inptr = 0;
guint16 value = 0;
if (error) if (error)
{ {
@@ -699,24 +706,39 @@ elanspi_capture_hv_image_handler (FpiSpiTransfer *transfer, FpDevice *dev, gpoin
return; return;
} }
int i, outptr; if (fpi_device_get_driver_data (dev) & ELANSPI_QUIRK_X571)
guint16 value = 0;
for (i = 0, outptr = 0; i < transfer->length_rd && outptr < (self->sensor_height * self->sensor_width * 2); i += 1)
{ {
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; self->last_image[outptr / 2] = transfer->buffer_rd[inptr] + transfer->buffer_rd[inptr + 1] * 0x100;
value |= transfer->buffer_rd[i]; inptr += 2;
self->last_image[outptr / 2] = value; 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,17 @@ elanspi_capture_hv_handler (FpiSsm *ssm, FpDevice *dev)
return; return;
} }
/* otherwise, read the image /* 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 = fpi_spi_transfer_new (dev, self->spi_fd);
xfer->ssm = ssm; xfer->ssm = ssm;
fpi_spi_transfer_write (xfer, 2); fpi_spi_transfer_write (xfer, 2);
xfer->buffer_wr[0] = 0x10; /* receieve line */ xfer->buffer_wr[0] = 0x10; /* receieve line/image */
fpi_spi_transfer_read (xfer, self->sensor_height * (self->sensor_width * 2 + 48)); if (fpi_device_get_driver_data (dev) & ELANSPI_QUIRK_X571)
fpi_spi_transfer_read (xfer, self->sensor_height * (self->sensor_width * 2 + 2) - 2);
else
fpi_spi_transfer_read (xfer, self->sensor_height * (self->sensor_width * 2 + 48));
fpi_spi_transfer_submit (xfer, fpi_device_get_cancellable (dev), elanspi_capture_hv_image_handler, NULL); fpi_spi_transfer_submit (xfer, fpi_device_get_cancellable (dev), elanspi_capture_hv_image_handler, NULL);
return; return;
} }
@@ -873,7 +900,7 @@ elanspi_calibrate_hv_handler (FpiSsm *ssm, FpDevice *dev)
case ELANSPI_CALIBHV_PROCESS: case ELANSPI_CALIBHV_PROCESS:
/* compute mean */ /* 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) if (mean_diff < 100)
{ {
fp_dbg ("<calibhv> calibration ok (mdiff < 100 w/ gdac=%04x)", self->hv_data.gdac_value); fp_dbg ("<calibhv> calibration ok (mdiff < 100 w/ gdac=%04x)", self->hv_data.gdac_value);
@@ -896,7 +923,7 @@ elanspi_calibrate_hv_handler (FpiSsm *ssm, FpDevice *dev)
return; return;
} }
/* update gdac */ /* 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; self->hv_data.gdac_value -= self->hv_data.gdac_step;
else else
self->hv_data.gdac_value += self->hv_data.gdac_step; self->hv_data.gdac_value += self->hv_data.gdac_step;

View File

@@ -71,6 +71,7 @@ struct elanspi_regtable
struct struct
{ {
unsigned char sid; unsigned char sid;
unsigned quirk;
const struct elanspi_reg_entry *table; const struct elanspi_reg_entry *table;
} entries[]; } entries[];
}; };
@@ -172,11 +173,11 @@ static const struct elanspi_reg_entry elanspi_calibration_table_id0[] = {
static const struct elanspi_regtable elanspi_calibration_table_old = { static const struct elanspi_regtable elanspi_calibration_table_old = {
.other = elanspi_calibration_table_default, .other = elanspi_calibration_table_default,
.entries = { .entries = {
{ .sid = 0x0, .table = elanspi_calibration_table_id0 }, { .sid = 0x0, .quirk = 0, .table = elanspi_calibration_table_id0 },
{ .sid = 0x5, .table = elanspi_calibration_table_id57 }, { .sid = 0x5, .quirk = 0, .table = elanspi_calibration_table_id57 },
{ .sid = 0x6, .table = elanspi_calibration_table_id6 }, { .sid = 0x6, .quirk = 0, .table = elanspi_calibration_table_id6 },
{ .sid = 0x7, .table = elanspi_calibration_table_id57 }, { .sid = 0x7, .quirk = 0, .table = elanspi_calibration_table_id57 },
{ .sid = 0x0, .table = NULL } { .sid = 0x0, .quirk = 0, .table = NULL }
} }
}; };
@@ -312,20 +313,133 @@ static const struct elanspi_reg_entry elanspi_calibration_table_page1_id14[] = {
{0xff, 0xff} {0xff, 0xff}
}; };
static const struct elanspi_regtable elanspi_calibration_table_new_page0 = { static const struct elanspi_reg_entry elanspi_calibration_table_page0_id14_x571[] = {
.other = NULL, {0x00, 0x5a},
.entries = { {0x01, 0x00},
{ .sid = 0xe, .table = elanspi_calibration_table_page0_id14 }, {0x02, 0x4f},
{ .sid = 0x0, .table = NULL } {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 = { static const struct elanspi_reg_entry elanspi_calibration_table_page1_id14_x571[] = {
.other = NULL, {0x00, 0xfb},
.entries = { {0x01, 0xff},
{ .sid = 0xe, .table = elanspi_calibration_table_page1_id14 }, {0x02, 0x7f},
{ .sid = 0x0, .table = NULL } {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 #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_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_UDEV_TYPES FPI_DEVICE_UDEV_SUBTYPE_SPIDEV | FPI_DEVICE_UDEV_SUBTYPE_HIDRAW
#define ELANSPI_TP_VID 0x04f3 #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[] = { 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 = 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}, {.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 = "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 = "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 = 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} {.udev_types = 0}
}; };
@@ -357,6 +495,7 @@ static const FpIdEntry elanspi_id_table[] = {
#define ELANSPI_MAX_OLD_STAGE2_CALBIRATION_MEAN 8000 #define ELANSPI_MAX_OLD_STAGE2_CALBIRATION_MEAN 8000
#define ELANSPI_HV_CALIBRATION_TARGET_MEAN 3000 #define ELANSPI_HV_CALIBRATION_TARGET_MEAN 3000
#define ELANSPI_HV_X571_CALIBRATION_TARGET_MEAN 7000
#define ELANSPI_MIN_EMPTY_INVALID_PERCENT 6 #define ELANSPI_MIN_EMPTY_INVALID_PERCENT 6
#define ELANSPI_MAX_REAL_INVALID_PERCENT 3 #define ELANSPI_MAX_REAL_INVALID_PERCENT 3