1 /* 2 * Export MIPS Creator CI20 HDMI display operations as a server. 3 * 4 * Copyright (C) 2018, 2020, 2021 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/hdmi-jz4780.h> 23 #include <l4/devices/lcd-jz4740-config.h> 24 #include <l4/devices/lcd-jz4740-panel.h> 25 #include <l4/devices/panel-loader.h> 26 #include <l4/devices/memory.h> 27 28 #include <l4/re/env.h> 29 30 #include <ipc/irq.h> 31 #include <ipc/server.h> 32 #include "activation_server.h" 33 #include "cpm_client.h" 34 #include "icu_client.h" 35 36 /* Virtual addresses for the HDMI register block plus interrupt capability. */ 37 38 static l4_addr_t hdmi_virt_base = 0, hdmi_virt_base_end = 0; 39 static l4_uint32_t hdmi_irq_start, hdmi_irq_end; 40 static l4_cap_idx_t hdmi_irq, icu; 41 42 /* Device abstractions. */ 43 44 static Hdmi_jz4780_chip *hdmi = 0; 45 static CPM *cpm_device; 46 47 48 49 static int setup_memory(void) 50 { 51 if (get_memory("jz4780-hdmi", &hdmi_virt_base, &hdmi_virt_base_end)) 52 return 1; 53 54 if (get_irq("jz4780-hdmi", &hdmi_irq_start, &hdmi_irq_end)) 55 return 1; 56 57 /* Obtain a reference to the CPM device. */ 58 59 l4_cap_idx_t cpm = l4re_env_get_cap("cpm"); 60 if (!l4_is_valid_cap(cpm)) return 1; 61 62 static client_CPM cpm_obj(cpm); 63 cpm_device = &cpm_obj; 64 65 /* Start the HDMI peripheral. */ 66 67 cpm_device->stop_clock(Clock_hdmi); 68 cpm_device->set_frequency(Clock_frequency_hdmi, 27000000); 69 cpm_device->start_clock(Clock_hdmi); 70 71 /* Load the panel data from the configured library. */ 72 73 struct Jz4740_lcd_panel *panel = (struct Jz4740_lcd_panel *) load_panel(); 74 if (!panel) return 1; 75 76 /* Obtain access to the HDMI interrupt using the ICU. */ 77 78 icu = l4re_env_get_cap("icu"); 79 if (!l4_is_valid_cap(icu)) return 1; 80 81 if (ipc_create_irq(&hdmi_irq)) return 1; 82 83 /* Bind the IRQ object to the interrupt in this thread. */ 84 85 client_ICU icu_obj(icu); 86 87 long err = icu_obj.bind(hdmi_irq_start, hdmi_irq); 88 if (err) return err; 89 90 err = ipc_bind_irq(hdmi_irq, 0, l4re_env()->main_thread); 91 if (err) return err; 92 93 /* Obtain an abstraction for the HDMI peripheral. */ 94 95 hdmi = new Hdmi_jz4780_chip(hdmi_virt_base, hdmi_virt_base_end, hdmi_irq, panel); 96 97 return 0; 98 } 99 100 101 102 /* Display device. */ 103 104 class server_DisplayObject : public Activation 105 { 106 public: 107 /* Switch the display off. */ 108 109 long disable(void) 110 { 111 return L4_EOK; 112 } 113 114 /* Switch the display on. */ 115 116 long enable(void) 117 { 118 uint32_t frequency; 119 120 // NOTE: Should test to see if it is connected. 121 122 if (!cpm_device->get_frequency(Clock_frequency_lcd_pixel, &frequency)) 123 { 124 hdmi->enable(frequency); 125 } 126 127 return L4_EOK; 128 } 129 }; 130 131 132 133 int main(void) 134 { 135 if (setup_memory()) return 1; 136 137 /* Initialise and register a new server object. */ 138 139 server_DisplayObject obj; 140 l4_cap_idx_t server; 141 142 if (ipc_server_bind("display", (l4_umword_t) &obj, &server)) return 1; 143 144 /* Enter the IPC server loop. */ 145 146 ipc_server_loop(Activation_expected_items, &obj, 147 (ipc_server_handler_type) handle_Activation); 148 return 0; 149 }