1 1.1 riastrad /* $NetBSD: edid.c,v 1.2 2021/12/18 23:45:31 riastradh Exp $ */ 2 1.1 riastrad 3 1.1 riastrad /* 4 1.1 riastrad * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. 5 1.1 riastrad * 6 1.1 riastrad * Permission is hereby granted, free of charge, to any person obtaining a 7 1.1 riastrad * copy of this software and associated documentation files (the "Software"), 8 1.1 riastrad * to deal in the Software without restriction, including without limitation 9 1.1 riastrad * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 1.1 riastrad * and/or sell copies of the Software, and to permit persons to whom the 11 1.1 riastrad * Software is furnished to do so, subject to the following conditions: 12 1.1 riastrad * 13 1.1 riastrad * The above copyright notice and this permission notice (including the next 14 1.1 riastrad * paragraph) shall be included in all copies or substantial portions of the 15 1.1 riastrad * Software. 16 1.1 riastrad * 17 1.1 riastrad * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 1.1 riastrad * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 1.1 riastrad * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 1.1 riastrad * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 1.1 riastrad * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 1.1 riastrad * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 1.1 riastrad * SOFTWARE. 24 1.1 riastrad * 25 1.1 riastrad * Authors: 26 1.1 riastrad * Ke Yu 27 1.1 riastrad * Zhiyuan Lv <zhiyuan.lv (at) intel.com> 28 1.1 riastrad * 29 1.1 riastrad * Contributors: 30 1.1 riastrad * Terrence Xu <terrence.xu (at) intel.com> 31 1.1 riastrad * Changbin Du <changbin.du (at) intel.com> 32 1.1 riastrad * Bing Niu <bing.niu (at) intel.com> 33 1.1 riastrad * Zhi Wang <zhi.a.wang (at) intel.com> 34 1.1 riastrad * 35 1.1 riastrad */ 36 1.1 riastrad 37 1.1 riastrad #include <sys/cdefs.h> 38 1.1 riastrad __KERNEL_RCSID(0, "$NetBSD: edid.c,v 1.2 2021/12/18 23:45:31 riastradh Exp $"); 39 1.1 riastrad 40 1.1 riastrad #include "i915_drv.h" 41 1.1 riastrad #include "gvt.h" 42 1.1 riastrad 43 1.1 riastrad #define GMBUS1_TOTAL_BYTES_SHIFT 16 44 1.1 riastrad #define GMBUS1_TOTAL_BYTES_MASK 0x1ff 45 1.1 riastrad #define gmbus1_total_byte_count(v) (((v) >> \ 46 1.1 riastrad GMBUS1_TOTAL_BYTES_SHIFT) & GMBUS1_TOTAL_BYTES_MASK) 47 1.1 riastrad #define gmbus1_slave_addr(v) (((v) & 0xff) >> 1) 48 1.1 riastrad #define gmbus1_slave_index(v) (((v) >> 8) & 0xff) 49 1.1 riastrad #define gmbus1_bus_cycle(v) (((v) >> 25) & 0x7) 50 1.1 riastrad 51 1.1 riastrad /* GMBUS0 bits definitions */ 52 1.1 riastrad #define _GMBUS_PIN_SEL_MASK (0x7) 53 1.1 riastrad 54 1.1 riastrad static unsigned char edid_get_byte(struct intel_vgpu *vgpu) 55 1.1 riastrad { 56 1.1 riastrad struct intel_vgpu_i2c_edid *edid = &vgpu->display.i2c_edid; 57 1.1 riastrad unsigned char chr = 0; 58 1.1 riastrad 59 1.1 riastrad if (edid->state == I2C_NOT_SPECIFIED || !edid->slave_selected) { 60 1.1 riastrad gvt_vgpu_err("Driver tries to read EDID without proper sequence!\n"); 61 1.1 riastrad return 0; 62 1.1 riastrad } 63 1.1 riastrad if (edid->current_edid_read >= EDID_SIZE) { 64 1.1 riastrad gvt_vgpu_err("edid_get_byte() exceeds the size of EDID!\n"); 65 1.1 riastrad return 0; 66 1.1 riastrad } 67 1.1 riastrad 68 1.1 riastrad if (!edid->edid_available) { 69 1.1 riastrad gvt_vgpu_err("Reading EDID but EDID is not available!\n"); 70 1.1 riastrad return 0; 71 1.1 riastrad } 72 1.1 riastrad 73 1.1 riastrad if (intel_vgpu_has_monitor_on_port(vgpu, edid->port)) { 74 1.1 riastrad struct intel_vgpu_edid_data *edid_data = 75 1.1 riastrad intel_vgpu_port(vgpu, edid->port)->edid; 76 1.1 riastrad 77 1.1 riastrad chr = edid_data->edid_block[edid->current_edid_read]; 78 1.1 riastrad edid->current_edid_read++; 79 1.1 riastrad } else { 80 1.1 riastrad gvt_vgpu_err("No EDID available during the reading?\n"); 81 1.1 riastrad } 82 1.1 riastrad return chr; 83 1.1 riastrad } 84 1.1 riastrad 85 1.1 riastrad static inline int cnp_get_port_from_gmbus0(u32 gmbus0) 86 1.1 riastrad { 87 1.1 riastrad int port_select = gmbus0 & _GMBUS_PIN_SEL_MASK; 88 1.1 riastrad int port = -EINVAL; 89 1.1 riastrad 90 1.1 riastrad if (port_select == GMBUS_PIN_1_BXT) 91 1.1 riastrad port = PORT_B; 92 1.1 riastrad else if (port_select == GMBUS_PIN_2_BXT) 93 1.1 riastrad port = PORT_C; 94 1.1 riastrad else if (port_select == GMBUS_PIN_3_BXT) 95 1.1 riastrad port = PORT_D; 96 1.1 riastrad else if (port_select == GMBUS_PIN_4_CNP) 97 1.1 riastrad port = PORT_E; 98 1.1 riastrad return port; 99 1.1 riastrad } 100 1.1 riastrad 101 1.1 riastrad static inline int bxt_get_port_from_gmbus0(u32 gmbus0) 102 1.1 riastrad { 103 1.1 riastrad int port_select = gmbus0 & _GMBUS_PIN_SEL_MASK; 104 1.1 riastrad int port = -EINVAL; 105 1.1 riastrad 106 1.1 riastrad if (port_select == GMBUS_PIN_1_BXT) 107 1.1 riastrad port = PORT_B; 108 1.1 riastrad else if (port_select == GMBUS_PIN_2_BXT) 109 1.1 riastrad port = PORT_C; 110 1.1 riastrad else if (port_select == GMBUS_PIN_3_BXT) 111 1.1 riastrad port = PORT_D; 112 1.1 riastrad return port; 113 1.1 riastrad } 114 1.1 riastrad 115 1.1 riastrad static inline int get_port_from_gmbus0(u32 gmbus0) 116 1.1 riastrad { 117 1.1 riastrad int port_select = gmbus0 & _GMBUS_PIN_SEL_MASK; 118 1.1 riastrad int port = -EINVAL; 119 1.1 riastrad 120 1.1 riastrad if (port_select == GMBUS_PIN_VGADDC) 121 1.1 riastrad port = PORT_E; 122 1.1 riastrad else if (port_select == GMBUS_PIN_DPC) 123 1.1 riastrad port = PORT_C; 124 1.1 riastrad else if (port_select == GMBUS_PIN_DPB) 125 1.1 riastrad port = PORT_B; 126 1.1 riastrad else if (port_select == GMBUS_PIN_DPD) 127 1.1 riastrad port = PORT_D; 128 1.1 riastrad return port; 129 1.1 riastrad } 130 1.1 riastrad 131 1.1 riastrad static void reset_gmbus_controller(struct intel_vgpu *vgpu) 132 1.1 riastrad { 133 1.1 riastrad vgpu_vreg_t(vgpu, PCH_GMBUS2) = GMBUS_HW_RDY; 134 1.1 riastrad if (!vgpu->display.i2c_edid.edid_available) 135 1.1 riastrad vgpu_vreg_t(vgpu, PCH_GMBUS2) |= GMBUS_SATOER; 136 1.1 riastrad vgpu->display.i2c_edid.gmbus.phase = GMBUS_IDLE_PHASE; 137 1.1 riastrad } 138 1.1 riastrad 139 1.1 riastrad /* GMBUS0 */ 140 1.1 riastrad static int gmbus0_mmio_write(struct intel_vgpu *vgpu, 141 1.1 riastrad unsigned int offset, void *p_data, unsigned int bytes) 142 1.1 riastrad { 143 1.1 riastrad struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; 144 1.1 riastrad int port, pin_select; 145 1.1 riastrad 146 1.1 riastrad memcpy(&vgpu_vreg(vgpu, offset), p_data, bytes); 147 1.1 riastrad 148 1.1 riastrad pin_select = vgpu_vreg(vgpu, offset) & _GMBUS_PIN_SEL_MASK; 149 1.1 riastrad 150 1.1 riastrad intel_vgpu_init_i2c_edid(vgpu); 151 1.1 riastrad 152 1.1 riastrad if (pin_select == 0) 153 1.1 riastrad return 0; 154 1.1 riastrad 155 1.1 riastrad if (IS_BROXTON(dev_priv)) 156 1.1 riastrad port = bxt_get_port_from_gmbus0(pin_select); 157 1.1 riastrad else if (IS_COFFEELAKE(dev_priv)) 158 1.1 riastrad port = cnp_get_port_from_gmbus0(pin_select); 159 1.1 riastrad else 160 1.1 riastrad port = get_port_from_gmbus0(pin_select); 161 1.1 riastrad if (WARN_ON(port < 0)) 162 1.1 riastrad return 0; 163 1.1 riastrad 164 1.1 riastrad vgpu->display.i2c_edid.state = I2C_GMBUS; 165 1.1 riastrad vgpu->display.i2c_edid.gmbus.phase = GMBUS_IDLE_PHASE; 166 1.1 riastrad 167 1.1 riastrad vgpu_vreg_t(vgpu, PCH_GMBUS2) &= ~GMBUS_ACTIVE; 168 1.1 riastrad vgpu_vreg_t(vgpu, PCH_GMBUS2) |= GMBUS_HW_RDY | GMBUS_HW_WAIT_PHASE; 169 1.1 riastrad 170 1.1 riastrad if (intel_vgpu_has_monitor_on_port(vgpu, port) && 171 1.1 riastrad !intel_vgpu_port_is_dp(vgpu, port)) { 172 1.1 riastrad vgpu->display.i2c_edid.port = port; 173 1.1 riastrad vgpu->display.i2c_edid.edid_available = true; 174 1.1 riastrad vgpu_vreg_t(vgpu, PCH_GMBUS2) &= ~GMBUS_SATOER; 175 1.1 riastrad } else 176 1.1 riastrad vgpu_vreg_t(vgpu, PCH_GMBUS2) |= GMBUS_SATOER; 177 1.1 riastrad return 0; 178 1.1 riastrad } 179 1.1 riastrad 180 1.1 riastrad static int gmbus1_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, 181 1.1 riastrad void *p_data, unsigned int bytes) 182 1.1 riastrad { 183 1.1 riastrad struct intel_vgpu_i2c_edid *i2c_edid = &vgpu->display.i2c_edid; 184 1.1 riastrad u32 slave_addr; 185 1.1 riastrad u32 wvalue = *(u32 *)p_data; 186 1.1 riastrad 187 1.1 riastrad if (vgpu_vreg(vgpu, offset) & GMBUS_SW_CLR_INT) { 188 1.1 riastrad if (!(wvalue & GMBUS_SW_CLR_INT)) { 189 1.1 riastrad vgpu_vreg(vgpu, offset) &= ~GMBUS_SW_CLR_INT; 190 1.1 riastrad reset_gmbus_controller(vgpu); 191 1.1 riastrad } 192 1.1 riastrad /* 193 1.1 riastrad * TODO: "This bit is cleared to zero when an event 194 1.1 riastrad * causes the HW_RDY bit transition to occur " 195 1.1 riastrad */ 196 1.1 riastrad } else { 197 1.1 riastrad /* 198 1.1 riastrad * per bspec setting this bit can cause: 199 1.1 riastrad * 1) INT status bit cleared 200 1.1 riastrad * 2) HW_RDY bit asserted 201 1.1 riastrad */ 202 1.1 riastrad if (wvalue & GMBUS_SW_CLR_INT) { 203 1.1 riastrad vgpu_vreg_t(vgpu, PCH_GMBUS2) &= ~GMBUS_INT; 204 1.1 riastrad vgpu_vreg_t(vgpu, PCH_GMBUS2) |= GMBUS_HW_RDY; 205 1.1 riastrad } 206 1.1 riastrad 207 1.1 riastrad /* For virtualization, we suppose that HW is always ready, 208 1.1 riastrad * so GMBUS_SW_RDY should always be cleared 209 1.1 riastrad */ 210 1.1 riastrad if (wvalue & GMBUS_SW_RDY) 211 1.1 riastrad wvalue &= ~GMBUS_SW_RDY; 212 1.1 riastrad 213 1.1 riastrad i2c_edid->gmbus.total_byte_count = 214 1.1 riastrad gmbus1_total_byte_count(wvalue); 215 1.1 riastrad slave_addr = gmbus1_slave_addr(wvalue); 216 1.1 riastrad 217 1.1 riastrad /* vgpu gmbus only support EDID */ 218 1.1 riastrad if (slave_addr == EDID_ADDR) { 219 1.1 riastrad i2c_edid->slave_selected = true; 220 1.1 riastrad } else if (slave_addr != 0) { 221 1.1 riastrad gvt_dbg_dpy( 222 1.1 riastrad "vgpu%d: unsupported gmbus slave addr(0x%x)\n" 223 1.1 riastrad " gmbus operations will be ignored.\n", 224 1.1 riastrad vgpu->id, slave_addr); 225 1.1 riastrad } 226 1.1 riastrad 227 1.1 riastrad if (wvalue & GMBUS_CYCLE_INDEX) 228 1.1 riastrad i2c_edid->current_edid_read = 229 1.1 riastrad gmbus1_slave_index(wvalue); 230 1.1 riastrad 231 1.1 riastrad i2c_edid->gmbus.cycle_type = gmbus1_bus_cycle(wvalue); 232 1.1 riastrad switch (gmbus1_bus_cycle(wvalue)) { 233 1.1 riastrad case GMBUS_NOCYCLE: 234 1.1 riastrad break; 235 1.1 riastrad case GMBUS_STOP: 236 1.1 riastrad /* From spec: 237 1.1 riastrad * This can only cause a STOP to be generated 238 1.1 riastrad * if a GMBUS cycle is generated, the GMBUS is 239 1.1 riastrad * currently in a data/wait/idle phase, or it is in a 240 1.1 riastrad * WAIT phase 241 1.1 riastrad */ 242 1.1 riastrad if (gmbus1_bus_cycle(vgpu_vreg(vgpu, offset)) 243 1.1 riastrad != GMBUS_NOCYCLE) { 244 1.1 riastrad intel_vgpu_init_i2c_edid(vgpu); 245 1.1 riastrad /* After the 'stop' cycle, hw state would become 246 1.1 riastrad * 'stop phase' and then 'idle phase' after a 247 1.1 riastrad * few milliseconds. In emulation, we just set 248 1.1 riastrad * it as 'idle phase' ('stop phase' is not 249 1.1 riastrad * visible in gmbus interface) 250 1.1 riastrad */ 251 1.1 riastrad i2c_edid->gmbus.phase = GMBUS_IDLE_PHASE; 252 1.1 riastrad vgpu_vreg_t(vgpu, PCH_GMBUS2) &= ~GMBUS_ACTIVE; 253 1.1 riastrad } 254 1.1 riastrad break; 255 1.1 riastrad case NIDX_NS_W: 256 1.1 riastrad case IDX_NS_W: 257 1.1 riastrad case NIDX_STOP: 258 1.1 riastrad case IDX_STOP: 259 1.1 riastrad /* From hw spec the GMBUS phase 260 1.1 riastrad * transition like this: 261 1.1 riastrad * START (-->INDEX) -->DATA 262 1.1 riastrad */ 263 1.1 riastrad i2c_edid->gmbus.phase = GMBUS_DATA_PHASE; 264 1.1 riastrad vgpu_vreg_t(vgpu, PCH_GMBUS2) |= GMBUS_ACTIVE; 265 1.1 riastrad break; 266 1.1 riastrad default: 267 1.1 riastrad gvt_vgpu_err("Unknown/reserved GMBUS cycle detected!\n"); 268 1.1 riastrad break; 269 1.1 riastrad } 270 1.1 riastrad /* 271 1.1 riastrad * From hw spec the WAIT state will be 272 1.1 riastrad * cleared: 273 1.1 riastrad * (1) in a new GMBUS cycle 274 1.1 riastrad * (2) by generating a stop 275 1.1 riastrad */ 276 1.1 riastrad vgpu_vreg(vgpu, offset) = wvalue; 277 1.1 riastrad } 278 1.1 riastrad return 0; 279 1.1 riastrad } 280 1.1 riastrad 281 1.1 riastrad static int gmbus3_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, 282 1.1 riastrad void *p_data, unsigned int bytes) 283 1.1 riastrad { 284 1.1 riastrad WARN_ON(1); 285 1.1 riastrad return 0; 286 1.1 riastrad } 287 1.1 riastrad 288 1.1 riastrad static int gmbus3_mmio_read(struct intel_vgpu *vgpu, unsigned int offset, 289 1.1 riastrad void *p_data, unsigned int bytes) 290 1.1 riastrad { 291 1.1 riastrad int i; 292 1.1 riastrad unsigned char byte_data; 293 1.1 riastrad struct intel_vgpu_i2c_edid *i2c_edid = &vgpu->display.i2c_edid; 294 1.1 riastrad int byte_left = i2c_edid->gmbus.total_byte_count - 295 1.1 riastrad i2c_edid->current_edid_read; 296 1.1 riastrad int byte_count = byte_left; 297 1.1 riastrad u32 reg_data = 0; 298 1.1 riastrad 299 1.1 riastrad /* Data can only be recevied if previous settings correct */ 300 1.1 riastrad if (vgpu_vreg_t(vgpu, PCH_GMBUS1) & GMBUS_SLAVE_READ) { 301 1.1 riastrad if (byte_left <= 0) { 302 1.1 riastrad memcpy(p_data, &vgpu_vreg(vgpu, offset), bytes); 303 1.1 riastrad return 0; 304 1.1 riastrad } 305 1.1 riastrad 306 1.1 riastrad if (byte_count > 4) 307 1.1 riastrad byte_count = 4; 308 1.1 riastrad for (i = 0; i < byte_count; i++) { 309 1.1 riastrad byte_data = edid_get_byte(vgpu); 310 1.1 riastrad reg_data |= (byte_data << (i << 3)); 311 1.1 riastrad } 312 1.1 riastrad 313 1.1 riastrad memcpy(&vgpu_vreg(vgpu, offset), ®_data, byte_count); 314 1.1 riastrad memcpy(p_data, &vgpu_vreg(vgpu, offset), bytes); 315 1.1 riastrad 316 1.1 riastrad if (byte_left <= 4) { 317 1.1 riastrad switch (i2c_edid->gmbus.cycle_type) { 318 1.1 riastrad case NIDX_STOP: 319 1.1 riastrad case IDX_STOP: 320 1.1 riastrad i2c_edid->gmbus.phase = GMBUS_IDLE_PHASE; 321 1.1 riastrad break; 322 1.1 riastrad case NIDX_NS_W: 323 1.1 riastrad case IDX_NS_W: 324 1.1 riastrad default: 325 1.1 riastrad i2c_edid->gmbus.phase = GMBUS_WAIT_PHASE; 326 1.1 riastrad break; 327 1.1 riastrad } 328 1.1 riastrad intel_vgpu_init_i2c_edid(vgpu); 329 1.1 riastrad } 330 1.1 riastrad /* 331 1.1 riastrad * Read GMBUS3 during send operation, 332 1.1 riastrad * return the latest written value 333 1.1 riastrad */ 334 1.1 riastrad } else { 335 1.1 riastrad memcpy(p_data, &vgpu_vreg(vgpu, offset), bytes); 336 1.1 riastrad gvt_vgpu_err("warning: gmbus3 read with nothing returned\n"); 337 1.1 riastrad } 338 1.1 riastrad return 0; 339 1.1 riastrad } 340 1.1 riastrad 341 1.1 riastrad static int gmbus2_mmio_read(struct intel_vgpu *vgpu, unsigned int offset, 342 1.1 riastrad void *p_data, unsigned int bytes) 343 1.1 riastrad { 344 1.1 riastrad u32 value = vgpu_vreg(vgpu, offset); 345 1.1 riastrad 346 1.1 riastrad if (!(vgpu_vreg(vgpu, offset) & GMBUS_INUSE)) 347 1.1 riastrad vgpu_vreg(vgpu, offset) |= GMBUS_INUSE; 348 1.1 riastrad memcpy(p_data, (void *)&value, bytes); 349 1.1 riastrad return 0; 350 1.1 riastrad } 351 1.1 riastrad 352 1.1 riastrad static int gmbus2_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, 353 1.1 riastrad void *p_data, unsigned int bytes) 354 1.1 riastrad { 355 1.1 riastrad u32 wvalue = *(u32 *)p_data; 356 1.1 riastrad 357 1.1 riastrad if (wvalue & GMBUS_INUSE) 358 1.1 riastrad vgpu_vreg(vgpu, offset) &= ~GMBUS_INUSE; 359 1.1 riastrad /* All other bits are read-only */ 360 1.1 riastrad return 0; 361 1.1 riastrad } 362 1.1 riastrad 363 1.1 riastrad /** 364 1.1 riastrad * intel_gvt_i2c_handle_gmbus_read - emulate gmbus register mmio read 365 1.1 riastrad * @vgpu: a vGPU 366 1.1 riastrad * @offset: reg offset 367 1.1 riastrad * @p_data: data return buffer 368 1.1 riastrad * @bytes: access data length 369 1.1 riastrad * 370 1.1 riastrad * This function is used to emulate gmbus register mmio read 371 1.1 riastrad * 372 1.1 riastrad * Returns: 373 1.1 riastrad * Zero on success, negative error code if failed. 374 1.1 riastrad * 375 1.1 riastrad */ 376 1.1 riastrad int intel_gvt_i2c_handle_gmbus_read(struct intel_vgpu *vgpu, 377 1.1 riastrad unsigned int offset, void *p_data, unsigned int bytes) 378 1.1 riastrad { 379 1.1 riastrad if (WARN_ON(bytes > 8 && (offset & (bytes - 1)))) 380 1.1 riastrad return -EINVAL; 381 1.1 riastrad 382 1.1 riastrad if (offset == i915_mmio_reg_offset(PCH_GMBUS2)) 383 1.1 riastrad return gmbus2_mmio_read(vgpu, offset, p_data, bytes); 384 1.1 riastrad else if (offset == i915_mmio_reg_offset(PCH_GMBUS3)) 385 1.1 riastrad return gmbus3_mmio_read(vgpu, offset, p_data, bytes); 386 1.1 riastrad 387 1.1 riastrad memcpy(p_data, &vgpu_vreg(vgpu, offset), bytes); 388 1.1 riastrad return 0; 389 1.1 riastrad } 390 1.1 riastrad 391 1.1 riastrad /** 392 1.1 riastrad * intel_gvt_i2c_handle_gmbus_write - emulate gmbus register mmio write 393 1.1 riastrad * @vgpu: a vGPU 394 1.1 riastrad * @offset: reg offset 395 1.1 riastrad * @p_data: data return buffer 396 1.1 riastrad * @bytes: access data length 397 1.1 riastrad * 398 1.1 riastrad * This function is used to emulate gmbus register mmio write 399 1.1 riastrad * 400 1.1 riastrad * Returns: 401 1.1 riastrad * Zero on success, negative error code if failed. 402 1.1 riastrad * 403 1.1 riastrad */ 404 1.1 riastrad int intel_gvt_i2c_handle_gmbus_write(struct intel_vgpu *vgpu, 405 1.1 riastrad unsigned int offset, void *p_data, unsigned int bytes) 406 1.1 riastrad { 407 1.1 riastrad if (WARN_ON(bytes > 8 && (offset & (bytes - 1)))) 408 1.1 riastrad return -EINVAL; 409 1.1 riastrad 410 1.1 riastrad if (offset == i915_mmio_reg_offset(PCH_GMBUS0)) 411 1.1 riastrad return gmbus0_mmio_write(vgpu, offset, p_data, bytes); 412 1.1 riastrad else if (offset == i915_mmio_reg_offset(PCH_GMBUS1)) 413 1.1 riastrad return gmbus1_mmio_write(vgpu, offset, p_data, bytes); 414 1.1 riastrad else if (offset == i915_mmio_reg_offset(PCH_GMBUS2)) 415 1.1 riastrad return gmbus2_mmio_write(vgpu, offset, p_data, bytes); 416 1.1 riastrad else if (offset == i915_mmio_reg_offset(PCH_GMBUS3)) 417 1.1 riastrad return gmbus3_mmio_write(vgpu, offset, p_data, bytes); 418 1.1 riastrad 419 1.1 riastrad memcpy(&vgpu_vreg(vgpu, offset), p_data, bytes); 420 1.1 riastrad return 0; 421 1.1 riastrad } 422 1.1 riastrad 423 1.1 riastrad enum { 424 1.1 riastrad AUX_CH_CTL = 0, 425 1.1 riastrad AUX_CH_DATA1, 426 1.1 riastrad AUX_CH_DATA2, 427 1.1 riastrad AUX_CH_DATA3, 428 1.1 riastrad AUX_CH_DATA4, 429 1.1 riastrad AUX_CH_DATA5 430 1.1 riastrad }; 431 1.1 riastrad 432 1.1 riastrad static inline int get_aux_ch_reg(unsigned int offset) 433 1.1 riastrad { 434 1.1 riastrad int reg; 435 1.1 riastrad 436 1.1 riastrad switch (offset & 0xff) { 437 1.1 riastrad case 0x10: 438 1.1 riastrad reg = AUX_CH_CTL; 439 1.1 riastrad break; 440 1.1 riastrad case 0x14: 441 1.1 riastrad reg = AUX_CH_DATA1; 442 1.1 riastrad break; 443 1.1 riastrad case 0x18: 444 1.1 riastrad reg = AUX_CH_DATA2; 445 1.1 riastrad break; 446 1.1 riastrad case 0x1c: 447 1.1 riastrad reg = AUX_CH_DATA3; 448 1.1 riastrad break; 449 1.1 riastrad case 0x20: 450 1.1 riastrad reg = AUX_CH_DATA4; 451 1.1 riastrad break; 452 1.1 riastrad case 0x24: 453 1.1 riastrad reg = AUX_CH_DATA5; 454 1.1 riastrad break; 455 1.1 riastrad default: 456 1.1 riastrad reg = -1; 457 1.1 riastrad break; 458 1.1 riastrad } 459 1.1 riastrad return reg; 460 1.1 riastrad } 461 1.1 riastrad 462 1.1 riastrad #define AUX_CTL_MSG_LENGTH(reg) \ 463 1.1 riastrad ((reg & DP_AUX_CH_CTL_MESSAGE_SIZE_MASK) >> \ 464 1.1 riastrad DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) 465 1.1 riastrad 466 1.1 riastrad /** 467 1.1 riastrad * intel_gvt_i2c_handle_aux_ch_write - emulate AUX channel register write 468 1.1 riastrad * @vgpu: a vGPU 469 1.1 riastrad * @port_idx: port index 470 1.1 riastrad * @offset: reg offset 471 1.1 riastrad * @p_data: write ptr 472 1.1 riastrad * 473 1.1 riastrad * This function is used to emulate AUX channel register write 474 1.1 riastrad * 475 1.1 riastrad */ 476 1.1 riastrad void intel_gvt_i2c_handle_aux_ch_write(struct intel_vgpu *vgpu, 477 1.1 riastrad int port_idx, 478 1.1 riastrad unsigned int offset, 479 1.1 riastrad void *p_data) 480 1.1 riastrad { 481 1.1 riastrad struct intel_vgpu_i2c_edid *i2c_edid = &vgpu->display.i2c_edid; 482 1.1 riastrad int msg_length, ret_msg_size; 483 1.1 riastrad int msg, addr, ctrl, op; 484 1.1 riastrad u32 value = *(u32 *)p_data; 485 1.1 riastrad int aux_data_for_write = 0; 486 1.1 riastrad int reg = get_aux_ch_reg(offset); 487 1.1 riastrad 488 1.1 riastrad if (reg != AUX_CH_CTL) { 489 1.1 riastrad vgpu_vreg(vgpu, offset) = value; 490 1.1 riastrad return; 491 1.1 riastrad } 492 1.1 riastrad 493 1.1 riastrad msg_length = AUX_CTL_MSG_LENGTH(value); 494 1.1 riastrad // check the msg in DATA register. 495 1.1 riastrad msg = vgpu_vreg(vgpu, offset + 4); 496 1.1 riastrad addr = (msg >> 8) & 0xffff; 497 1.1 riastrad ctrl = (msg >> 24) & 0xff; 498 1.1 riastrad op = ctrl >> 4; 499 1.1 riastrad if (!(value & DP_AUX_CH_CTL_SEND_BUSY)) { 500 1.1 riastrad /* The ctl write to clear some states */ 501 1.1 riastrad return; 502 1.1 riastrad } 503 1.1 riastrad 504 1.1 riastrad /* Always set the wanted value for vms. */ 505 1.1 riastrad ret_msg_size = (((op & 0x1) == GVT_AUX_I2C_READ) ? 2 : 1); 506 1.1 riastrad vgpu_vreg(vgpu, offset) = 507 1.1 riastrad DP_AUX_CH_CTL_DONE | 508 1.1 riastrad ((ret_msg_size << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) & 509 1.1 riastrad DP_AUX_CH_CTL_MESSAGE_SIZE_MASK); 510 1.1 riastrad 511 1.1 riastrad if (msg_length == 3) { 512 1.1 riastrad if (!(op & GVT_AUX_I2C_MOT)) { 513 1.1 riastrad /* stop */ 514 1.1 riastrad intel_vgpu_init_i2c_edid(vgpu); 515 1.1 riastrad } else { 516 1.1 riastrad /* start or restart */ 517 1.1 riastrad i2c_edid->aux_ch.i2c_over_aux_ch = true; 518 1.1 riastrad i2c_edid->aux_ch.aux_ch_mot = true; 519 1.1 riastrad if (addr == 0) { 520 1.1 riastrad /* reset the address */ 521 1.1 riastrad intel_vgpu_init_i2c_edid(vgpu); 522 1.1 riastrad } else if (addr == EDID_ADDR) { 523 1.1 riastrad i2c_edid->state = I2C_AUX_CH; 524 1.1 riastrad i2c_edid->port = port_idx; 525 1.1 riastrad i2c_edid->slave_selected = true; 526 1.1 riastrad if (intel_vgpu_has_monitor_on_port(vgpu, 527 1.1 riastrad port_idx) && 528 1.1 riastrad intel_vgpu_port_is_dp(vgpu, port_idx)) 529 1.1 riastrad i2c_edid->edid_available = true; 530 1.1 riastrad } 531 1.1 riastrad } 532 1.1 riastrad } else if ((op & 0x1) == GVT_AUX_I2C_WRITE) { 533 1.1 riastrad /* TODO 534 1.1 riastrad * We only support EDID reading from I2C_over_AUX. And 535 1.1 riastrad * we do not expect the index mode to be used. Right now 536 1.1 riastrad * the WRITE operation is ignored. It is good enough to 537 1.1 riastrad * support the gfx driver to do EDID access. 538 1.1 riastrad */ 539 1.1 riastrad } else { 540 1.1 riastrad if (WARN_ON((op & 0x1) != GVT_AUX_I2C_READ)) 541 1.1 riastrad return; 542 1.1 riastrad if (WARN_ON(msg_length != 4)) 543 1.1 riastrad return; 544 1.1 riastrad if (i2c_edid->edid_available && i2c_edid->slave_selected) { 545 1.1 riastrad unsigned char val = edid_get_byte(vgpu); 546 1.1 riastrad 547 1.1 riastrad aux_data_for_write = (val << 16); 548 1.1 riastrad } else 549 1.1 riastrad aux_data_for_write = (0xff << 16); 550 1.1 riastrad } 551 1.1 riastrad /* write the return value in AUX_CH_DATA reg which includes: 552 1.1 riastrad * ACK of I2C_WRITE 553 1.1 riastrad * returned byte if it is READ 554 1.1 riastrad */ 555 1.1 riastrad aux_data_for_write |= GVT_AUX_I2C_REPLY_ACK << 24; 556 1.1 riastrad vgpu_vreg(vgpu, offset + 4) = aux_data_for_write; 557 1.1 riastrad } 558 1.1 riastrad 559 1.1 riastrad /** 560 1.1 riastrad * intel_vgpu_init_i2c_edid - initialize vGPU i2c edid emulation 561 1.1 riastrad * @vgpu: a vGPU 562 1.1 riastrad * 563 1.1 riastrad * This function is used to initialize vGPU i2c edid emulation stuffs 564 1.1 riastrad * 565 1.1 riastrad */ 566 1.1 riastrad void intel_vgpu_init_i2c_edid(struct intel_vgpu *vgpu) 567 1.1 riastrad { 568 1.1 riastrad struct intel_vgpu_i2c_edid *edid = &vgpu->display.i2c_edid; 569 1.1 riastrad 570 1.1 riastrad edid->state = I2C_NOT_SPECIFIED; 571 1.1 riastrad 572 1.1 riastrad edid->port = -1; 573 1.1 riastrad edid->slave_selected = false; 574 1.1 riastrad edid->edid_available = false; 575 1.1 riastrad edid->current_edid_read = 0; 576 1.1 riastrad 577 1.1 riastrad memset(&edid->gmbus, 0, sizeof(struct intel_vgpu_i2c_gmbus)); 578 1.1 riastrad 579 1.1 riastrad edid->aux_ch.i2c_over_aux_ch = false; 580 1.1 riastrad edid->aux_ch.aux_ch_mot = false; 581 1.1 riastrad } 582