1 /* 2 * Xilinx Display Port 3 * 4 * Copyright (C) 2015 : GreenSocs Ltd 5 * http://www.greensocs.com/ , email: info@greensocs.com 6 * 7 * Developed by : 8 * Frederic Konrad <fred.konrad@greensocs.com> 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License as published by 12 * the Free Software Foundation, either version 2 of the License, or 13 * (at your option)any later version. 14 * 15 * This program is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License along 21 * with this program; if not, see <http://www.gnu.org/licenses/>. 22 * 23 */ 24 25 #include "qemu/osdep.h" 26 #include "qapi/error.h" 27 #include "qemu/error-report.h" 28 #include "qemu/log.h" 29 #include "qemu/module.h" 30 #include "hw/display/xlnx_dp.h" 31 #include "hw/irq.h" 32 #include "migration/vmstate.h" 33 34 #ifndef DEBUG_DP 35 #define DEBUG_DP 0 36 #endif 37 38 #define DPRINTF(fmt, ...) do { \ 39 if (DEBUG_DP) { \ 40 qemu_log("xlnx_dp: " fmt , ## __VA_ARGS__); \ 41 } \ 42 } while (0) 43 44 /* 45 * Register offset for DP. 46 */ 47 #define DP_LINK_BW_SET (0x0000 >> 2) 48 #define DP_LANE_COUNT_SET (0x0004 >> 2) 49 #define DP_ENHANCED_FRAME_EN (0x0008 >> 2) 50 #define DP_TRAINING_PATTERN_SET (0x000C >> 2) 51 #define DP_LINK_QUAL_PATTERN_SET (0x0010 >> 2) 52 #define DP_SCRAMBLING_DISABLE (0x0014 >> 2) 53 #define DP_DOWNSPREAD_CTRL (0x0018 >> 2) 54 #define DP_SOFTWARE_RESET (0x001C >> 2) 55 #define DP_TRANSMITTER_ENABLE (0x0080 >> 2) 56 #define DP_MAIN_STREAM_ENABLE (0x0084 >> 2) 57 #define DP_FORCE_SCRAMBLER_RESET (0x00C0 >> 2) 58 #define DP_VERSION_REGISTER (0x00F8 >> 2) 59 #define DP_CORE_ID (0x00FC >> 2) 60 61 #define DP_AUX_COMMAND_REGISTER (0x0100 >> 2) 62 #define AUX_ADDR_ONLY_MASK (0x1000) 63 #define AUX_COMMAND_MASK (0x0F00) 64 #define AUX_COMMAND_SHIFT (8) 65 #define AUX_COMMAND_NBYTES (0x000F) 66 67 #define DP_AUX_WRITE_FIFO (0x0104 >> 2) 68 #define DP_AUX_ADDRESS (0x0108 >> 2) 69 #define DP_AUX_CLOCK_DIVIDER (0x010C >> 2) 70 #define DP_TX_USER_FIFO_OVERFLOW (0x0110 >> 2) 71 #define DP_INTERRUPT_SIGNAL_STATE (0x0130 >> 2) 72 #define DP_AUX_REPLY_DATA (0x0134 >> 2) 73 #define DP_AUX_REPLY_CODE (0x0138 >> 2) 74 #define DP_AUX_REPLY_COUNT (0x013C >> 2) 75 #define DP_REPLY_DATA_COUNT (0x0148 >> 2) 76 #define DP_REPLY_STATUS (0x014C >> 2) 77 #define DP_HPD_DURATION (0x0150 >> 2) 78 #define DP_MAIN_STREAM_HTOTAL (0x0180 >> 2) 79 #define DP_MAIN_STREAM_VTOTAL (0x0184 >> 2) 80 #define DP_MAIN_STREAM_POLARITY (0x0188 >> 2) 81 #define DP_MAIN_STREAM_HSWIDTH (0x018C >> 2) 82 #define DP_MAIN_STREAM_VSWIDTH (0x0190 >> 2) 83 #define DP_MAIN_STREAM_HRES (0x0194 >> 2) 84 #define DP_MAIN_STREAM_VRES (0x0198 >> 2) 85 #define DP_MAIN_STREAM_HSTART (0x019C >> 2) 86 #define DP_MAIN_STREAM_VSTART (0x01A0 >> 2) 87 #define DP_MAIN_STREAM_MISC0 (0x01A4 >> 2) 88 #define DP_MAIN_STREAM_MISC1 (0x01A8 >> 2) 89 #define DP_MAIN_STREAM_M_VID (0x01AC >> 2) 90 #define DP_MSA_TRANSFER_UNIT_SIZE (0x01B0 >> 2) 91 #define DP_MAIN_STREAM_N_VID (0x01B4 >> 2) 92 #define DP_USER_DATA_COUNT_PER_LANE (0x01BC >> 2) 93 #define DP_MIN_BYTES_PER_TU (0x01C4 >> 2) 94 #define DP_FRAC_BYTES_PER_TU (0x01C8 >> 2) 95 #define DP_INIT_WAIT (0x01CC >> 2) 96 #define DP_PHY_RESET (0x0200 >> 2) 97 #define DP_PHY_VOLTAGE_DIFF_LANE_0 (0x0220 >> 2) 98 #define DP_PHY_VOLTAGE_DIFF_LANE_1 (0x0224 >> 2) 99 #define DP_TRANSMIT_PRBS7 (0x0230 >> 2) 100 #define DP_PHY_CLOCK_SELECT (0x0234 >> 2) 101 #define DP_TX_PHY_POWER_DOWN (0x0238 >> 2) 102 #define DP_PHY_PRECURSOR_LANE_0 (0x023C >> 2) 103 #define DP_PHY_PRECURSOR_LANE_1 (0x0240 >> 2) 104 #define DP_PHY_POSTCURSOR_LANE_0 (0x024C >> 2) 105 #define DP_PHY_POSTCURSOR_LANE_1 (0x0250 >> 2) 106 #define DP_PHY_STATUS (0x0280 >> 2) 107 108 #define DP_TX_AUDIO_CONTROL (0x0300 >> 2) 109 #define DP_TX_AUD_CTRL (1) 110 111 #define DP_TX_AUDIO_CHANNELS (0x0304 >> 2) 112 #define DP_TX_AUDIO_INFO_DATA(n) ((0x0308 + 4 * n) >> 2) 113 #define DP_TX_M_AUD (0x0328 >> 2) 114 #define DP_TX_N_AUD (0x032C >> 2) 115 #define DP_TX_AUDIO_EXT_DATA(n) ((0x0330 + 4 * n) >> 2) 116 #define DP_INT_STATUS (0x03A0 >> 2) 117 #define DP_INT_VBLNK_START (1 << 13) 118 #define DP_INT_MASK (0x03A4 >> 2) 119 #define DP_INT_EN (0x03A8 >> 2) 120 #define DP_INT_DS (0x03AC >> 2) 121 122 /* 123 * Registers offset for Audio Video Buffer configuration. 124 */ 125 #define V_BLEND_OFFSET (0xA000) 126 #define V_BLEND_BG_CLR_0 (0x0000 >> 2) 127 #define V_BLEND_BG_CLR_1 (0x0004 >> 2) 128 #define V_BLEND_BG_CLR_2 (0x0008 >> 2) 129 #define V_BLEND_SET_GLOBAL_ALPHA_REG (0x000C >> 2) 130 #define V_BLEND_OUTPUT_VID_FORMAT (0x0014 >> 2) 131 #define V_BLEND_LAYER0_CONTROL (0x0018 >> 2) 132 #define V_BLEND_LAYER1_CONTROL (0x001C >> 2) 133 134 #define V_BLEND_RGB2YCBCR_COEFF(n) ((0x0020 + 4 * n) >> 2) 135 #define V_BLEND_IN1CSC_COEFF(n) ((0x0044 + 4 * n) >> 2) 136 137 #define V_BLEND_LUMA_IN1CSC_OFFSET (0x0068 >> 2) 138 #define V_BLEND_CR_IN1CSC_OFFSET (0x006C >> 2) 139 #define V_BLEND_CB_IN1CSC_OFFSET (0x0070 >> 2) 140 #define V_BLEND_LUMA_OUTCSC_OFFSET (0x0074 >> 2) 141 #define V_BLEND_CR_OUTCSC_OFFSET (0x0078 >> 2) 142 #define V_BLEND_CB_OUTCSC_OFFSET (0x007C >> 2) 143 144 #define V_BLEND_IN2CSC_COEFF(n) ((0x0080 + 4 * n) >> 2) 145 146 #define V_BLEND_LUMA_IN2CSC_OFFSET (0x00A4 >> 2) 147 #define V_BLEND_CR_IN2CSC_OFFSET (0x00A8 >> 2) 148 #define V_BLEND_CB_IN2CSC_OFFSET (0x00AC >> 2) 149 #define V_BLEND_CHROMA_KEY_ENABLE (0x01D0 >> 2) 150 #define V_BLEND_CHROMA_KEY_COMP1 (0x01D4 >> 2) 151 #define V_BLEND_CHROMA_KEY_COMP2 (0x01D8 >> 2) 152 #define V_BLEND_CHROMA_KEY_COMP3 (0x01DC >> 2) 153 154 /* 155 * Registers offset for Audio Video Buffer configuration. 156 */ 157 #define AV_BUF_MANAGER_OFFSET (0xB000) 158 #define AV_BUF_FORMAT (0x0000 >> 2) 159 #define AV_BUF_NON_LIVE_LATENCY (0x0008 >> 2) 160 #define AV_CHBUF0 (0x0010 >> 2) 161 #define AV_CHBUF1 (0x0014 >> 2) 162 #define AV_CHBUF2 (0x0018 >> 2) 163 #define AV_CHBUF3 (0x001C >> 2) 164 #define AV_CHBUF4 (0x0020 >> 2) 165 #define AV_CHBUF5 (0x0024 >> 2) 166 #define AV_BUF_STC_CONTROL (0x002C >> 2) 167 #define AV_BUF_STC_INIT_VALUE0 (0x0030 >> 2) 168 #define AV_BUF_STC_INIT_VALUE1 (0x0034 >> 2) 169 #define AV_BUF_STC_ADJ (0x0038 >> 2) 170 #define AV_BUF_STC_VIDEO_VSYNC_TS_REG0 (0x003C >> 2) 171 #define AV_BUF_STC_VIDEO_VSYNC_TS_REG1 (0x0040 >> 2) 172 #define AV_BUF_STC_EXT_VSYNC_TS_REG0 (0x0044 >> 2) 173 #define AV_BUF_STC_EXT_VSYNC_TS_REG1 (0x0048 >> 2) 174 #define AV_BUF_STC_CUSTOM_EVENT_TS_REG0 (0x004C >> 2) 175 #define AV_BUF_STC_CUSTOM_EVENT_TS_REG1 (0x0050 >> 2) 176 #define AV_BUF_STC_CUSTOM_EVENT2_TS_REG0 (0x0054 >> 2) 177 #define AV_BUF_STC_CUSTOM_EVENT2_TS_REG1 (0x0058 >> 2) 178 #define AV_BUF_STC_SNAPSHOT0 (0x0060 >> 2) 179 #define AV_BUF_STC_SNAPSHOT1 (0x0064 >> 2) 180 #define AV_BUF_OUTPUT_AUDIO_VIDEO_SELECT (0x0070 >> 2) 181 #define AV_BUF_HCOUNT_VCOUNT_INT0 (0x0074 >> 2) 182 #define AV_BUF_HCOUNT_VCOUNT_INT1 (0x0078 >> 2) 183 #define AV_BUF_DITHER_CONFIG (0x007C >> 2) 184 #define AV_BUF_DITHER_CONFIG_MAX (0x008C >> 2) 185 #define AV_BUF_DITHER_CONFIG_MIN (0x0090 >> 2) 186 #define AV_BUF_PATTERN_GEN_SELECT (0x0100 >> 2) 187 #define AV_BUF_AUD_VID_CLK_SOURCE (0x0120 >> 2) 188 #define AV_BUF_SRST_REG (0x0124 >> 2) 189 #define AV_BUF_AUDIO_RDY_INTERVAL (0x0128 >> 2) 190 #define AV_BUF_AUDIO_CH_CONFIG (0x012C >> 2) 191 192 #define AV_BUF_GRAPHICS_COMP_SCALE_FACTOR(n)((0x0200 + 4 * n) >> 2) 193 194 #define AV_BUF_VIDEO_COMP_SCALE_FACTOR(n) ((0x020C + 4 * n) >> 2) 195 196 #define AV_BUF_LIVE_VIDEO_COMP_SF(n) ((0x0218 + 4 * n) >> 2) 197 198 #define AV_BUF_LIVE_VID_CONFIG (0x0224 >> 2) 199 200 #define AV_BUF_LIVE_GFX_COMP_SF(n) ((0x0228 + 4 * n) >> 2) 201 202 #define AV_BUF_LIVE_GFX_CONFIG (0x0234 >> 2) 203 204 #define AUDIO_MIXER_REGISTER_OFFSET (0xC000) 205 #define AUDIO_MIXER_VOLUME_CONTROL (0x0000 >> 2) 206 #define AUDIO_MIXER_META_DATA (0x0004 >> 2) 207 #define AUD_CH_STATUS_REG(n) ((0x0008 + 4 * n) >> 2) 208 #define AUD_CH_A_DATA_REG(n) ((0x0020 + 4 * n) >> 2) 209 #define AUD_CH_B_DATA_REG(n) ((0x0038 + 4 * n) >> 2) 210 211 #define DP_AUDIO_DMA_CHANNEL(n) (4 + n) 212 #define DP_GRAPHIC_DMA_CHANNEL (3) 213 #define DP_VIDEO_DMA_CHANNEL (0) 214 215 enum DPGraphicFmt { 216 DP_GRAPHIC_RGBA8888 = 0 << 8, 217 DP_GRAPHIC_ABGR8888 = 1 << 8, 218 DP_GRAPHIC_RGB888 = 2 << 8, 219 DP_GRAPHIC_BGR888 = 3 << 8, 220 DP_GRAPHIC_RGBA5551 = 4 << 8, 221 DP_GRAPHIC_RGBA4444 = 5 << 8, 222 DP_GRAPHIC_RGB565 = 6 << 8, 223 DP_GRAPHIC_8BPP = 7 << 8, 224 DP_GRAPHIC_4BPP = 8 << 8, 225 DP_GRAPHIC_2BPP = 9 << 8, 226 DP_GRAPHIC_1BPP = 10 << 8, 227 DP_GRAPHIC_MASK = 0xF << 8 228 }; 229 230 enum DPVideoFmt { 231 DP_NL_VID_CB_Y0_CR_Y1 = 0, 232 DP_NL_VID_CR_Y0_CB_Y1 = 1, 233 DP_NL_VID_Y0_CR_Y1_CB = 2, 234 DP_NL_VID_Y0_CB_Y1_CR = 3, 235 DP_NL_VID_YV16 = 4, 236 DP_NL_VID_YV24 = 5, 237 DP_NL_VID_YV16CL = 6, 238 DP_NL_VID_MONO = 7, 239 DP_NL_VID_YV16CL2 = 8, 240 DP_NL_VID_YUV444 = 9, 241 DP_NL_VID_RGB888 = 10, 242 DP_NL_VID_RGBA8880 = 11, 243 DP_NL_VID_RGB888_10BPC = 12, 244 DP_NL_VID_YUV444_10BPC = 13, 245 DP_NL_VID_YV16CL2_10BPC = 14, 246 DP_NL_VID_YV16CL_10BPC = 15, 247 DP_NL_VID_YV16_10BPC = 16, 248 DP_NL_VID_YV24_10BPC = 17, 249 DP_NL_VID_Y_ONLY_10BPC = 18, 250 DP_NL_VID_YV16_420 = 19, 251 DP_NL_VID_YV16CL_420 = 20, 252 DP_NL_VID_YV16CL2_420 = 21, 253 DP_NL_VID_YV16_420_10BPC = 22, 254 DP_NL_VID_YV16CL_420_10BPC = 23, 255 DP_NL_VID_YV16CL2_420_10BPC = 24, 256 DP_NL_VID_FMT_MASK = 0x1F 257 }; 258 259 typedef enum DPGraphicFmt DPGraphicFmt; 260 typedef enum DPVideoFmt DPVideoFmt; 261 262 static const VMStateDescription vmstate_dp = { 263 .name = TYPE_XLNX_DP, 264 .version_id = 2, 265 .fields = (const VMStateField[]){ 266 VMSTATE_UINT32_ARRAY(core_registers, XlnxDPState, 267 DP_CORE_REG_ARRAY_SIZE), 268 VMSTATE_UINT32_ARRAY(avbufm_registers, XlnxDPState, 269 DP_AVBUF_REG_ARRAY_SIZE), 270 VMSTATE_UINT32_ARRAY(vblend_registers, XlnxDPState, 271 DP_VBLEND_REG_ARRAY_SIZE), 272 VMSTATE_UINT32_ARRAY(audio_registers, XlnxDPState, 273 DP_AUDIO_REG_ARRAY_SIZE), 274 VMSTATE_PTIMER(vblank, XlnxDPState), 275 VMSTATE_END_OF_LIST() 276 } 277 }; 278 279 #define DP_VBLANK_PTIMER_POLICY (PTIMER_POLICY_WRAP_AFTER_ONE_PERIOD | \ 280 PTIMER_POLICY_CONTINUOUS_TRIGGER | \ 281 PTIMER_POLICY_NO_IMMEDIATE_TRIGGER) 282 283 static void xlnx_dp_update_irq(XlnxDPState *s); 284 285 static uint64_t xlnx_dp_audio_read(void *opaque, hwaddr offset, unsigned size) 286 { 287 XlnxDPState *s = XLNX_DP(opaque); 288 289 offset = offset >> 2; 290 return s->audio_registers[offset]; 291 } 292 293 static void xlnx_dp_audio_write(void *opaque, hwaddr offset, uint64_t value, 294 unsigned size) 295 { 296 XlnxDPState *s = XLNX_DP(opaque); 297 298 offset = offset >> 2; 299 300 switch (offset) { 301 case AUDIO_MIXER_META_DATA: 302 s->audio_registers[offset] = value & 0x00000001; 303 break; 304 default: 305 s->audio_registers[offset] = value; 306 break; 307 } 308 } 309 310 static const MemoryRegionOps audio_ops = { 311 .read = xlnx_dp_audio_read, 312 .write = xlnx_dp_audio_write, 313 .endianness = DEVICE_NATIVE_ENDIAN, 314 }; 315 316 static inline uint32_t xlnx_dp_audio_get_volume(XlnxDPState *s, 317 uint8_t channel) 318 { 319 switch (channel) { 320 case 0: 321 return extract32(s->audio_registers[AUDIO_MIXER_VOLUME_CONTROL], 0, 16); 322 case 1: 323 return extract32(s->audio_registers[AUDIO_MIXER_VOLUME_CONTROL], 16, 324 16); 325 default: 326 return 0; 327 } 328 } 329 330 static inline void xlnx_dp_audio_activate(XlnxDPState *s) 331 { 332 bool activated = ((s->core_registers[DP_TX_AUDIO_CONTROL] 333 & DP_TX_AUD_CTRL) != 0); 334 AUD_set_active_out(s->amixer_output_stream, activated); 335 xlnx_dpdma_set_host_data_location(s->dpdma, DP_AUDIO_DMA_CHANNEL(0), 336 &s->audio_buffer_0); 337 xlnx_dpdma_set_host_data_location(s->dpdma, DP_AUDIO_DMA_CHANNEL(1), 338 &s->audio_buffer_1); 339 } 340 341 static inline void xlnx_dp_audio_mix_buffer(XlnxDPState *s) 342 { 343 /* 344 * Audio packets are signed and have this shape: 345 * | 16 | 16 | 16 | 16 | 16 | 16 | 16 | 16 | 346 * | R3 | L3 | R2 | L2 | R1 | L1 | R0 | L0 | 347 * 348 * Output audio is 16bits saturated. 349 */ 350 int i; 351 352 if ((s->audio_data_available[0]) && (xlnx_dp_audio_get_volume(s, 0))) { 353 for (i = 0; i < s->audio_data_available[0] / 2; i++) { 354 s->temp_buffer[i] = (int64_t)(s->audio_buffer_0[i]) 355 * xlnx_dp_audio_get_volume(s, 0) / 8192; 356 } 357 s->byte_left = s->audio_data_available[0]; 358 } else { 359 memset(s->temp_buffer, 0, s->audio_data_available[1] / 2); 360 } 361 362 if ((s->audio_data_available[1]) && (xlnx_dp_audio_get_volume(s, 1))) { 363 if ((s->audio_data_available[0] == 0) 364 || (s->audio_data_available[1] == s->audio_data_available[0])) { 365 for (i = 0; i < s->audio_data_available[1] / 2; i++) { 366 s->temp_buffer[i] += (int64_t)(s->audio_buffer_1[i]) 367 * xlnx_dp_audio_get_volume(s, 1) / 8192; 368 } 369 s->byte_left = s->audio_data_available[1]; 370 } 371 } 372 373 for (i = 0; i < s->byte_left / 2; i++) { 374 s->out_buffer[i] = MAX(-32767, MIN(s->temp_buffer[i], 32767)); 375 } 376 377 s->data_ptr = 0; 378 } 379 380 static void xlnx_dp_audio_callback(void *opaque, int avail) 381 { 382 /* 383 * Get the individual left and right audio streams from the DPDMA, 384 * and fill the output buffer with the combined stereo audio data 385 * adjusted by the volume controls. 386 * QEMU's audio subsystem will call this callback repeatedly; 387 * we return the data from the output buffer until it is emptied, 388 * and then we will read data from the DPDMA again. 389 */ 390 XlnxDPState *s = XLNX_DP(opaque); 391 size_t written = 0; 392 393 if (s->byte_left == 0) { 394 s->audio_data_available[0] = xlnx_dpdma_start_operation(s->dpdma, 4, 395 true); 396 s->audio_data_available[1] = xlnx_dpdma_start_operation(s->dpdma, 5, 397 true); 398 xlnx_dp_audio_mix_buffer(s); 399 } 400 401 /* Send the buffer through the audio. */ 402 if (s->byte_left <= MAX_QEMU_BUFFER_SIZE) { 403 if (s->byte_left != 0) { 404 written = AUD_write(s->amixer_output_stream, 405 &s->out_buffer[s->data_ptr], s->byte_left); 406 } else { 407 int len_to_copy; 408 /* 409 * There is nothing to play.. We don't have any data! Fill the 410 * buffer with zero's and send it. 411 */ 412 written = 0; 413 while (avail) { 414 len_to_copy = MIN(AUD_CHBUF_MAX_DEPTH, avail); 415 memset(s->out_buffer, 0, len_to_copy); 416 avail -= AUD_write(s->amixer_output_stream, s->out_buffer, 417 len_to_copy); 418 } 419 } 420 } else { 421 written = AUD_write(s->amixer_output_stream, 422 &s->out_buffer[s->data_ptr], MAX_QEMU_BUFFER_SIZE); 423 } 424 s->byte_left -= written; 425 s->data_ptr += written; 426 } 427 428 /* 429 * AUX channel related function. 430 */ 431 static void xlnx_dp_aux_clear_rx_fifo(XlnxDPState *s) 432 { 433 fifo8_reset(&s->rx_fifo); 434 } 435 436 static void xlnx_dp_aux_push_rx_fifo(XlnxDPState *s, uint8_t *buf, size_t len) 437 { 438 DPRINTF("Push %u data in rx_fifo\n", (unsigned)len); 439 fifo8_push_all(&s->rx_fifo, buf, len); 440 } 441 442 static uint8_t xlnx_dp_aux_pop_rx_fifo(XlnxDPState *s) 443 { 444 uint8_t ret; 445 446 if (fifo8_is_empty(&s->rx_fifo)) { 447 qemu_log_mask(LOG_GUEST_ERROR, 448 "%s: Reading empty RX_FIFO\n", 449 __func__); 450 /* 451 * The datasheet is not clear about the reset value, it seems 452 * to be unspecified. We choose to return '0'. 453 */ 454 ret = 0; 455 } else { 456 ret = fifo8_pop(&s->rx_fifo); 457 DPRINTF("pop 0x%" PRIX8 " from rx_fifo.\n", ret); 458 } 459 return ret; 460 } 461 462 static void xlnx_dp_aux_clear_tx_fifo(XlnxDPState *s) 463 { 464 fifo8_reset(&s->tx_fifo); 465 } 466 467 static void xlnx_dp_aux_push_tx_fifo(XlnxDPState *s, uint8_t *buf, size_t len) 468 { 469 DPRINTF("Push %u data in tx_fifo\n", (unsigned)len); 470 fifo8_push_all(&s->tx_fifo, buf, len); 471 } 472 473 static uint8_t xlnx_dp_aux_pop_tx_fifo(XlnxDPState *s) 474 { 475 uint8_t ret; 476 477 if (fifo8_is_empty(&s->tx_fifo)) { 478 error_report("%s: TX_FIFO underflow", __func__); 479 abort(); 480 } 481 ret = fifo8_pop(&s->tx_fifo); 482 DPRINTF("pop 0x%2.2X from tx_fifo.\n", ret); 483 return ret; 484 } 485 486 static uint32_t xlnx_dp_aux_get_address(XlnxDPState *s) 487 { 488 return s->core_registers[DP_AUX_ADDRESS]; 489 } 490 491 /* 492 * Get command from the register. 493 */ 494 static void xlnx_dp_aux_set_command(XlnxDPState *s, uint32_t value) 495 { 496 bool address_only = (value & AUX_ADDR_ONLY_MASK) != 0; 497 AUXCommand cmd = (value & AUX_COMMAND_MASK) >> AUX_COMMAND_SHIFT; 498 uint8_t nbytes = (value & AUX_COMMAND_NBYTES) + 1; 499 uint8_t buf[16]; 500 int i; 501 502 /* 503 * When an address_only command is executed nothing happen to the fifo, so 504 * just make nbytes = 0. 505 */ 506 if (address_only) { 507 nbytes = 0; 508 } 509 510 switch (cmd) { 511 case READ_AUX: 512 case READ_I2C: 513 case READ_I2C_MOT: 514 s->core_registers[DP_AUX_REPLY_CODE] = aux_request(s->aux_bus, cmd, 515 xlnx_dp_aux_get_address(s), 516 nbytes, buf); 517 s->core_registers[DP_REPLY_DATA_COUNT] = nbytes; 518 519 if (s->core_registers[DP_AUX_REPLY_CODE] == AUX_I2C_ACK) { 520 xlnx_dp_aux_push_rx_fifo(s, buf, nbytes); 521 } 522 break; 523 case WRITE_AUX: 524 case WRITE_I2C: 525 case WRITE_I2C_MOT: 526 for (i = 0; i < nbytes; i++) { 527 buf[i] = xlnx_dp_aux_pop_tx_fifo(s); 528 } 529 s->core_registers[DP_AUX_REPLY_CODE] = aux_request(s->aux_bus, cmd, 530 xlnx_dp_aux_get_address(s), 531 nbytes, buf); 532 xlnx_dp_aux_clear_tx_fifo(s); 533 break; 534 case WRITE_I2C_STATUS: 535 qemu_log_mask(LOG_UNIMP, "xlnx_dp: Write i2c status not implemented\n"); 536 break; 537 default: 538 qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid command: %u", __func__, cmd); 539 return; 540 } 541 542 s->core_registers[DP_INTERRUPT_SIGNAL_STATE] |= 0x04; 543 } 544 545 static void xlnx_dp_set_dpdma(const Object *obj, const char *name, Object *val, 546 Error **errp) 547 { 548 XlnxDPState *s = XLNX_DP(obj); 549 if (s->console) { 550 DisplaySurface *surface = qemu_console_surface(s->console); 551 XlnxDPDMAState *dma = XLNX_DPDMA(val); 552 xlnx_dpdma_set_host_data_location(dma, DP_GRAPHIC_DMA_CHANNEL, 553 surface_data(surface)); 554 } 555 } 556 557 static inline uint8_t xlnx_dp_global_alpha_value(XlnxDPState *s) 558 { 559 return (s->vblend_registers[V_BLEND_SET_GLOBAL_ALPHA_REG] & 0x1FE) >> 1; 560 } 561 562 static inline bool xlnx_dp_global_alpha_enabled(XlnxDPState *s) 563 { 564 /* 565 * If the alpha is totally opaque (255) we consider the alpha is disabled to 566 * reduce CPU consumption. 567 */ 568 return ((xlnx_dp_global_alpha_value(s) != 0xFF) && 569 ((s->vblend_registers[V_BLEND_SET_GLOBAL_ALPHA_REG] & 0x01) != 0)); 570 } 571 572 static void xlnx_dp_recreate_surface(XlnxDPState *s) 573 { 574 /* 575 * Two possibilities, if blending is enabled the console displays 576 * bout_plane, if not g_plane is displayed. 577 */ 578 uint16_t width = s->core_registers[DP_MAIN_STREAM_HRES]; 579 uint16_t height = s->core_registers[DP_MAIN_STREAM_VRES]; 580 DisplaySurface *current_console_surface = qemu_console_surface(s->console); 581 582 if ((width != 0) && (height != 0)) { 583 /* 584 * As dpy_gfx_replace_surface calls qemu_free_displaysurface on the 585 * surface we need to be careful and don't free the surface associated 586 * to the console or double free will happen. 587 */ 588 if (s->bout_plane.surface != current_console_surface) { 589 qemu_free_displaysurface(s->bout_plane.surface); 590 } 591 if (s->v_plane.surface != current_console_surface) { 592 qemu_free_displaysurface(s->v_plane.surface); 593 } 594 if (s->g_plane.surface != current_console_surface) { 595 qemu_free_displaysurface(s->g_plane.surface); 596 } 597 598 s->g_plane.surface 599 = qemu_create_displaysurface_from(width, height, 600 s->g_plane.format, 0, NULL); 601 s->v_plane.surface 602 = qemu_create_displaysurface_from(width, height, 603 s->v_plane.format, 0, NULL); 604 if (xlnx_dp_global_alpha_enabled(s)) { 605 s->bout_plane.surface = 606 qemu_create_displaysurface_from(width, 607 height, 608 s->g_plane.format, 609 0, NULL); 610 dpy_gfx_replace_surface(s->console, s->bout_plane.surface); 611 } else { 612 s->bout_plane.surface = NULL; 613 dpy_gfx_replace_surface(s->console, s->g_plane.surface); 614 } 615 616 xlnx_dpdma_set_host_data_location(s->dpdma, DP_GRAPHIC_DMA_CHANNEL, 617 surface_data(s->g_plane.surface)); 618 xlnx_dpdma_set_host_data_location(s->dpdma, DP_VIDEO_DMA_CHANNEL, 619 surface_data(s->v_plane.surface)); 620 } 621 } 622 623 /* 624 * Change the graphic format of the surface. 625 */ 626 static void xlnx_dp_change_graphic_fmt(XlnxDPState *s) 627 { 628 switch (s->avbufm_registers[AV_BUF_FORMAT] & DP_GRAPHIC_MASK) { 629 case DP_GRAPHIC_RGBA8888: 630 s->g_plane.format = PIXMAN_r8g8b8a8; 631 break; 632 case DP_GRAPHIC_ABGR8888: 633 s->g_plane.format = PIXMAN_a8b8g8r8; 634 break; 635 case DP_GRAPHIC_RGB565: 636 s->g_plane.format = PIXMAN_r5g6b5; 637 break; 638 case DP_GRAPHIC_RGB888: 639 s->g_plane.format = PIXMAN_r8g8b8; 640 break; 641 case DP_GRAPHIC_BGR888: 642 s->g_plane.format = PIXMAN_b8g8r8; 643 break; 644 default: 645 error_report("%s: unsupported graphic format %u", __func__, 646 s->avbufm_registers[AV_BUF_FORMAT] & DP_GRAPHIC_MASK); 647 abort(); 648 } 649 650 switch (s->avbufm_registers[AV_BUF_FORMAT] & DP_NL_VID_FMT_MASK) { 651 case 0: 652 s->v_plane.format = PIXMAN_x8b8g8r8; 653 break; 654 case DP_NL_VID_Y0_CB_Y1_CR: 655 s->v_plane.format = PIXMAN_yuy2; 656 break; 657 case DP_NL_VID_RGBA8880: 658 s->v_plane.format = PIXMAN_x8b8g8r8; 659 break; 660 default: 661 error_report("%s: unsupported video format %u", __func__, 662 s->avbufm_registers[AV_BUF_FORMAT] & DP_NL_VID_FMT_MASK); 663 abort(); 664 } 665 666 xlnx_dp_recreate_surface(s); 667 } 668 669 static void xlnx_dp_update_irq(XlnxDPState *s) 670 { 671 uint32_t flags; 672 673 flags = s->core_registers[DP_INT_STATUS] & ~s->core_registers[DP_INT_MASK]; 674 DPRINTF("update IRQ value = %" PRIx32 "\n", flags); 675 qemu_set_irq(s->irq, flags != 0); 676 } 677 678 static uint64_t xlnx_dp_read(void *opaque, hwaddr offset, unsigned size) 679 { 680 XlnxDPState *s = XLNX_DP(opaque); 681 uint64_t ret = 0; 682 683 offset = offset >> 2; 684 685 switch (offset) { 686 case DP_TX_USER_FIFO_OVERFLOW: 687 /* This register is cleared after a read */ 688 ret = s->core_registers[DP_TX_USER_FIFO_OVERFLOW]; 689 s->core_registers[DP_TX_USER_FIFO_OVERFLOW] = 0; 690 break; 691 case DP_AUX_REPLY_DATA: 692 ret = xlnx_dp_aux_pop_rx_fifo(s); 693 break; 694 case DP_INTERRUPT_SIGNAL_STATE: 695 /* 696 * XXX: Not sure it is the right thing to do actually. 697 * The register is not written by the device driver so it's stuck 698 * to 0x04. 699 */ 700 ret = s->core_registers[DP_INTERRUPT_SIGNAL_STATE]; 701 s->core_registers[DP_INTERRUPT_SIGNAL_STATE] &= ~0x04; 702 break; 703 case DP_AUX_WRITE_FIFO: 704 case DP_TX_AUDIO_INFO_DATA(0): 705 case DP_TX_AUDIO_INFO_DATA(1): 706 case DP_TX_AUDIO_INFO_DATA(2): 707 case DP_TX_AUDIO_INFO_DATA(3): 708 case DP_TX_AUDIO_INFO_DATA(4): 709 case DP_TX_AUDIO_INFO_DATA(5): 710 case DP_TX_AUDIO_INFO_DATA(6): 711 case DP_TX_AUDIO_INFO_DATA(7): 712 case DP_TX_AUDIO_EXT_DATA(0): 713 case DP_TX_AUDIO_EXT_DATA(1): 714 case DP_TX_AUDIO_EXT_DATA(2): 715 case DP_TX_AUDIO_EXT_DATA(3): 716 case DP_TX_AUDIO_EXT_DATA(4): 717 case DP_TX_AUDIO_EXT_DATA(5): 718 case DP_TX_AUDIO_EXT_DATA(6): 719 case DP_TX_AUDIO_EXT_DATA(7): 720 case DP_TX_AUDIO_EXT_DATA(8): 721 /* write only registers */ 722 ret = 0; 723 break; 724 default: 725 assert(offset <= (0x3AC >> 2)); 726 if (offset == (0x3A8 >> 2) || offset == (0x3AC >> 2)) { 727 ret = s->core_registers[DP_INT_MASK]; 728 } else { 729 ret = s->core_registers[offset]; 730 } 731 break; 732 } 733 734 DPRINTF("core read @%" PRIx64 " = 0x%8.8" PRIX64 "\n", offset << 2, ret); 735 return ret; 736 } 737 738 static void xlnx_dp_write(void *opaque, hwaddr offset, uint64_t value, 739 unsigned size) 740 { 741 XlnxDPState *s = XLNX_DP(opaque); 742 743 DPRINTF("core write @%" PRIx64 " = 0x%8.8" PRIX64 "\n", offset, value); 744 745 offset = offset >> 2; 746 747 switch (offset) { 748 /* 749 * Only special write case are handled. 750 */ 751 case DP_LINK_BW_SET: 752 s->core_registers[offset] = value & 0x000000FF; 753 break; 754 case DP_LANE_COUNT_SET: 755 case DP_MAIN_STREAM_MISC0: 756 s->core_registers[offset] = value & 0x0000000F; 757 break; 758 case DP_TRAINING_PATTERN_SET: 759 case DP_LINK_QUAL_PATTERN_SET: 760 case DP_MAIN_STREAM_POLARITY: 761 case DP_PHY_VOLTAGE_DIFF_LANE_0: 762 case DP_PHY_VOLTAGE_DIFF_LANE_1: 763 s->core_registers[offset] = value & 0x00000003; 764 break; 765 case DP_ENHANCED_FRAME_EN: 766 case DP_SCRAMBLING_DISABLE: 767 case DP_DOWNSPREAD_CTRL: 768 case DP_MAIN_STREAM_ENABLE: 769 case DP_TRANSMIT_PRBS7: 770 s->core_registers[offset] = value & 0x00000001; 771 break; 772 case DP_PHY_CLOCK_SELECT: 773 s->core_registers[offset] = value & 0x00000007; 774 break; 775 case DP_SOFTWARE_RESET: 776 /* 777 * No need to update this bit as it's read '0'. 778 */ 779 /* 780 * TODO: reset IP. 781 */ 782 break; 783 case DP_TRANSMITTER_ENABLE: 784 s->core_registers[offset] = value & 0x01; 785 ptimer_transaction_begin(s->vblank); 786 if (value & 0x1) { 787 ptimer_run(s->vblank, 0); 788 } else { 789 ptimer_stop(s->vblank); 790 } 791 ptimer_transaction_commit(s->vblank); 792 break; 793 case DP_FORCE_SCRAMBLER_RESET: 794 /* 795 * No need to update this bit as it's read '0'. 796 */ 797 /* 798 * TODO: force a scrambler reset?? 799 */ 800 break; 801 case DP_AUX_COMMAND_REGISTER: 802 s->core_registers[offset] = value & 0x00001F0F; 803 xlnx_dp_aux_set_command(s, s->core_registers[offset]); 804 break; 805 case DP_MAIN_STREAM_HTOTAL: 806 case DP_MAIN_STREAM_VTOTAL: 807 case DP_MAIN_STREAM_HSTART: 808 case DP_MAIN_STREAM_VSTART: 809 s->core_registers[offset] = value & 0x0000FFFF; 810 break; 811 case DP_MAIN_STREAM_HRES: 812 case DP_MAIN_STREAM_VRES: 813 s->core_registers[offset] = value & 0x0000FFFF; 814 xlnx_dp_recreate_surface(s); 815 break; 816 case DP_MAIN_STREAM_HSWIDTH: 817 case DP_MAIN_STREAM_VSWIDTH: 818 s->core_registers[offset] = value & 0x00007FFF; 819 break; 820 case DP_MAIN_STREAM_MISC1: 821 s->core_registers[offset] = value & 0x00000086; 822 break; 823 case DP_MAIN_STREAM_M_VID: 824 case DP_MAIN_STREAM_N_VID: 825 s->core_registers[offset] = value & 0x00FFFFFF; 826 break; 827 case DP_MSA_TRANSFER_UNIT_SIZE: 828 case DP_MIN_BYTES_PER_TU: 829 case DP_INIT_WAIT: 830 s->core_registers[offset] = value & 0x00000007; 831 break; 832 case DP_USER_DATA_COUNT_PER_LANE: 833 s->core_registers[offset] = value & 0x0003FFFF; 834 break; 835 case DP_FRAC_BYTES_PER_TU: 836 s->core_registers[offset] = value & 0x000003FF; 837 break; 838 case DP_PHY_RESET: 839 s->core_registers[offset] = value & 0x00010003; 840 /* 841 * TODO: Reset something? 842 */ 843 break; 844 case DP_TX_PHY_POWER_DOWN: 845 s->core_registers[offset] = value & 0x0000000F; 846 /* 847 * TODO: Power down things? 848 */ 849 break; 850 case DP_AUX_WRITE_FIFO: { 851 uint8_t c = value; 852 xlnx_dp_aux_push_tx_fifo(s, &c, 1); 853 break; 854 } 855 case DP_AUX_CLOCK_DIVIDER: 856 break; 857 case DP_AUX_REPLY_COUNT: 858 /* 859 * Writing to this register clear the counter. 860 */ 861 s->core_registers[offset] = 0x00000000; 862 break; 863 case DP_AUX_ADDRESS: 864 s->core_registers[offset] = value & 0x000FFFFF; 865 break; 866 case DP_VERSION_REGISTER: 867 case DP_CORE_ID: 868 case DP_TX_USER_FIFO_OVERFLOW: 869 case DP_AUX_REPLY_DATA: 870 case DP_AUX_REPLY_CODE: 871 case DP_REPLY_DATA_COUNT: 872 case DP_REPLY_STATUS: 873 case DP_HPD_DURATION: 874 /* 875 * Write to read only location.. 876 */ 877 break; 878 case DP_TX_AUDIO_CONTROL: 879 s->core_registers[offset] = value & 0x00000001; 880 xlnx_dp_audio_activate(s); 881 break; 882 case DP_TX_AUDIO_CHANNELS: 883 s->core_registers[offset] = value & 0x00000007; 884 xlnx_dp_audio_activate(s); 885 break; 886 case DP_INT_STATUS: 887 s->core_registers[DP_INT_STATUS] &= ~value; 888 xlnx_dp_update_irq(s); 889 break; 890 case DP_INT_EN: 891 s->core_registers[DP_INT_MASK] &= ~value; 892 xlnx_dp_update_irq(s); 893 break; 894 case DP_INT_DS: 895 s->core_registers[DP_INT_MASK] |= value; 896 xlnx_dp_update_irq(s); 897 break; 898 default: 899 assert(offset <= (0x504C >> 2)); 900 s->core_registers[offset] = value; 901 break; 902 } 903 } 904 905 static const MemoryRegionOps dp_ops = { 906 .read = xlnx_dp_read, 907 .write = xlnx_dp_write, 908 .endianness = DEVICE_NATIVE_ENDIAN, 909 .valid = { 910 .min_access_size = 4, 911 .max_access_size = 4, 912 }, 913 .impl = { 914 .min_access_size = 4, 915 .max_access_size = 4, 916 }, 917 }; 918 919 /* 920 * This is to handle Read/Write to the Video Blender. 921 */ 922 static void xlnx_dp_vblend_write(void *opaque, hwaddr offset, 923 uint64_t value, unsigned size) 924 { 925 XlnxDPState *s = XLNX_DP(opaque); 926 bool alpha_was_enabled; 927 928 DPRINTF("vblend: write @0x%" HWADDR_PRIX " = 0x%" PRIX32 "\n", offset, 929 (uint32_t)value); 930 offset = offset >> 2; 931 932 switch (offset) { 933 case V_BLEND_BG_CLR_0: 934 case V_BLEND_BG_CLR_1: 935 case V_BLEND_BG_CLR_2: 936 s->vblend_registers[offset] = value & 0x00000FFF; 937 break; 938 case V_BLEND_SET_GLOBAL_ALPHA_REG: 939 /* 940 * A write to this register can enable or disable blending. Thus we need 941 * to recreate the surfaces. 942 */ 943 alpha_was_enabled = xlnx_dp_global_alpha_enabled(s); 944 s->vblend_registers[offset] = value & 0x000001FF; 945 if (xlnx_dp_global_alpha_enabled(s) != alpha_was_enabled) { 946 xlnx_dp_recreate_surface(s); 947 } 948 break; 949 case V_BLEND_OUTPUT_VID_FORMAT: 950 s->vblend_registers[offset] = value & 0x00000017; 951 break; 952 case V_BLEND_LAYER0_CONTROL: 953 case V_BLEND_LAYER1_CONTROL: 954 s->vblend_registers[offset] = value & 0x00000103; 955 break; 956 case V_BLEND_RGB2YCBCR_COEFF(0): 957 case V_BLEND_RGB2YCBCR_COEFF(1): 958 case V_BLEND_RGB2YCBCR_COEFF(2): 959 case V_BLEND_RGB2YCBCR_COEFF(3): 960 case V_BLEND_RGB2YCBCR_COEFF(4): 961 case V_BLEND_RGB2YCBCR_COEFF(5): 962 case V_BLEND_RGB2YCBCR_COEFF(6): 963 case V_BLEND_RGB2YCBCR_COEFF(7): 964 case V_BLEND_RGB2YCBCR_COEFF(8): 965 case V_BLEND_IN1CSC_COEFF(0): 966 case V_BLEND_IN1CSC_COEFF(1): 967 case V_BLEND_IN1CSC_COEFF(2): 968 case V_BLEND_IN1CSC_COEFF(3): 969 case V_BLEND_IN1CSC_COEFF(4): 970 case V_BLEND_IN1CSC_COEFF(5): 971 case V_BLEND_IN1CSC_COEFF(6): 972 case V_BLEND_IN1CSC_COEFF(7): 973 case V_BLEND_IN1CSC_COEFF(8): 974 case V_BLEND_IN2CSC_COEFF(0): 975 case V_BLEND_IN2CSC_COEFF(1): 976 case V_BLEND_IN2CSC_COEFF(2): 977 case V_BLEND_IN2CSC_COEFF(3): 978 case V_BLEND_IN2CSC_COEFF(4): 979 case V_BLEND_IN2CSC_COEFF(5): 980 case V_BLEND_IN2CSC_COEFF(6): 981 case V_BLEND_IN2CSC_COEFF(7): 982 case V_BLEND_IN2CSC_COEFF(8): 983 s->vblend_registers[offset] = value & 0x0000FFFF; 984 break; 985 case V_BLEND_LUMA_IN1CSC_OFFSET: 986 case V_BLEND_CR_IN1CSC_OFFSET: 987 case V_BLEND_CB_IN1CSC_OFFSET: 988 case V_BLEND_LUMA_IN2CSC_OFFSET: 989 case V_BLEND_CR_IN2CSC_OFFSET: 990 case V_BLEND_CB_IN2CSC_OFFSET: 991 case V_BLEND_LUMA_OUTCSC_OFFSET: 992 case V_BLEND_CR_OUTCSC_OFFSET: 993 case V_BLEND_CB_OUTCSC_OFFSET: 994 s->vblend_registers[offset] = value & 0x3FFF7FFF; 995 break; 996 case V_BLEND_CHROMA_KEY_ENABLE: 997 s->vblend_registers[offset] = value & 0x00000003; 998 break; 999 case V_BLEND_CHROMA_KEY_COMP1: 1000 case V_BLEND_CHROMA_KEY_COMP2: 1001 case V_BLEND_CHROMA_KEY_COMP3: 1002 s->vblend_registers[offset] = value & 0x0FFF0FFF; 1003 break; 1004 default: 1005 s->vblend_registers[offset] = value; 1006 break; 1007 } 1008 } 1009 1010 static uint64_t xlnx_dp_vblend_read(void *opaque, hwaddr offset, 1011 unsigned size) 1012 { 1013 XlnxDPState *s = XLNX_DP(opaque); 1014 1015 DPRINTF("vblend: read @0x%" HWADDR_PRIX " = 0x%" PRIX32 "\n", offset, 1016 s->vblend_registers[offset >> 2]); 1017 return s->vblend_registers[offset >> 2]; 1018 } 1019 1020 static const MemoryRegionOps vblend_ops = { 1021 .read = xlnx_dp_vblend_read, 1022 .write = xlnx_dp_vblend_write, 1023 .endianness = DEVICE_NATIVE_ENDIAN, 1024 .valid = { 1025 .min_access_size = 4, 1026 .max_access_size = 4, 1027 }, 1028 .impl = { 1029 .min_access_size = 4, 1030 .max_access_size = 4, 1031 }, 1032 }; 1033 1034 /* 1035 * This is to handle Read/Write to the Audio Video buffer manager. 1036 */ 1037 static void xlnx_dp_avbufm_write(void *opaque, hwaddr offset, uint64_t value, 1038 unsigned size) 1039 { 1040 XlnxDPState *s = XLNX_DP(opaque); 1041 1042 DPRINTF("avbufm: write @0x%" HWADDR_PRIX " = 0x%" PRIX32 "\n", offset, 1043 (uint32_t)value); 1044 offset = offset >> 2; 1045 1046 switch (offset) { 1047 case AV_BUF_FORMAT: 1048 s->avbufm_registers[offset] = value & 0x00000FFF; 1049 xlnx_dp_change_graphic_fmt(s); 1050 break; 1051 case AV_CHBUF0: 1052 case AV_CHBUF1: 1053 case AV_CHBUF2: 1054 case AV_CHBUF3: 1055 case AV_CHBUF4: 1056 case AV_CHBUF5: 1057 s->avbufm_registers[offset] = value & 0x0000007F; 1058 break; 1059 case AV_BUF_OUTPUT_AUDIO_VIDEO_SELECT: 1060 s->avbufm_registers[offset] = value & 0x0000007F; 1061 break; 1062 case AV_BUF_DITHER_CONFIG: 1063 s->avbufm_registers[offset] = value & 0x000007FF; 1064 break; 1065 case AV_BUF_DITHER_CONFIG_MAX: 1066 case AV_BUF_DITHER_CONFIG_MIN: 1067 s->avbufm_registers[offset] = value & 0x00000FFF; 1068 break; 1069 case AV_BUF_PATTERN_GEN_SELECT: 1070 s->avbufm_registers[offset] = value & 0xFFFFFF03; 1071 break; 1072 case AV_BUF_AUD_VID_CLK_SOURCE: 1073 s->avbufm_registers[offset] = value & 0x00000007; 1074 break; 1075 case AV_BUF_SRST_REG: 1076 s->avbufm_registers[offset] = value & 0x00000002; 1077 break; 1078 case AV_BUF_AUDIO_CH_CONFIG: 1079 s->avbufm_registers[offset] = value & 0x00000003; 1080 break; 1081 case AV_BUF_GRAPHICS_COMP_SCALE_FACTOR(0): 1082 case AV_BUF_GRAPHICS_COMP_SCALE_FACTOR(1): 1083 case AV_BUF_GRAPHICS_COMP_SCALE_FACTOR(2): 1084 case AV_BUF_VIDEO_COMP_SCALE_FACTOR(0): 1085 case AV_BUF_VIDEO_COMP_SCALE_FACTOR(1): 1086 case AV_BUF_VIDEO_COMP_SCALE_FACTOR(2): 1087 s->avbufm_registers[offset] = value & 0x0000FFFF; 1088 break; 1089 case AV_BUF_LIVE_VIDEO_COMP_SF(0): 1090 case AV_BUF_LIVE_VIDEO_COMP_SF(1): 1091 case AV_BUF_LIVE_VIDEO_COMP_SF(2): 1092 case AV_BUF_LIVE_VID_CONFIG: 1093 case AV_BUF_LIVE_GFX_COMP_SF(0): 1094 case AV_BUF_LIVE_GFX_COMP_SF(1): 1095 case AV_BUF_LIVE_GFX_COMP_SF(2): 1096 case AV_BUF_LIVE_GFX_CONFIG: 1097 case AV_BUF_NON_LIVE_LATENCY: 1098 case AV_BUF_STC_CONTROL: 1099 case AV_BUF_STC_INIT_VALUE0: 1100 case AV_BUF_STC_INIT_VALUE1: 1101 case AV_BUF_STC_ADJ: 1102 case AV_BUF_STC_VIDEO_VSYNC_TS_REG0: 1103 case AV_BUF_STC_VIDEO_VSYNC_TS_REG1: 1104 case AV_BUF_STC_EXT_VSYNC_TS_REG0: 1105 case AV_BUF_STC_EXT_VSYNC_TS_REG1: 1106 case AV_BUF_STC_CUSTOM_EVENT_TS_REG0: 1107 case AV_BUF_STC_CUSTOM_EVENT_TS_REG1: 1108 case AV_BUF_STC_CUSTOM_EVENT2_TS_REG0: 1109 case AV_BUF_STC_CUSTOM_EVENT2_TS_REG1: 1110 case AV_BUF_STC_SNAPSHOT0: 1111 case AV_BUF_STC_SNAPSHOT1: 1112 case AV_BUF_HCOUNT_VCOUNT_INT0: 1113 case AV_BUF_HCOUNT_VCOUNT_INT1: 1114 qemu_log_mask(LOG_UNIMP, "avbufm: unimplemented register 0x%04" 1115 PRIx64 "\n", 1116 offset << 2); 1117 break; 1118 default: 1119 s->avbufm_registers[offset] = value; 1120 break; 1121 } 1122 } 1123 1124 static uint64_t xlnx_dp_avbufm_read(void *opaque, hwaddr offset, 1125 unsigned size) 1126 { 1127 XlnxDPState *s = XLNX_DP(opaque); 1128 1129 offset = offset >> 2; 1130 return s->avbufm_registers[offset]; 1131 } 1132 1133 static const MemoryRegionOps avbufm_ops = { 1134 .read = xlnx_dp_avbufm_read, 1135 .write = xlnx_dp_avbufm_write, 1136 .endianness = DEVICE_NATIVE_ENDIAN, 1137 .valid = { 1138 .min_access_size = 4, 1139 .max_access_size = 4, 1140 }, 1141 .impl = { 1142 .min_access_size = 4, 1143 .max_access_size = 4, 1144 }, 1145 }; 1146 1147 /* 1148 * This is a global alpha blending using pixman. 1149 * Both graphic and video planes are multiplied with the global alpha 1150 * coefficient and added. 1151 */ 1152 static inline void xlnx_dp_blend_surface(XlnxDPState *s) 1153 { 1154 pixman_fixed_t alpha1[] = { pixman_double_to_fixed(1), 1155 pixman_double_to_fixed(1), 1156 pixman_double_to_fixed(1.0) }; 1157 pixman_fixed_t alpha2[] = { pixman_double_to_fixed(1), 1158 pixman_double_to_fixed(1), 1159 pixman_double_to_fixed(1.0) }; 1160 1161 if ((surface_width(s->g_plane.surface) 1162 != surface_width(s->v_plane.surface)) || 1163 (surface_height(s->g_plane.surface) 1164 != surface_height(s->v_plane.surface))) { 1165 return; 1166 } 1167 1168 alpha1[2] = pixman_double_to_fixed((double)(xlnx_dp_global_alpha_value(s)) 1169 / 256.0); 1170 alpha2[2] = pixman_double_to_fixed((255.0 1171 - (double)xlnx_dp_global_alpha_value(s)) 1172 / 256.0); 1173 1174 pixman_image_set_filter(s->g_plane.surface->image, 1175 PIXMAN_FILTER_CONVOLUTION, alpha1, 3); 1176 pixman_image_composite(PIXMAN_OP_SRC, s->g_plane.surface->image, 0, 1177 s->bout_plane.surface->image, 0, 0, 0, 0, 0, 0, 1178 surface_width(s->g_plane.surface), 1179 surface_height(s->g_plane.surface)); 1180 pixman_image_set_filter(s->v_plane.surface->image, 1181 PIXMAN_FILTER_CONVOLUTION, alpha2, 3); 1182 pixman_image_composite(PIXMAN_OP_ADD, s->v_plane.surface->image, 0, 1183 s->bout_plane.surface->image, 0, 0, 0, 0, 0, 0, 1184 surface_width(s->g_plane.surface), 1185 surface_height(s->g_plane.surface)); 1186 } 1187 1188 static void xlnx_dp_update_display(void *opaque) 1189 { 1190 XlnxDPState *s = XLNX_DP(opaque); 1191 1192 if ((s->core_registers[DP_TRANSMITTER_ENABLE] & 0x01) == 0) { 1193 return; 1194 } 1195 1196 xlnx_dpdma_trigger_vsync_irq(s->dpdma); 1197 1198 /* 1199 * Trigger the DMA channel. 1200 */ 1201 if (!xlnx_dpdma_start_operation(s->dpdma, 3, false)) { 1202 /* 1203 * An error occurred don't do anything with the data.. 1204 * Trigger an underflow interrupt. 1205 */ 1206 s->core_registers[DP_INT_STATUS] |= (1 << 21); 1207 xlnx_dp_update_irq(s); 1208 return; 1209 } 1210 1211 if (xlnx_dp_global_alpha_enabled(s)) { 1212 if (!xlnx_dpdma_start_operation(s->dpdma, 0, false)) { 1213 s->core_registers[DP_INT_STATUS] |= (1 << 21); 1214 xlnx_dp_update_irq(s); 1215 return; 1216 } 1217 xlnx_dp_blend_surface(s); 1218 } 1219 1220 /* 1221 * XXX: We might want to update only what changed. 1222 */ 1223 dpy_gfx_update_full(s->console); 1224 } 1225 1226 static const GraphicHwOps xlnx_dp_gfx_ops = { 1227 .gfx_update = xlnx_dp_update_display, 1228 }; 1229 1230 static void xlnx_dp_init(Object *obj) 1231 { 1232 SysBusDevice *sbd = SYS_BUS_DEVICE(obj); 1233 XlnxDPState *s = XLNX_DP(obj); 1234 1235 memory_region_init(&s->container, obj, TYPE_XLNX_DP, DP_CONTAINER_SIZE); 1236 1237 memory_region_init_io(&s->core_iomem, obj, &dp_ops, s, TYPE_XLNX_DP 1238 ".core", sizeof(s->core_registers)); 1239 memory_region_add_subregion(&s->container, DP_CORE_REG_OFFSET, 1240 &s->core_iomem); 1241 1242 memory_region_init_io(&s->vblend_iomem, obj, &vblend_ops, s, TYPE_XLNX_DP 1243 ".v_blend", sizeof(s->vblend_registers)); 1244 memory_region_add_subregion(&s->container, DP_VBLEND_REG_OFFSET, 1245 &s->vblend_iomem); 1246 1247 memory_region_init_io(&s->avbufm_iomem, obj, &avbufm_ops, s, TYPE_XLNX_DP 1248 ".av_buffer_manager", sizeof(s->avbufm_registers)); 1249 memory_region_add_subregion(&s->container, DP_AVBUF_REG_OFFSET, 1250 &s->avbufm_iomem); 1251 1252 memory_region_init_io(&s->audio_iomem, obj, &audio_ops, s, TYPE_XLNX_DP 1253 ".audio", sizeof(s->audio_registers)); 1254 memory_region_add_subregion(&s->container, 0xC000, &s->audio_iomem); 1255 1256 sysbus_init_mmio(sbd, &s->container); 1257 sysbus_init_irq(sbd, &s->irq); 1258 1259 object_property_add_link(obj, "dpdma", TYPE_XLNX_DPDMA, 1260 (Object **) &s->dpdma, 1261 xlnx_dp_set_dpdma, 1262 OBJ_PROP_LINK_STRONG); 1263 1264 /* 1265 * Initialize AUX Bus. 1266 */ 1267 s->aux_bus = aux_bus_init(DEVICE(obj), "aux"); 1268 1269 /* 1270 * Initialize DPCD and EDID.. 1271 */ 1272 s->dpcd = DPCD(qdev_new("dpcd")); 1273 object_property_add_child(OBJECT(s), "dpcd", OBJECT(s->dpcd)); 1274 1275 s->edid = I2CDDC(qdev_new("i2c-ddc")); 1276 i2c_slave_set_address(I2C_SLAVE(s->edid), 0x50); 1277 object_property_add_child(OBJECT(s), "edid", OBJECT(s->edid)); 1278 1279 fifo8_create(&s->rx_fifo, 16); 1280 fifo8_create(&s->tx_fifo, 16); 1281 } 1282 1283 static void xlnx_dp_finalize(Object *obj) 1284 { 1285 XlnxDPState *s = XLNX_DP(obj); 1286 1287 fifo8_destroy(&s->tx_fifo); 1288 fifo8_destroy(&s->rx_fifo); 1289 } 1290 1291 static void vblank_hit(void *opaque) 1292 { 1293 XlnxDPState *s = XLNX_DP(opaque); 1294 1295 s->core_registers[DP_INT_STATUS] |= DP_INT_VBLNK_START; 1296 xlnx_dp_update_irq(s); 1297 } 1298 1299 static void xlnx_dp_realize(DeviceState *dev, Error **errp) 1300 { 1301 XlnxDPState *s = XLNX_DP(dev); 1302 DisplaySurface *surface; 1303 struct audsettings as; 1304 1305 if (!AUD_register_card("xlnx_dp.audio", &s->aud_card, errp)) { 1306 return; 1307 } 1308 1309 aux_bus_realize(s->aux_bus); 1310 1311 qdev_realize(DEVICE(s->dpcd), BUS(s->aux_bus), &error_fatal); 1312 aux_map_slave(AUX_SLAVE(s->dpcd), 0x0000); 1313 1314 qdev_realize_and_unref(DEVICE(s->edid), BUS(aux_get_i2c_bus(s->aux_bus)), 1315 &error_fatal); 1316 1317 s->console = graphic_console_init(dev, 0, &xlnx_dp_gfx_ops, s); 1318 surface = qemu_console_surface(s->console); 1319 xlnx_dpdma_set_host_data_location(s->dpdma, DP_GRAPHIC_DMA_CHANNEL, 1320 surface_data(surface)); 1321 1322 as.freq = 44100; 1323 as.nchannels = 2; 1324 as.fmt = AUDIO_FORMAT_S16; 1325 as.endianness = 0; 1326 1327 s->amixer_output_stream = AUD_open_out(&s->aud_card, 1328 s->amixer_output_stream, 1329 "xlnx_dp.audio.out", 1330 s, 1331 xlnx_dp_audio_callback, 1332 &as); 1333 AUD_set_volume_out(s->amixer_output_stream, 0, 255, 255); 1334 xlnx_dp_audio_activate(s); 1335 s->vblank = ptimer_init(vblank_hit, s, DP_VBLANK_PTIMER_POLICY); 1336 ptimer_transaction_begin(s->vblank); 1337 ptimer_set_freq(s->vblank, 30); 1338 ptimer_transaction_commit(s->vblank); 1339 } 1340 1341 static void xlnx_dp_reset(DeviceState *dev) 1342 { 1343 XlnxDPState *s = XLNX_DP(dev); 1344 1345 memset(s->core_registers, 0, sizeof(s->core_registers)); 1346 s->core_registers[DP_VERSION_REGISTER] = 0x04010000; 1347 s->core_registers[DP_CORE_ID] = 0x01020000; 1348 s->core_registers[DP_REPLY_STATUS] = 0x00000010; 1349 s->core_registers[DP_MSA_TRANSFER_UNIT_SIZE] = 0x00000040; 1350 s->core_registers[DP_INIT_WAIT] = 0x00000020; 1351 s->core_registers[DP_PHY_RESET] = 0x00010003; 1352 s->core_registers[DP_INT_MASK] = 0xFFFFF03F; 1353 s->core_registers[DP_PHY_STATUS] = 0x00000043; 1354 s->core_registers[DP_INTERRUPT_SIGNAL_STATE] = 0x00000001; 1355 1356 s->vblend_registers[V_BLEND_RGB2YCBCR_COEFF(0)] = 0x00001000; 1357 s->vblend_registers[V_BLEND_RGB2YCBCR_COEFF(4)] = 0x00001000; 1358 s->vblend_registers[V_BLEND_RGB2YCBCR_COEFF(8)] = 0x00001000; 1359 s->vblend_registers[V_BLEND_IN1CSC_COEFF(0)] = 0x00001000; 1360 s->vblend_registers[V_BLEND_IN1CSC_COEFF(4)] = 0x00001000; 1361 s->vblend_registers[V_BLEND_IN1CSC_COEFF(8)] = 0x00001000; 1362 s->vblend_registers[V_BLEND_IN2CSC_COEFF(0)] = 0x00001000; 1363 s->vblend_registers[V_BLEND_IN2CSC_COEFF(4)] = 0x00001000; 1364 s->vblend_registers[V_BLEND_IN2CSC_COEFF(8)] = 0x00001000; 1365 1366 s->avbufm_registers[AV_BUF_NON_LIVE_LATENCY] = 0x00000180; 1367 s->avbufm_registers[AV_BUF_OUTPUT_AUDIO_VIDEO_SELECT] = 0x00000008; 1368 s->avbufm_registers[AV_BUF_DITHER_CONFIG_MAX] = 0x00000FFF; 1369 s->avbufm_registers[AV_BUF_GRAPHICS_COMP_SCALE_FACTOR(0)] = 0x00010101; 1370 s->avbufm_registers[AV_BUF_GRAPHICS_COMP_SCALE_FACTOR(1)] = 0x00010101; 1371 s->avbufm_registers[AV_BUF_GRAPHICS_COMP_SCALE_FACTOR(2)] = 0x00010101; 1372 s->avbufm_registers[AV_BUF_VIDEO_COMP_SCALE_FACTOR(0)] = 0x00010101; 1373 s->avbufm_registers[AV_BUF_VIDEO_COMP_SCALE_FACTOR(1)] = 0x00010101; 1374 s->avbufm_registers[AV_BUF_VIDEO_COMP_SCALE_FACTOR(2)] = 0x00010101; 1375 s->avbufm_registers[AV_BUF_LIVE_VIDEO_COMP_SF(0)] = 0x00010101; 1376 s->avbufm_registers[AV_BUF_LIVE_VIDEO_COMP_SF(1)] = 0x00010101; 1377 s->avbufm_registers[AV_BUF_LIVE_VIDEO_COMP_SF(2)] = 0x00010101; 1378 s->avbufm_registers[AV_BUF_LIVE_GFX_COMP_SF(0)] = 0x00010101; 1379 s->avbufm_registers[AV_BUF_LIVE_GFX_COMP_SF(1)] = 0x00010101; 1380 s->avbufm_registers[AV_BUF_LIVE_GFX_COMP_SF(2)] = 0x00010101; 1381 1382 memset(s->audio_registers, 0, sizeof(s->audio_registers)); 1383 s->byte_left = 0; 1384 1385 xlnx_dp_aux_clear_rx_fifo(s); 1386 xlnx_dp_change_graphic_fmt(s); 1387 xlnx_dp_update_irq(s); 1388 } 1389 1390 static Property xlnx_dp_device_properties[] = { 1391 DEFINE_AUDIO_PROPERTIES(XlnxDPState, aud_card), 1392 DEFINE_PROP_END_OF_LIST(), 1393 }; 1394 1395 static void xlnx_dp_class_init(ObjectClass *oc, void *data) 1396 { 1397 DeviceClass *dc = DEVICE_CLASS(oc); 1398 1399 dc->realize = xlnx_dp_realize; 1400 dc->vmsd = &vmstate_dp; 1401 device_class_set_legacy_reset(dc, xlnx_dp_reset); 1402 device_class_set_props(dc, xlnx_dp_device_properties); 1403 } 1404 1405 static const TypeInfo xlnx_dp_info = { 1406 .name = TYPE_XLNX_DP, 1407 .parent = TYPE_SYS_BUS_DEVICE, 1408 .instance_size = sizeof(XlnxDPState), 1409 .instance_init = xlnx_dp_init, 1410 .instance_finalize = xlnx_dp_finalize, 1411 .class_init = xlnx_dp_class_init, 1412 }; 1413 1414 static void xlnx_dp_register_types(void) 1415 { 1416 type_register_static(&xlnx_dp_info); 1417 } 1418 1419 type_init(xlnx_dp_register_types) 1420