[Xiaomi Redmi 1S] thewisenerd:
regarding s2w/d2w, input handlers and 'issues'

i am throughout this post, going to talk about but one 'issue': touchscreen not working with s2w/d2w toggle.

i know its been more than a month without any kernel releases; but srsly guys, i'm not much of a 'maintainer'. please move on to the much better kernels available there. do I bother? no. it's completely fine by me. i make these kernels for my own satisfaction and currently am happily using a self-compiled kernel kernel_xiaomi_armani/lp5.1-d2w running on slimroms, and as said: you can either compile a kernel yourself; or wait for your features to be picked by other kernels; or wait for me (my phone actually; it has to come back from the service center; and xiaomi's service centers suck! (well, at least the couple ones i've been to at least...).

it started with me occasionally experiencing touch screen unresponsiveness randomly, and @Luffy.d informed me about a similar issue both on xda and hangouts; it bugged me.

then, when i was working on writing native d2w for ft5x06 based on balika011's code, i figured out what the probable problem was: toggling s2w/d2w when the screen was off.

yes, kernel applications/configurators that run at boot; some run after screen turns off; and this causes the issue.

why exactly?

well; as of now, what happens is:

when the touchscreen is turned off, disable_irq is called.:

disable_irq(dev->irq);

what disable_irq does is: tells kernel to ignore all irq interrupts on this device.

and when touchscreen turned on, enable_irq is called:

enable_irq(dev->irq);

what enable_irq does is: tells kernel to recieve/parse/ all irq interrupts on this device.

but, when we modify the code; for s2w/d2w, what happens is:

when the display is turned off, enable_irq_wake is called.:

enable_irq_wake(dev->irq);

what enable_irq_wake does is: it tells the cpu to not 'cancel' the device and continue recieving interrupts from this device. this is why interrupts are continuously recieved from touch panel even when rest of device is in suspend (viz. s2w/d2w does NOT prevent deep sleep; something else might)

when the display is turned on, disable_irq_wake is called.:

disable_irq_wake(dev->irq);

this tells the kernel to bring back the input device to 'normal mode'; and interrupts are handled nromally.

so, where's the problem?

during boot; s2w/d2w is disabled by default. user settings are applied when the kernel configurator app runs, which usually occours after first boot completes, and screen turns off by default, unless otherwise behaviour specified because of user interaction.

when the display is turned off; disable_irq call is made, thus kernel starts ignoreing all irq requests on the ts panel.

but, what happens when s2w/d2w is enabled/disabled with screen off?

well, different cases:

the usual case:

[*] enable s2w/d2w with s2w/d2w not already enabled: in this case, disable_irq was called, and not enable_irq_wake. the next time user switches on device, instead of calling enable_irq, disable_irq_wake is called (since code thinks enable_irq_wake was called). this is why the ts panel is not enabled at all in the first place, and no input is logged.

the different case:

[*] disable s2w/d2w with s2w/d2w already enabled: in this case, enable_irq_wake was called and disable_irq was not called. so, when next time user tries to switch on display, instead of calling disable_irq_wake, enable_irq is called. this leads to anomaly.

i figured this problem; and noted this in commit:

https://github.com/thewisenerd/kernel_xiaomi_armani/commit/f2089df959b0c66b6193658da8c8718dbeec11e3

this was fixed in :

https://github.com/thewisenerd/kernel_xiaomi_armani/commit/fc6d6a0b8cfd7eb036c8c328dff4d2402553a279

what is the fix?

very similar to what i wrote and noted in commit f2089df:

* if buf[0] == 0 //// disable d2w while screen off
* if switch == 1 // enable_irq_wake was called
* disable_irq_wake(irq); // call disable_irq_wake to complete cycle
* disable_irq(irq); // disable irq properly now
* if buf[0] == 1 // enable d2w while screen off
* if switch == 0 // d2w was off, disable_irq was called
* enable_irq(irq) //enable irq first to being with
* enable_irq_wake(irq); //enable irq wake.

--------------------------------------------------------------------------------

also, during ts_resume, in ft5x06, what currently is being done is: the panel is being reset every time. however, this is not needed, if panel was not put in deep sleep, viz. hibernate in first place; please read more in ft5x06_ts datasheets avaialable on internet.

so, it was modified to only reset panel if d2w/s2w was disabled.

this was added here: https://github.com/thewisenerd/kernel_xiaomi_armani/commit/9e7da32f5c871615942bedf0559698abe25a2094

calling this reset_panel(), the above fix now becomes:

* if buf[0] == 0 //// disable d2w while screen off
* if switch == 1 // enable_irq_wake was called
* disable_irq_wake(irq); // call disable_irq_wake to complete cycle
* disable_irq(irq); // disable irq properly now
* if buf[0] == 1 // enable d2w while screen off
* if switch == 0 // d2w was off, disable_irq was called
* reset_panel(); // to actually get the touch panel working
* enable_irq(irq) //enable irq first to being with
* enable_irq_wake(irq); //enable irq wake.

those who have included d2w/s2w in their kernels, please update :)

note; these fixes are specific to the native d2w code written for ft5x06 code.

todo: fix this properly across even modular s2w/d2w. i am currently writing a simple s2w/d2w modules, in which there will be support for calling functions at the time of switch store/dump, and before power_trigger calling, but let's see how those modules progress goes. you can find random code drops on github.

p.s. when i say simple: i mean without much complication than required. nothing is wrong with current implementations. i just feel that all those comparisons/calculations/cpucycles/variables are not really necessary, so, i'm writing my own modules based off current implementation, a spin-off my insomnia.

p.p.s. i am not not even sure if workqueues are needed, but i guess i'll rethink about it *after* i get a night's sleep probably.