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