1 /* 2 * Export Ben NanoNote display operations as a server. 3 * 4 * Copyright (C) 2018, 2020 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-jz4740.h> 23 #include <l4/devices/lcd-jz4740-config.h> 24 #include <l4/devices/lcd-jz4740-panel.h> 25 #include <l4/devices/memory.h> 26 27 #include <l4/cxx/ipc_server> 28 #include <l4/re/env> 29 #include <l4/re/env.h> 30 #include <l4/re/util/object_registry> 31 #include <l4/sys/capability> 32 33 #include "activation_client.h" 34 #include "display-ops.h" 35 36 /* Virtual address for the GPIO register block. */ 37 38 static l4_addr_t gpio_virt_base = 0, gpio_virt_base_end = 0; 39 40 /* GPIO abstraction. */ 41 42 static Gpio_jz4740_chip *gpio_port_c = 0; 43 44 45 46 /* GPIO pin definitions. */ 47 48 enum Jz4740_lcd_gpio_mask 49 { 50 Jz4740_lcd_gpio_d0_d7 = 0xff, 51 }; 52 53 enum Jz4740_lcd_gpio 54 { 55 Jz4740_lcd_gpio_clk = 18, /* pixel clock */ 56 Jz4740_lcd_gpio_rs = 19, /* hsync; command/data select */ 57 Jz4740_lcd_gpio_cs = 20, /* vsync; chip select */ 58 }; 59 60 61 62 static int setup_memory(void) 63 { 64 if (get_memory("jz4740-gpio", &gpio_virt_base, &gpio_virt_base_end)) 65 return 1; 66 67 return 0; 68 } 69 70 71 72 /* Display device. */ 73 74 class Display_device_server : public L4::Server_object_t<L4::Kobject> 75 { 76 Pin_slice slcd8_mask = {.offset=0, .mask=(1 << Jz4740_lcd_gpio_cs) | (1 << Jz4740_lcd_gpio_rs) | 77 (1 << Jz4740_lcd_gpio_clk) | Jz4740_lcd_gpio_d0_d7}; 78 79 Activation *_backlight; 80 81 public: 82 explicit Display_device_server(Activation *backlight) 83 : _backlight(backlight) 84 { 85 } 86 87 /* Dispatch incoming requests. */ 88 89 int dispatch(l4_umword_t obj, L4::Ipc::Iostream &ios) 90 { 91 l4_msgtag_t tag; 92 93 (void) obj; 94 ios >> tag; 95 96 switch (tag.label()) 97 { 98 case Display_op_disable: 99 disable(); 100 return L4_EOK; 101 102 case Display_op_enable: 103 enable(); 104 return L4_EOK; 105 106 default: 107 return -L4_EBADPROTO; 108 } 109 } 110 111 /* Switch the display off. */ 112 113 void disable(void) 114 { 115 /* Configure SLCD8 pins. */ 116 117 gpio_port_c->multi_setup(slcd8_mask, Hw::Gpio_chip::Input, 0); 118 _backlight->disable(); 119 } 120 121 /* Switch the display on. */ 122 123 void enable(void) 124 { 125 /* Configure SLCD8 pins. */ 126 127 gpio_port_c->multi_config_pad(slcd8_mask, Hw::Gpio_chip::Function_alt, 0); 128 _backlight->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 abstraction. */ 141 142 Gpio_jz4740_chip gpio_port(gpio_virt_base + 0x200, gpio_virt_base + 0x300, 32); 143 144 gpio_port_c = &gpio_port; 145 146 /* Obtain a reference to the backlight device. */ 147 148 l4_cap_idx_t backlight = l4re_env_get_cap("backlight"); 149 if (!l4_is_valid_cap(backlight)) return 1; 150 151 /* Use the activation interface with the backlight. */ 152 153 client_Activation backlight_obj(backlight); 154 155 /* Initialise and register a new server object. */ 156 157 Display_device_server server_obj(&backlight_obj); 158 server.registry()->register_obj(&server_obj, "display"); 159 160 /* Enter the IPC server loop. */ 161 162 server.loop(); 163 return 0; 164 }