1 /* 2 * JZ4780 HDMI peripheral support. 3 * 4 * Copyright (C) 2020 Paul Boddie <paul@boddie.org.uk> 5 * 6 * Some structures have been adopted from the Linux DRM bridge driver for 7 * Synopsys DW-HDMI with the following attribution: 8 * 9 * Copyright (C) 2011 Freescale Semiconductor, Inc. 10 * 11 * This program is free software; you can redistribute it and/or 12 * modify it under the terms of the GNU General Public License as 13 * published by the Free Software Foundation; either version 2 of 14 * the License, or (at your option) any later version. 15 * 16 * This program is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 * GNU General Public License for more details. 20 * 21 * You should have received a copy of the GNU General Public License 22 * along with this program; if not, write to the Free Software 23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, 24 * Boston, MA 02110-1301, USA 25 */ 26 27 #pragma once 28 29 #include <l4/devices/lcd-jz4740-panel.h> 30 #include <l4/sys/types.h> 31 #include <stdint.h> 32 33 34 35 // PHY capability definition type. 36 37 struct Phy_capabilities 38 { 39 uint8_t type; 40 const char *name; 41 int gen; 42 int svsret; 43 int configure; 44 }; 45 46 47 48 // PHY configuration types. 49 50 enum Phy_resolutions 51 { 52 Phy_resolution_8bpc = 0, 53 Phy_resolution_10bpc = 1, 54 Phy_resolution_12bpc = 2, 55 Phy_resolution_count = 3, 56 }; 57 58 struct Phy_mpll_config 59 { 60 unsigned long pixelclock; // frequency (Hz) 61 struct { 62 uint16_t cpce; 63 uint16_t gmp; 64 } res[Phy_resolution_count]; 65 }; 66 67 struct Phy_curr_ctrl 68 { 69 unsigned long pixelclock; // frequency (Hz) 70 uint16_t curr[Phy_resolution_count]; 71 }; 72 73 struct Phy_config 74 { 75 unsigned long pixelclock; // frequency (Hz) 76 uint16_t symbol; // clock symbol and transmitter control 77 uint16_t term; // transmission termination value 78 uint16_t vlevel; // voltage level control 79 }; 80 81 82 83 #ifdef __cplusplus 84 85 #include <l4/devices/hw_mmio_register_block.h> 86 87 // HDMI device control. 88 89 class Hdmi_jz4780_chip 90 { 91 private: 92 l4_addr_t _start, _end; 93 l4_cap_idx_t _irq; 94 Hw::Register_block<8> _regs; 95 96 // Identification. 97 98 uint16_t _version; 99 uint8_t _phy_type; 100 const struct Phy_capabilities *_phy_def; 101 102 // Input/output properties. 103 104 struct Jz4740_lcd_panel *_panel; 105 unsigned long _pixelclock; 106 107 // Transfer properties. 108 109 bool _segment_read; 110 uint8_t _device_register, _phy_device_register; 111 112 // Convenience methods for register access. 113 114 void reg_update(uint32_t reg, uint32_t bits, bool enable); 115 void reg_update_field(uint32_t reg, uint32_t mask, uint32_t bits); 116 void reg_fill_field(uint32_t reg, uint32_t mask); 117 118 protected: 119 unsigned long get_pixelclock(); 120 121 void get_identification(); 122 123 void irq_init(); 124 125 void i2c_init(uint32_t reset, uint32_t divider, uint32_t config0, 126 uint32_t config1, uint32_t status, uint32_t mask); 127 128 long i2c_wait(uint32_t status); 129 130 void phy_irq_init(); 131 132 public: 133 Hdmi_jz4780_chip(l4_addr_t start, l4_addr_t end, l4_cap_idx_t irq, 134 struct Jz4740_lcd_panel *panel); 135 136 // Chipset querying. 137 138 void get_version(uint8_t *major, uint16_t *minor); 139 void get_phy_capabilities(const struct Phy_capabilities **phy_def); 140 141 // I2C operations. 142 143 int i2c_read(uint8_t *buf, unsigned int length); 144 145 void i2c_set_address(uint8_t address); 146 void i2c_set_segment(uint8_t segment); 147 void i2c_set_register(uint8_t device_register); 148 149 int i2c_phy_write(uint8_t address, uint16_t value); 150 int i2c_phy_write(uint16_t *buf, unsigned int length); 151 152 void i2c_phy_set_address(uint8_t address); 153 void i2c_phy_set_register(uint8_t device_register); 154 155 // PHY configuration operations. 156 157 void phy_enable_powerdown(bool enable); 158 void phy_enable_tmds(bool enable); 159 void phy_enable_svsret(bool enable); 160 void phy_enable_gen2_powerdown(bool enable); 161 void phy_enable_gen2_tx_power(bool enable); 162 void phy_enable_interface(bool enable); 163 164 // PHY operations. 165 166 long phy_configure(); 167 long phy_configure_specific(); 168 long phy_init(); 169 void phy_power_off(); 170 void phy_power_on(); 171 void phy_reset(); 172 173 // Hotplug and signalling support. 174 175 bool connected(); 176 long wait_for_connection(); 177 long wait_for_tx_phy_lock(int level); 178 long wait_for_phy_irq(uint32_t int_status_flags, uint32_t status_flags, 179 uint32_t polarity_flags); 180 181 // Video output initialisation. 182 183 void enable_overflow_irq(bool enable); 184 void frame_init(); 185 void data_path_init(); 186 void packet_init(); 187 void csc_init(); 188 void sample_init(); 189 void hdcp_init(); 190 191 // Enable the video output. 192 193 long enable(unsigned long pixelclock); 194 }; 195 196 #endif /* __cplusplus */ 197 198 199 200 /* C language interface. */ 201 202 EXTERN_C_BEGIN 203 204 void *jz4780_hdmi_init(l4_addr_t start, l4_addr_t end, l4_cap_idx_t irq, 205 struct Jz4740_lcd_panel *panel); 206 207 void jz4780_hdmi_get_version(void *hdmi, uint8_t *major, uint16_t *minor); 208 209 void jz4780_hdmi_get_phy_capabilities(void *hdmi, const struct Phy_capabilities **phy_def); 210 211 int jz4780_hdmi_i2c_read(void *hdmi, uint8_t *buf, unsigned int length); 212 213 void jz4780_hdmi_i2c_set_address(void *hdmi, uint8_t address); 214 215 void jz4780_hdmi_i2c_set_segment(void *hdmi, uint8_t segment); 216 217 void jz4780_hdmi_i2c_set_register(void *hdmi, uint8_t device_register); 218 219 int jz4780_hdmi_phy_i2c_write(void *hdmi, uint16_t *buf, unsigned int length); 220 221 void jz4780_hdmi_i2c_phy_set_address(void *hdmi, uint8_t address); 222 223 void jz4780_hdmi_i2c_phy_set_register(void *hdmi, uint8_t device_register); 224 225 int jz4780_hdmi_connected(void *hdmi); 226 227 long jz4780_hdmi_wait_for_connection(void *hdmi); 228 229 long jz4780_hdmi_enable(void *hdmi, unsigned long pixelclock); 230 231 EXTERN_C_END