diff options
| author | Kristina Martšenko <kristina.martsenko@gmail.com> | 2015-01-25 11:28:19 -0500 |
|---|---|---|
| committer | Jonathan Cameron <jic23@kernel.org> | 2015-01-26 15:57:37 -0500 |
| commit | f81197b8a31b8fb287ae57f597b5b6841e1ece92 (patch) | |
| tree | 1f429f871d970e4d9f5cab5ffdc3521c87ac22b3 | |
| parent | 4f33fbae555000bf73aaacbc4f5b24668afc8c7a (diff) | |
iio: mxs-lradc: separate touchscreen and buffer virtual channels
The touchscreen was initially designed [1] to map all of its physical
channels to one virtual channel, leaving buffered capture to use the
remaining 7 virtual channels. When the touchscreen was reimplemented
[2], it was made to use four virtual channels, which overlap and
conflict with the channels the buffer uses.
As a result, when the buffer is enabled, the touchscreen's virtual
channels are remapped to whichever physical channels the buffer was
configured with, causing the touchscreen to read those instead of the
touch measurement channels. Effectively the touchscreen stops working.
So here we separate the channels again, giving the touchscreen 2 virtual
channels and the buffer 6. We can't give the touchscreen just 1 channel
as before, as the current pressure calculation requires 2 channels to be
read at the same time.
This makes the touchscreen continue to work during buffered capture. It
has been tested on i.MX28, but not on i.MX23.
[1] 06ddd353f5c8 ("iio: mxs: Implement support for touchscreen")
[2] dee05308f602 ("Staging/iio/adc/touchscreen/MXS: add interrupt driven
touch detection")
Signed-off-by: Kristina Martšenko <kristina.martsenko@gmail.com>
Reviewed-by: Marek Vasut <marex@denx.de>
Cc: Stable@vger.kernel.org
Signed-off-by: Jonathan Cameron <jic23@kernel.org>
| -rw-r--r-- | drivers/staging/iio/adc/mxs-lradc.c | 166 |
1 files changed, 75 insertions, 91 deletions
diff --git a/drivers/staging/iio/adc/mxs-lradc.c b/drivers/staging/iio/adc/mxs-lradc.c index f053535385bf..4e574b76ead0 100644 --- a/drivers/staging/iio/adc/mxs-lradc.c +++ b/drivers/staging/iio/adc/mxs-lradc.c | |||
| @@ -214,11 +214,14 @@ struct mxs_lradc { | |||
| 214 | unsigned long is_divided; | 214 | unsigned long is_divided; |
| 215 | 215 | ||
| 216 | /* | 216 | /* |
| 217 | * Touchscreen LRADC channels receives a private slot in the CTRL4 | 217 | * When the touchscreen is enabled, we give it two private virtual |
| 218 | * register, the slot #7. Therefore only 7 slots instead of 8 in the | 218 | * channels: #6 and #7. This means that only 6 virtual channels (instead |
| 219 | * CTRL4 register can be mapped to LRADC channels when using the | 219 | * of 8) will be available for buffered capture. |
| 220 | * touchscreen. | 220 | */ |
| 221 | * | 221 | #define TOUCHSCREEN_VCHANNEL1 7 |
| 222 | #define TOUCHSCREEN_VCHANNEL2 6 | ||
| 223 | |||
| 224 | /* | ||
| 222 | * Furthermore, certain LRADC channels are shared between touchscreen | 225 | * Furthermore, certain LRADC channels are shared between touchscreen |
| 223 | * and/or touch-buttons and generic LRADC block. Therefore when using | 226 | * and/or touch-buttons and generic LRADC block. Therefore when using |
| 224 | * either of these, these channels are not available for the regular | 227 | * either of these, these channels are not available for the regular |
| @@ -342,6 +345,9 @@ struct mxs_lradc { | |||
| 342 | #define LRADC_CTRL4 0x140 | 345 | #define LRADC_CTRL4 0x140 |
| 343 | #define LRADC_CTRL4_LRADCSELECT_MASK(n) (0xf << ((n) * 4)) | 346 | #define LRADC_CTRL4_LRADCSELECT_MASK(n) (0xf << ((n) * 4)) |
| 344 | #define LRADC_CTRL4_LRADCSELECT_OFFSET(n) ((n) * 4) | 347 | #define LRADC_CTRL4_LRADCSELECT_OFFSET(n) ((n) * 4) |
| 348 | #define LRADC_CTRL4_LRADCSELECT(n, x) \ | ||
| 349 | (((x) << LRADC_CTRL4_LRADCSELECT_OFFSET(n)) & \ | ||
| 350 | LRADC_CTRL4_LRADCSELECT_MASK(n)) | ||
| 345 | 351 | ||
| 346 | #define LRADC_RESOLUTION 12 | 352 | #define LRADC_RESOLUTION 12 |
| 347 | #define LRADC_SINGLE_SAMPLE_MASK ((1 << LRADC_RESOLUTION) - 1) | 353 | #define LRADC_SINGLE_SAMPLE_MASK ((1 << LRADC_RESOLUTION) - 1) |
| @@ -416,6 +422,14 @@ static bool mxs_lradc_check_touch_event(struct mxs_lradc *lradc) | |||
| 416 | LRADC_STATUS_TOUCH_DETECT_RAW); | 422 | LRADC_STATUS_TOUCH_DETECT_RAW); |
| 417 | } | 423 | } |
| 418 | 424 | ||
| 425 | static void mxs_lradc_map_channel(struct mxs_lradc *lradc, unsigned vch, | ||
| 426 | unsigned ch) | ||
| 427 | { | ||
| 428 | mxs_lradc_reg_clear(lradc, LRADC_CTRL4_LRADCSELECT_MASK(vch), | ||
| 429 | LRADC_CTRL4); | ||
| 430 | mxs_lradc_reg_set(lradc, LRADC_CTRL4_LRADCSELECT(vch, ch), LRADC_CTRL4); | ||
| 431 | } | ||
| 432 | |||
| 419 | static void mxs_lradc_setup_ts_channel(struct mxs_lradc *lradc, unsigned ch) | 433 | static void mxs_lradc_setup_ts_channel(struct mxs_lradc *lradc, unsigned ch) |
| 420 | { | 434 | { |
| 421 | /* | 435 | /* |
| @@ -443,12 +457,8 @@ static void mxs_lradc_setup_ts_channel(struct mxs_lradc *lradc, unsigned ch) | |||
| 443 | LRADC_DELAY_DELAY(lradc->over_sample_delay - 1), | 457 | LRADC_DELAY_DELAY(lradc->over_sample_delay - 1), |
| 444 | LRADC_DELAY(3)); | 458 | LRADC_DELAY(3)); |
| 445 | 459 | ||
| 446 | mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ(2) | | 460 | mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ(ch), LRADC_CTRL1); |
| 447 | LRADC_CTRL1_LRADC_IRQ(3) | LRADC_CTRL1_LRADC_IRQ(4) | | ||
| 448 | LRADC_CTRL1_LRADC_IRQ(5), LRADC_CTRL1); | ||
| 449 | 461 | ||
| 450 | /* wake us again, when the complete conversion is done */ | ||
| 451 | mxs_lradc_reg_set(lradc, LRADC_CTRL1_LRADC_IRQ_EN(ch), LRADC_CTRL1); | ||
| 452 | /* | 462 | /* |
| 453 | * after changing the touchscreen plates setting | 463 | * after changing the touchscreen plates setting |
| 454 | * the signals need some initial time to settle. Start the | 464 | * the signals need some initial time to settle. Start the |
| @@ -502,12 +512,8 @@ static void mxs_lradc_setup_ts_pressure(struct mxs_lradc *lradc, unsigned ch1, | |||
| 502 | LRADC_DELAY_DELAY(lradc->over_sample_delay - 1), | 512 | LRADC_DELAY_DELAY(lradc->over_sample_delay - 1), |
| 503 | LRADC_DELAY(3)); | 513 | LRADC_DELAY(3)); |
| 504 | 514 | ||
| 505 | mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ(2) | | 515 | mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ(ch2), LRADC_CTRL1); |
| 506 | LRADC_CTRL1_LRADC_IRQ(3) | LRADC_CTRL1_LRADC_IRQ(4) | | ||
| 507 | LRADC_CTRL1_LRADC_IRQ(5), LRADC_CTRL1); | ||
| 508 | 516 | ||
| 509 | /* wake us again, when the conversions are done */ | ||
| 510 | mxs_lradc_reg_set(lradc, LRADC_CTRL1_LRADC_IRQ_EN(ch2), LRADC_CTRL1); | ||
| 511 | /* | 517 | /* |
| 512 | * after changing the touchscreen plates setting | 518 | * after changing the touchscreen plates setting |
| 513 | * the signals need some initial time to settle. Start the | 519 | * the signals need some initial time to settle. Start the |
| @@ -573,36 +579,6 @@ static unsigned mxs_lradc_read_ts_pressure(struct mxs_lradc *lradc, | |||
| 573 | #define TS_CH_XM 4 | 579 | #define TS_CH_XM 4 |
| 574 | #define TS_CH_YM 5 | 580 | #define TS_CH_YM 5 |
| 575 | 581 | ||
| 576 | static int mxs_lradc_read_ts_channel(struct mxs_lradc *lradc) | ||
| 577 | { | ||
| 578 | u32 reg; | ||
| 579 | int val; | ||
| 580 | |||
| 581 | reg = readl(lradc->base + LRADC_CTRL1); | ||
| 582 | |||
| 583 | /* only channels 3 to 5 are of interest here */ | ||
| 584 | if (reg & LRADC_CTRL1_LRADC_IRQ(TS_CH_YP)) { | ||
| 585 | mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ_EN(TS_CH_YP) | | ||
| 586 | LRADC_CTRL1_LRADC_IRQ(TS_CH_YP), LRADC_CTRL1); | ||
| 587 | val = mxs_lradc_read_raw_channel(lradc, TS_CH_YP); | ||
| 588 | } else if (reg & LRADC_CTRL1_LRADC_IRQ(TS_CH_XM)) { | ||
| 589 | mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ_EN(TS_CH_XM) | | ||
| 590 | LRADC_CTRL1_LRADC_IRQ(TS_CH_XM), LRADC_CTRL1); | ||
| 591 | val = mxs_lradc_read_raw_channel(lradc, TS_CH_XM); | ||
| 592 | } else if (reg & LRADC_CTRL1_LRADC_IRQ(TS_CH_YM)) { | ||
| 593 | mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ_EN(TS_CH_YM) | | ||
| 594 | LRADC_CTRL1_LRADC_IRQ(TS_CH_YM), LRADC_CTRL1); | ||
| 595 | val = mxs_lradc_read_raw_channel(lradc, TS_CH_YM); | ||
| 596 | } else { | ||
| 597 | return -EIO; | ||
| 598 | } | ||
| 599 | |||
| 600 | mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(2)); | ||
| 601 | mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(3)); | ||
| 602 | |||
| 603 | return val; | ||
| 604 | } | ||
| 605 | |||
| 606 | /* | 582 | /* |
| 607 | * YP(open)--+-------------+ | 583 | * YP(open)--+-------------+ |
| 608 | * | |--+ | 584 | * | |--+ |
| @@ -646,7 +622,8 @@ static void mxs_lradc_prepare_x_pos(struct mxs_lradc *lradc) | |||
| 646 | mxs_lradc_reg_set(lradc, mxs_lradc_drive_x_plate(lradc), LRADC_CTRL0); | 622 | mxs_lradc_reg_set(lradc, mxs_lradc_drive_x_plate(lradc), LRADC_CTRL0); |
| 647 | 623 | ||
| 648 | lradc->cur_plate = LRADC_SAMPLE_X; | 624 | lradc->cur_plate = LRADC_SAMPLE_X; |
| 649 | mxs_lradc_setup_ts_channel(lradc, TS_CH_YP); | 625 | mxs_lradc_map_channel(lradc, TOUCHSCREEN_VCHANNEL1, TS_CH_YP); |
| 626 | mxs_lradc_setup_ts_channel(lradc, TOUCHSCREEN_VCHANNEL1); | ||
| 650 | } | 627 | } |
| 651 | 628 | ||
| 652 | /* | 629 | /* |
| @@ -667,7 +644,8 @@ static void mxs_lradc_prepare_y_pos(struct mxs_lradc *lradc) | |||
| 667 | mxs_lradc_reg_set(lradc, mxs_lradc_drive_y_plate(lradc), LRADC_CTRL0); | 644 | mxs_lradc_reg_set(lradc, mxs_lradc_drive_y_plate(lradc), LRADC_CTRL0); |
| 668 | 645 | ||
| 669 | lradc->cur_plate = LRADC_SAMPLE_Y; | 646 | lradc->cur_plate = LRADC_SAMPLE_Y; |
| 670 | mxs_lradc_setup_ts_channel(lradc, TS_CH_XM); | 647 | mxs_lradc_map_channel(lradc, TOUCHSCREEN_VCHANNEL1, TS_CH_XM); |
| 648 | mxs_lradc_setup_ts_channel(lradc, TOUCHSCREEN_VCHANNEL1); | ||
| 671 | } | 649 | } |
| 672 | 650 | ||
| 673 | /* | 651 | /* |
| @@ -688,7 +666,10 @@ static void mxs_lradc_prepare_pressure(struct mxs_lradc *lradc) | |||
| 688 | mxs_lradc_reg_set(lradc, mxs_lradc_drive_pressure(lradc), LRADC_CTRL0); | 666 | mxs_lradc_reg_set(lradc, mxs_lradc_drive_pressure(lradc), LRADC_CTRL0); |
| 689 | 667 | ||
| 690 | lradc->cur_plate = LRADC_SAMPLE_PRESSURE; | 668 | lradc->cur_plate = LRADC_SAMPLE_PRESSURE; |
| 691 | mxs_lradc_setup_ts_pressure(lradc, TS_CH_XP, TS_CH_YM); | 669 | mxs_lradc_map_channel(lradc, TOUCHSCREEN_VCHANNEL1, TS_CH_YM); |
| 670 | mxs_lradc_map_channel(lradc, TOUCHSCREEN_VCHANNEL2, TS_CH_XP); | ||
| 671 | mxs_lradc_setup_ts_pressure(lradc, TOUCHSCREEN_VCHANNEL2, | ||
| 672 | TOUCHSCREEN_VCHANNEL1); | ||
| 692 | } | 673 | } |
| 693 | 674 | ||
| 694 | static void mxs_lradc_enable_touch_detection(struct mxs_lradc *lradc) | 675 | static void mxs_lradc_enable_touch_detection(struct mxs_lradc *lradc) |
| @@ -701,6 +682,19 @@ static void mxs_lradc_enable_touch_detection(struct mxs_lradc *lradc) | |||
| 701 | mxs_lradc_reg_set(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, LRADC_CTRL1); | 682 | mxs_lradc_reg_set(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, LRADC_CTRL1); |
| 702 | } | 683 | } |
| 703 | 684 | ||
| 685 | static void mxs_lradc_start_touch_event(struct mxs_lradc *lradc) | ||
| 686 | { | ||
| 687 | mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, | ||
| 688 | LRADC_CTRL1); | ||
| 689 | mxs_lradc_reg_set(lradc, | ||
| 690 | LRADC_CTRL1_LRADC_IRQ_EN(TOUCHSCREEN_VCHANNEL1), LRADC_CTRL1); | ||
| 691 | /* | ||
| 692 | * start with the Y-pos, because it uses nearly the same plate | ||
| 693 | * settings like the touch detection | ||
| 694 | */ | ||
