1 /* 2 * Export Letux 400 display operations as a server. 3 * 4 * (c) 2018 Paul Boddie <paul@boddie.org.uk> 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License as 8 * published by the Free Software Foundation; either version 2 of 9 * the License, or (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 * Boston, MA 02110-1301, USA 20 */ 21 22 #include <l4/devices/gpio-jz4730.h> 23 #include <l4/devices/backlight-client.h> 24 #include <l4/devices/memory.h> 25 26 #include <l4/cxx/ipc_server> 27 #include <l4/re/env> 28 #include <l4/re/util/object_registry> 29 #include <l4/sys/capability> 30 31 #include "display-ops.h" 32 33 /* Virtual address for the GPIO register block. */ 34 35 static l4_addr_t gpio_virt_base = 0, gpio_virt_base_end = 0; 36 37 /* GPIO and backlight device abstractions. */ 38 39 static Gpio_jz4730_chip *gpio_port_b = 0, *gpio_port_c = 0; 40 static L4::Cap<Backlight_device_interface> backlight_device; 41 42 43 44 /* GPIO pin definitions. */ 45 46 enum Jz4730_lcd_gpio_mask 47 { 48 Jz4730_lcd_gpio_func1 = 0xf8ffff00, 49 Jz4730_lcd_gpio_func2 = 0x07000000, 50 }; 51 52 enum Jz4730_lcd_gpio 53 { 54 Jz4730_lcd_gpio_led_enable = 28, 55 Jz4730_lcd_gpio_display_enable = 29, 56 }; 57 58 59 60 static int setup_memory(void) 61 { 62 if (get_memory("jz4730-gpio", &gpio_virt_base, &gpio_virt_base_end)) 63 return 1; 64 65 return 0; 66 } 67 68 69 70 /* Display device. */ 71 72 class Display_device_server : public L4::Server_object_t<L4::Kobject> 73 { 74 Pin_slice lcd_mask1 = {.offset=0, .mask=Jz4730_lcd_gpio_func1}; 75 Pin_slice lcd_mask2 = {.offset=0, .mask=Jz4730_lcd_gpio_func2}; 76 77 public: 78 explicit Display_device_server() 79 { 80 /* Set functions for the LCD pins. */ 81 82 gpio_port_b->multi_config_pad(lcd_mask1, Hw::Gpio_chip::Function_alt, 1); 83 gpio_port_b->multi_config_pad(lcd_mask2, Hw::Gpio_chip::Function_alt, 2); 84 85 /* Enable LED, disable display. */ 86 87 gpio_port_c->setup(Jz4730_lcd_gpio_led_enable, Hw::Gpio_chip::Output, 1); 88 gpio_port_c->setup(Jz4730_lcd_gpio_display_enable, Hw::Gpio_chip::Output, 0); 89 } 90 91 /* Dispatch incoming requests. */ 92 93 int dispatch(l4_umword_t obj, L4::Ipc::Iostream &ios) 94 { 95 l4_msgtag_t tag; 96 97 (void) obj; 98 ios >> tag; 99 100 switch (tag.label()) 101 { 102 case Display_op_disable: 103 disable(); 104 return L4_EOK; 105 106 case Display_op_enable: 107 enable(); 108 return L4_EOK; 109 110 default: 111 return -L4_EBADPROTO; 112 } 113 } 114 115 /* Switch the display off. */ 116 117 void disable(void) 118 { 119 gpio_port_c->setup(Jz4730_lcd_gpio_display_enable, Hw::Gpio_chip::Output, 0); 120 backlight_device->disable(); 121 } 122 123 /* Switch the display on. */ 124 125 void enable(void) 126 { 127 gpio_port_c->setup(Jz4730_lcd_gpio_display_enable, Hw::Gpio_chip::Output, 1); 128 backlight_device->enable(); 129 } 130 }; 131 132 static L4Re::Util::Registry_server<> server; 133 134 135 136 int main(void) 137 { 138 if (setup_memory()) return 1; 139 140 /* Initialise the GPIO abstractions. */ 141 142 Gpio_jz4730_chip gpb(gpio_virt_base + (1 * 0x30), gpio_virt_base + (2 * 0x30), 32); 143 Gpio_jz4730_chip gpc(gpio_virt_base + (2 * 0x30), gpio_virt_base + (3 * 0x30), 32); 144 145 gpio_port_b = &gpb; 146 gpio_port_c = &gpc; 147 148 /* Obtain a reference to the backlight device. */ 149 150 backlight_device = L4Re::Env::env()->get_cap<Backlight_device_interface>("backlight"); 151 if (!backlight_device.is_valid()) return 1; 152 153 /* Initialise and register a new server object. */ 154 155 Display_device_server server_obj; 156 server.registry()->register_obj(&server_obj, "display"); 157 158 /* Enter the IPC server loop. */ 159 160 server.loop(); 161 return 0; 162 }