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