LPH9157-2 kernelio modulis
Jau parašėme programėlę rodyti vaizdams per SIEMENS C75 mobiliojo telefono ekranėlį LPH9157-2, tačiau ar norime čia ir sustoti? Tikrai ne! Mes norime, kad šis ekranėlis mums tarnautų kaip pilnavertis monitorius. Juk mažam kompiuteriui reikia ir mažo ekraniuko.
Teorija
Ko gi mums trūksta, kad galėtume paversti šią mūsų svajonę realybe? Ogi reikia parašyti Linux kernelio tvarkyklę. Beveik taip pat kaip ir anksčiau parašyta programa, bet vietoj vaizdų nuskaitymo iš failo, grafinius duomenis paimtų iš framebuferio. Kaip mums tai padaryti? Googlas mums pasakys! Pradedame knistis ir štai ką randame:
- Kažkas siūlo kurti viską patiems nuo pradžių, deja informacija jau pasenusi (2012 metų). Ir ne pilna!
- Kažkas ryžosi parašyti visą biblioteką mini ekranėlių tvarkyklėms, tačiau ji buvo parašyta taip gerai, kad ją jau integravo į patį kernelį, todėl ji daugiau nebetobulinama.
- Visgi parašyta buvo ne pakankamai gerai, kad jame ilgai užsibūtų :D, nes tik ką įtrauktas kodas iš kart buvo įdėtas į staging (išmetamo kodo) grupę.
- Visas problemas siekiama išspręsti naujuoju tinydrm moduliu, kuris padarytas pagal moderniausias kernelio kodinimo madas ir kurtas atsižvelgiant į prieš tai sukauptą patirtį.
Nedrąsūs programuotojai, kurie nori kurti tvarkykles, bet nesiryžta jų pateikti piktiems kernelio rašytojams gali savo kūrinius nupušinti į tinydrm githubo repozitoriją, kuri būtent tam ir skirta.
Būtent paskutiniuoju punktu ir turėtų vadovautis naują ekranėlio tvarkyklę kuriantys programuotojai. Mes imsime taip ir padarysime. Kaip pavyzdį naudosime oficialią ekranėlio mi0283qt tvarkyklę.
Kodas
Pradžių pradžia
Kaip ir visuose kernelio moduliuose viskas kas svarbiausia yra apačioje, tad pradedame nuo tvarkyklės inicializavimo struktūrų:
1 | //device-tree paieškos kriterijai |
Kaip matome – nieko įmantraus, tiesiog užregistruojame device-tree taisykles ir nurodome probe, remove ir shutdown funkcijas.
Funkcija probe paleidžiama kai aptinkamas ekranėlis. Kadangi SPI neturi įrenginių aptikimo protokolo, mūsų ekranėlis bus visada automatiškai aptiktas vos tik užkrovus modulį (žinoma jeigu device-tree tinkamai aprašytas).
Funkcija Probe
Kaip pasiimami GPIO galite prisiminti ankstesniame straipsnyje apie GPIO kernelio modulį.
Tikriausiai svarbiausia vieta yra mipi_dbi_spi_init funkcijos iškvietimas. Į ją paduodame struktūrose aprašytą tvarkyklės informaciją ir piešimo funkcijas.
1 | //Surašome funkcijas, kurios bus naudojamos piešimui. Mums pasisekė, nes jų |
Kadangi kažkoks geras žmogus piešimu jau pasirūpino, mums nieko daryti nereikės, yra tik viena problemėlė – mūsų ekranėliui reikia nestandartinių piešimo lango nustatymo koordinačių. Reikia koordinačių po vieną baitą, o standartinės funkcijos siunčia po du, todėl perimsime kernelio duomenis ir juos pakoreguosime taip, kaip mums reikia.
Tam ir skirtas tas “hakas” – mipi_command_override. Čia toks savotiškas senoviškas C stiliaus override:
1 | static int mipi_command_override(struct mipi_dbi *mipi, u8 cmd, u8 *data, size_t len) |
Funkcija lph9157_init
Dabar imsimės ekranėlio inicializacijai skirtos funkcijos. Visai kaip ir paprastoje userspace programėlėje (funckija initializeDevice), nusiųsim reset komandą, inicializuosim atmintį ir nustatysime spalvų paletę. Modulyje, skirtingai nei programoje kintamųjų pavadinimai standartizuoti, bet esu tikras be vargo atsirinksite.
1 | static int lph9157_init(struct mipi_dbi *mipi) |
Funckijos lph9157_shutdown ir lph9157_remove
Liko tik apsivalymo funkcijos, kurių viena iškviečiama rmmod metu, o kita išjungiant kompiuteriuką. Šiaip tai nėra būtina, bet mes vien dėl mandagumo nunulinsime GPIO, kad ekranėlis iki galo išsijungtų. Tada nekils problemų dar kartą kviečiant insmod, nes mūsų prietaisėliui nepatinka būti inicializuotam du kartus be išjungimo.
1 | void lph9157_poweroff(struct modulio_apjungti_duomenys *data) |
device-tree
Tam, kad kernelis aptiktų ekranėlį ir žinotų kuriuos GPIO naudoti reikės pamodifikuoti device-tree:
1 | &spi0 { |
Štai ir viskas! modulis parašytas! Kodą kaip visada rasite githube, liko tik testavimas.
Testavimas
Kodas kompiliuojasi paprastai – visai kaip ir kiti moduliai, tiesiog parašome make ir viskas baigta.
Paskui imamės insmod:
1 | make |
Kaip matome viskas puiku: dmesg parodė, kad užregistruotas naujas įrenginys, o ir pačiam ekranėlyje pasirodė kažkoks triukšmas:


Laikas konsolei! Linux konsolę į ekranėlį iš pagrindinio monitoriaus perkelsime pasinaudoję komanda con2fbmap:
1 | con2fbmap 1 1 |
Mums pavyko:

Bet gražiau atrodo paversta:
1 | echo 1 > /sys/class/graphics/fbcon/rotate |

Panašu, kad tvarkyklė veikia! Mūsų pačių parašyta, krauju ir prakaitu aplaistyta, bet veikia! Veikia!