master
c 1,497 lines 51.2 KB
Raw
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/core/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 audio_be_set_active_out(s->audio_be, 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 = audio_be_write(s->audio_be, 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 -= audio_be_write(s->audio_be, s->amixer_output_stream,
417 s->out_buffer, len_to_copy);
418 }
419 }
420 } else {
421 written = audio_be_write(s->audio_be, 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 size_t avail = fifo8_num_free(&s->rx_fifo);
439 DPRINTF("Push %u data in rx_fifo\n", (unsigned)len);
440 if (len > avail) {
441 /*
442 * Data sheet doesn't specify behaviour here: we choose to ignore
443 * the excess data.
444 */
445 qemu_log_mask(LOG_GUEST_ERROR,
446 "%s: ignoring %zu bytes pushed to full RX_FIFO\n",
447 __func__, len - avail);
448 len = avail;
449 }
450 fifo8_push_all(&s->rx_fifo, buf, len);
451 }
452
453 static uint8_t xlnx_dp_aux_pop_rx_fifo(XlnxDPState *s)
454 {
455 uint8_t ret;
456
457 if (fifo8_is_empty(&s->rx_fifo)) {
458 qemu_log_mask(LOG_GUEST_ERROR,
459 "%s: Reading empty RX_FIFO\n",
460 __func__);
461 /*
462 * The datasheet is not clear about the reset value, it seems
463 * to be unspecified. We choose to return '0'.
464 */
465 ret = 0;
466 } else {
467 ret = fifo8_pop(&s->rx_fifo);
468 DPRINTF("pop 0x%" PRIX8 " from rx_fifo.\n", ret);
469 }
470 return ret;
471 }
472
473 static void xlnx_dp_aux_clear_tx_fifo(XlnxDPState *s)
474 {
475 fifo8_reset(&s->tx_fifo);
476 }
477
478 static void xlnx_dp_aux_push_tx_fifo(XlnxDPState *s, uint8_t *buf, size_t len)
479 {
480 size_t avail = fifo8_num_free(&s->tx_fifo);
481 DPRINTF("Push %u data in tx_fifo\n", (unsigned)len);
482 if (len > avail) {
483 /*
484 * Data sheet doesn't specify behaviour here: we choose to ignore
485 * the excess data.
486 */
487 qemu_log_mask(LOG_GUEST_ERROR,
488 "%s: ignoring %zu bytes pushed to full TX_FIFO\n",
489 __func__, len - avail);
490 len = avail;
491 }
492 fifo8_push_all(&s->tx_fifo, buf, len);
493 }
494
495 static uint8_t xlnx_dp_aux_pop_tx_fifo(XlnxDPState *s)
496 {
497 uint8_t ret;
498
499 if (fifo8_is_empty(&s->tx_fifo)) {
500 /* Data sheet doesn't specify behaviour here: we choose to return 0 */
501 qemu_log_mask(LOG_GUEST_ERROR, "%s: attempt to read empty TX_FIFO\n",
502 __func__);
503 return 0;
504 }
505 ret = fifo8_pop(&s->tx_fifo);
506 DPRINTF("pop 0x%2.2X from tx_fifo.\n", ret);
507 return ret;
508 }
509
510 static uint32_t xlnx_dp_aux_get_address(XlnxDPState *s)
511 {
512 return s->core_registers[DP_AUX_ADDRESS];
513 }
514
515 /*
516 * Get command from the register.
517 */
518 static void xlnx_dp_aux_set_command(XlnxDPState *s, uint32_t value)
519 {
520 bool address_only = (value & AUX_ADDR_ONLY_MASK) != 0;
521 AUXCommand cmd = (value & AUX_COMMAND_MASK) >> AUX_COMMAND_SHIFT;
522 uint8_t nbytes = (value & AUX_COMMAND_NBYTES) + 1;
523 uint8_t buf[16];
524 int i;
525
526 /*
527 * When an address_only command is executed nothing happen to the fifo, so
528 * just make nbytes = 0.
529 */
530 if (address_only) {
531 nbytes = 0;
532 }
533
534 switch (cmd) {
535 case READ_AUX:
536 case READ_I2C:
537 case READ_I2C_MOT:
538 s->core_registers[DP_AUX_REPLY_CODE] = aux_request(s->aux_bus, cmd,
539 xlnx_dp_aux_get_address(s),
540 nbytes, buf);
541 s->core_registers[DP_REPLY_DATA_COUNT] = nbytes;
542
543 if (s->core_registers[DP_AUX_REPLY_CODE] == AUX_I2C_ACK) {
544 xlnx_dp_aux_push_rx_fifo(s, buf, nbytes);
545 }
546 break;
547 case WRITE_AUX:
548 case WRITE_I2C:
549 case WRITE_I2C_MOT:
550 for (i = 0; i < nbytes; i++) {
551 buf[i] = xlnx_dp_aux_pop_tx_fifo(s);
552 }
553 s->core_registers[DP_AUX_REPLY_CODE] = aux_request(s->aux_bus, cmd,
554 xlnx_dp_aux_get_address(s),
555 nbytes, buf);
556 xlnx_dp_aux_clear_tx_fifo(s);
557 break;
558 case WRITE_I2C_STATUS:
559 qemu_log_mask(LOG_UNIMP, "xlnx_dp: Write i2c status not implemented\n");
560 break;
561 default:
562 qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid command: %u", __func__, cmd);
563 return;
564 }
565
566 s->core_registers[DP_INTERRUPT_SIGNAL_STATE] |= 0x04;
567 }
568
569 static void xlnx_dp_set_dpdma(const Object *obj, const char *name, Object *val,
570 Error **errp)
571 {
572 XlnxDPState *s = XLNX_DP(obj);
573
574 if (!s) {
575 error_setg(errp, "%s cannot be set to NULL", name);
576 return;
577 }
578
579 if (s->console) {
580 DisplaySurface *surface = qemu_console_surface(s->console);
581 XlnxDPDMAState *dma = XLNX_DPDMA(val);
582 xlnx_dpdma_set_host_data_location(dma, DP_GRAPHIC_DMA_CHANNEL,
583 surface_data(surface));
584 }
585 }
586
587 static inline uint8_t xlnx_dp_global_alpha_value(XlnxDPState *s)
588 {
589 return (s->vblend_registers[V_BLEND_SET_GLOBAL_ALPHA_REG] & 0x1FE) >> 1;
590 }
591
592 static inline bool xlnx_dp_global_alpha_enabled(XlnxDPState *s)
593 {
594 /*
595 * If the alpha is totally opaque (255) we consider the alpha is disabled to
596 * reduce CPU consumption.
597 */
598 return ((xlnx_dp_global_alpha_value(s) != 0xFF) &&
599 ((s->vblend_registers[V_BLEND_SET_GLOBAL_ALPHA_REG] & 0x01) != 0));
600 }
601
602 static void xlnx_dp_recreate_surface(XlnxDPState *s)
603 {
604 /*
605 * Two possibilities, if blending is enabled the console displays
606 * bout_plane, if not g_plane is displayed.
607 */
608 uint16_t width = s->core_registers[DP_MAIN_STREAM_HRES];
609 uint16_t height = s->core_registers[DP_MAIN_STREAM_VRES];
610 DisplaySurface *current_console_surface = qemu_console_surface(s->console);
611
612 if ((width != 0) && (height != 0)) {
613 /*
614 * As qemu_console_replace_surface calls qemu_free_displaysurface on the
615 * surface we need to be careful and don't free the surface associated
616 * to the console or double free will happen.
617 */
618 if (s->bout_plane.surface != current_console_surface) {
619 qemu_free_displaysurface(s->bout_plane.surface);
620 }
621 if (s->v_plane.surface != current_console_surface) {
622 qemu_free_displaysurface(s->v_plane.surface);
623 }
624 if (s->g_plane.surface != current_console_surface) {
625 qemu_free_displaysurface(s->g_plane.surface);
626 }
627
628 s->g_plane.surface
629 = qemu_create_displaysurface_from(width, height,
630 s->g_plane.format, 0, NULL);
631 s->v_plane.surface
632 = qemu_create_displaysurface_from(width, height,
633 s->v_plane.format, 0, NULL);
634 if (xlnx_dp_global_alpha_enabled(s)) {
635 s->bout_plane.surface =
636 qemu_create_displaysurface_from(width,
637 height,
638 s->g_plane.format,
639 0, NULL);
640 qemu_console_set_surface(s->console, s->bout_plane.surface);
641 } else {
642 s->bout_plane.surface = NULL;
643 qemu_console_set_surface(s->console, s->g_plane.surface);
644 }
645
646 xlnx_dpdma_set_host_data_location(s->dpdma, DP_GRAPHIC_DMA_CHANNEL,
647 surface_data(s->g_plane.surface));
648 xlnx_dpdma_set_host_data_location(s->dpdma, DP_VIDEO_DMA_CHANNEL,
649 surface_data(s->v_plane.surface));
650 }
651 }
652
653 /*
654 * Change the graphic format of the surface.
655 */
656 static void xlnx_dp_change_graphic_fmt(XlnxDPState *s)
657 {
658 switch (s->avbufm_registers[AV_BUF_FORMAT] & DP_GRAPHIC_MASK) {
659 case DP_GRAPHIC_RGBA8888:
660 s->g_plane.format = PIXMAN_r8g8b8a8;
661 break;
662 case DP_GRAPHIC_ABGR8888:
663 s->g_plane.format = PIXMAN_a8b8g8r8;
664 break;
665 case DP_GRAPHIC_RGB565:
666 s->g_plane.format = PIXMAN_r5g6b5;
667 break;
668 case DP_GRAPHIC_RGB888:
669 s->g_plane.format = PIXMAN_r8g8b8;
670 break;
671 case DP_GRAPHIC_BGR888:
672 s->g_plane.format = PIXMAN_b8g8r8;
673 break;
674 case DP_GRAPHIC_RGBA5551:
675 case DP_GRAPHIC_RGBA4444:
676 case DP_GRAPHIC_8BPP:
677 case DP_GRAPHIC_4BPP:
678 case DP_GRAPHIC_2BPP:
679 case DP_GRAPHIC_1BPP:
680 qemu_log_mask(LOG_UNIMP, "%s: unimplemented graphic format %u",
681 __func__,
682 s->avbufm_registers[AV_BUF_FORMAT] & DP_GRAPHIC_MASK);
683 s->g_plane.format = PIXMAN_r8g8b8a8;
684 break;
685 default:
686 qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid graphic format %u",
687 __func__,
688 s->avbufm_registers[AV_BUF_FORMAT] & DP_GRAPHIC_MASK);
689 s->g_plane.format = PIXMAN_r8g8b8a8;
690 break;
691 }
692
693 switch (s->avbufm_registers[AV_BUF_FORMAT] & DP_NL_VID_FMT_MASK) {
694 case 0:
695 /* This is DP_NL_VID_CB_Y0_CR_Y1 ??? */
696 s->v_plane.format = PIXMAN_x8b8g8r8;
697 break;
698 case DP_NL_VID_Y0_CB_Y1_CR:
699 s->v_plane.format = PIXMAN_yuy2;
700 break;
701 case DP_NL_VID_RGBA8880:
702 s->v_plane.format = PIXMAN_x8b8g8r8;
703 break;
704 case DP_NL_VID_CR_Y0_CB_Y1:
705 case DP_NL_VID_Y0_CR_Y1_CB:
706 case DP_NL_VID_YV16:
707 case DP_NL_VID_YV24:
708 case DP_NL_VID_YV16CL:
709 case DP_NL_VID_MONO:
710 case DP_NL_VID_YV16CL2:
711 case DP_NL_VID_YUV444:
712 case DP_NL_VID_RGB888:
713 case DP_NL_VID_RGB888_10BPC:
714 case DP_NL_VID_YUV444_10BPC:
715 case DP_NL_VID_YV16CL2_10BPC:
716 case DP_NL_VID_YV16CL_10BPC:
717 case DP_NL_VID_YV16_10BPC:
718 case DP_NL_VID_YV24_10BPC:
719 case DP_NL_VID_Y_ONLY_10BPC:
720 case DP_NL_VID_YV16_420:
721 case DP_NL_VID_YV16CL_420:
722 case DP_NL_VID_YV16CL2_420:
723 case DP_NL_VID_YV16_420_10BPC:
724 case DP_NL_VID_YV16CL_420_10BPC:
725 case DP_NL_VID_YV16CL2_420_10BPC:
726 qemu_log_mask(LOG_UNIMP, "%s: unimplemented video format %u",
727 __func__,
728 s->avbufm_registers[AV_BUF_FORMAT] & DP_NL_VID_FMT_MASK);
729 s->v_plane.format = PIXMAN_x8b8g8r8;
730 break;
731 default:
732 qemu_log_mask(LOG_UNIMP, "%s: invalid video format %u",
733 __func__,
734 s->avbufm_registers[AV_BUF_FORMAT] & DP_NL_VID_FMT_MASK);
735 s->v_plane.format = PIXMAN_x8b8g8r8;
736 break;
737 }
738
739 xlnx_dp_recreate_surface(s);
740 }
741
742 static void xlnx_dp_update_irq(XlnxDPState *s)
743 {
744 uint32_t flags;
745
746 flags = s->core_registers[DP_INT_STATUS] & ~s->core_registers[DP_INT_MASK];
747 DPRINTF("update IRQ value = %" PRIx32 "\n", flags);
748 qemu_set_irq(s->irq, flags != 0);
749 }
750
751 static uint64_t xlnx_dp_read(void *opaque, hwaddr offset, unsigned size)
752 {
753 XlnxDPState *s = XLNX_DP(opaque);
754 uint64_t ret = 0;
755
756 offset = offset >> 2;
757
758 switch (offset) {
759 case DP_TX_USER_FIFO_OVERFLOW:
760 /* This register is cleared after a read */
761 ret = s->core_registers[DP_TX_USER_FIFO_OVERFLOW];
762 s->core_registers[DP_TX_USER_FIFO_OVERFLOW] = 0;
763 break;
764 case DP_AUX_REPLY_DATA:
765 ret = xlnx_dp_aux_pop_rx_fifo(s);
766 break;
767 case DP_INTERRUPT_SIGNAL_STATE:
768 /*
769 * XXX: Not sure it is the right thing to do actually.
770 * The register is not written by the device driver so it's stuck
771 * to 0x04.
772 */
773 ret = s->core_registers[DP_INTERRUPT_SIGNAL_STATE];
774 s->core_registers[DP_INTERRUPT_SIGNAL_STATE] &= ~0x04;
775 break;
776 case DP_AUX_WRITE_FIFO:
777 case DP_TX_AUDIO_INFO_DATA(0):
778 case DP_TX_AUDIO_INFO_DATA(1):
779 case DP_TX_AUDIO_INFO_DATA(2):
780 case DP_TX_AUDIO_INFO_DATA(3):
781 case DP_TX_AUDIO_INFO_DATA(4):
782 case DP_TX_AUDIO_INFO_DATA(5):
783 case DP_TX_AUDIO_INFO_DATA(6):
784 case DP_TX_AUDIO_INFO_DATA(7):
785 case DP_TX_AUDIO_EXT_DATA(0):
786 case DP_TX_AUDIO_EXT_DATA(1):
787 case DP_TX_AUDIO_EXT_DATA(2):
788 case DP_TX_AUDIO_EXT_DATA(3):
789 case DP_TX_AUDIO_EXT_DATA(4):
790 case DP_TX_AUDIO_EXT_DATA(5):
791 case DP_TX_AUDIO_EXT_DATA(6):
792 case DP_TX_AUDIO_EXT_DATA(7):
793 case DP_TX_AUDIO_EXT_DATA(8):
794 /* write only registers */
795 ret = 0;
796 break;
797 default:
798 assert(offset <= (0x3AC >> 2));
799 if (offset == (0x3A8 >> 2) || offset == (0x3AC >> 2)) {
800 ret = s->core_registers[DP_INT_MASK];
801 } else {
802 ret = s->core_registers[offset];
803 }
804 break;
805 }
806
807 DPRINTF("core read @%" PRIx64 " = 0x%8.8" PRIX64 "\n", offset << 2, ret);
808 return ret;
809 }
810
811 static void xlnx_dp_write(void *opaque, hwaddr offset, uint64_t value,
812 unsigned size)
813 {
814 XlnxDPState *s = XLNX_DP(opaque);
815
816 DPRINTF("core write @%" PRIx64 " = 0x%8.8" PRIX64 "\n", offset, value);
817
818 offset = offset >> 2;
819
820 switch (offset) {
821 /*
822 * Only special write case are handled.
823 */
824 case DP_LINK_BW_SET:
825 s->core_registers[offset] = value & 0x000000FF;
826 break;
827 case DP_LANE_COUNT_SET:
828 case DP_MAIN_STREAM_MISC0:
829 s->core_registers[offset] = value & 0x0000000F;
830 break;
831 case DP_TRAINING_PATTERN_SET:
832 case DP_LINK_QUAL_PATTERN_SET:
833 case DP_MAIN_STREAM_POLARITY:
834 case DP_PHY_VOLTAGE_DIFF_LANE_0:
835 case DP_PHY_VOLTAGE_DIFF_LANE_1:
836 s->core_registers[offset] = value & 0x00000003;
837 break;
838 case DP_ENHANCED_FRAME_EN:
839 case DP_SCRAMBLING_DISABLE:
840 case DP_DOWNSPREAD_CTRL:
841 case DP_MAIN_STREAM_ENABLE:
842 case DP_TRANSMIT_PRBS7:
843 s->core_registers[offset] = value & 0x00000001;
844 break;
845 case DP_PHY_CLOCK_SELECT:
846 s->core_registers[offset] = value & 0x00000007;
847 break;
848 case DP_SOFTWARE_RESET:
849 /*
850 * No need to update this bit as it's read '0'.
851 */
852 /*
853 * TODO: reset IP.
854 */
855 break;
856 case DP_TRANSMITTER_ENABLE:
857 s->core_registers[offset] = value & 0x01;
858 ptimer_transaction_begin(s->vblank);
859 if (value & 0x1) {
860 ptimer_run(s->vblank, 0);
861 } else {
862 ptimer_stop(s->vblank);
863 }
864 ptimer_transaction_commit(s->vblank);
865 break;
866 case DP_FORCE_SCRAMBLER_RESET:
867 /*
868 * No need to update this bit as it's read '0'.
869 */
870 /*
871 * TODO: force a scrambler reset??
872 */
873 break;
874 case DP_AUX_COMMAND_REGISTER:
875 s->core_registers[offset] = value & 0x00001F0F;
876 xlnx_dp_aux_set_command(s, s->core_registers[offset]);
877 break;
878 case DP_MAIN_STREAM_HTOTAL:
879 case DP_MAIN_STREAM_VTOTAL:
880 case DP_MAIN_STREAM_HSTART:
881 case DP_MAIN_STREAM_VSTART:
882 s->core_registers[offset] = value & 0x0000FFFF;
883 break;
884 case DP_MAIN_STREAM_HRES:
885 case DP_MAIN_STREAM_VRES:
886 s->core_registers[offset] = value & 0x0000FFFF;
887 xlnx_dp_recreate_surface(s);
888 break;
889 case DP_MAIN_STREAM_HSWIDTH:
890 case DP_MAIN_STREAM_VSWIDTH:
891 s->core_registers[offset] = value & 0x00007FFF;
892 break;
893 case DP_MAIN_STREAM_MISC1:
894 s->core_registers[offset] = value & 0x00000086;
895 break;
896 case DP_MAIN_STREAM_M_VID:
897 case DP_MAIN_STREAM_N_VID:
898 s->core_registers[offset] = value & 0x00FFFFFF;
899 break;
900 case DP_MSA_TRANSFER_UNIT_SIZE:
901 case DP_MIN_BYTES_PER_TU:
902 case DP_INIT_WAIT:
903 s->core_registers[offset] = value & 0x00000007;
904 break;
905 case DP_USER_DATA_COUNT_PER_LANE:
906 s->core_registers[offset] = value & 0x0003FFFF;
907 break;
908 case DP_FRAC_BYTES_PER_TU:
909 s->core_registers[offset] = value & 0x000003FF;
910 break;
911 case DP_PHY_RESET:
912 s->core_registers[offset] = value & 0x00010003;
913 /*
914 * TODO: Reset something?
915 */
916 break;
917 case DP_TX_PHY_POWER_DOWN:
918 s->core_registers[offset] = value & 0x0000000F;
919 /*
920 * TODO: Power down things?
921 */
922 break;
923 case DP_AUX_WRITE_FIFO: {
924 uint8_t c = value;
925 xlnx_dp_aux_push_tx_fifo(s, &c, 1);
926 break;
927 }
928 case DP_AUX_CLOCK_DIVIDER:
929 break;
930 case DP_AUX_REPLY_COUNT:
931 /*
932 * Writing to this register clear the counter.
933 */
934 s->core_registers[offset] = 0x00000000;
935 break;
936 case DP_AUX_ADDRESS:
937 s->core_registers[offset] = value & 0x000FFFFF;
938 break;
939 case DP_VERSION_REGISTER:
940 case DP_CORE_ID:
941 case DP_TX_USER_FIFO_OVERFLOW:
942 case DP_AUX_REPLY_DATA:
943 case DP_AUX_REPLY_CODE:
944 case DP_REPLY_DATA_COUNT:
945 case DP_REPLY_STATUS:
946 case DP_HPD_DURATION:
947 /*
948 * Write to read only location..
949 */
950 break;
951 case DP_TX_AUDIO_CONTROL:
952 s->core_registers[offset] = value & 0x00000001;
953 xlnx_dp_audio_activate(s);
954 break;
955 case DP_TX_AUDIO_CHANNELS:
956 s->core_registers[offset] = value & 0x00000007;
957 xlnx_dp_audio_activate(s);
958 break;
959 case DP_INT_STATUS:
960 s->core_registers[DP_INT_STATUS] &= ~value;
961 xlnx_dp_update_irq(s);
962 break;
963 case DP_INT_EN:
964 s->core_registers[DP_INT_MASK] &= ~value;
965 xlnx_dp_update_irq(s);
966 break;
967 case DP_INT_DS:
968 s->core_registers[DP_INT_MASK] |= value;
969 xlnx_dp_update_irq(s);
970 break;
971 default:
972 assert(offset <= (0x504C >> 2));
973 s->core_registers[offset] = value;
974 break;
975 }
976 }
977
978 static const MemoryRegionOps dp_ops = {
979 .read = xlnx_dp_read,
980 .write = xlnx_dp_write,
981 .endianness = DEVICE_NATIVE_ENDIAN,
982 .valid = {
983 .min_access_size = 4,
984 .max_access_size = 4,
985 },
986 .impl = {
987 .min_access_size = 4,
988 .max_access_size = 4,
989 },
990 };
991
992 /*
993 * This is to handle Read/Write to the Video Blender.
994 */
995 static void xlnx_dp_vblend_write(void *opaque, hwaddr offset,
996 uint64_t value, unsigned size)
997 {
998 XlnxDPState *s = XLNX_DP(opaque);
999 bool alpha_was_enabled;
1000
1001 DPRINTF("vblend: write @0x%" HWADDR_PRIX " = 0x%" PRIX32 "\n", offset,
1002 (uint32_t)value);
1003 offset = offset >> 2;
1004
1005 switch (offset) {
1006 case V_BLEND_BG_CLR_0:
1007 case V_BLEND_BG_CLR_1:
1008 case V_BLEND_BG_CLR_2:
1009 s->vblend_registers[offset] = value & 0x00000FFF;
1010 break;
1011 case V_BLEND_SET_GLOBAL_ALPHA_REG:
1012 /*
1013 * A write to this register can enable or disable blending. Thus we need
1014 * to recreate the surfaces.
1015 */
1016 alpha_was_enabled = xlnx_dp_global_alpha_enabled(s);
1017 s->vblend_registers[offset] = value & 0x000001FF;
1018 if (xlnx_dp_global_alpha_enabled(s) != alpha_was_enabled) {
1019 xlnx_dp_recreate_surface(s);
1020 }
1021 break;
1022 case V_BLEND_OUTPUT_VID_FORMAT:
1023 s->vblend_registers[offset] = value & 0x00000017;
1024 break;
1025 case V_BLEND_LAYER0_CONTROL:
1026 case V_BLEND_LAYER1_CONTROL:
1027 s->vblend_registers[offset] = value & 0x00000103;
1028 break;
1029 case V_BLEND_RGB2YCBCR_COEFF(0):
1030 case V_BLEND_RGB2YCBCR_COEFF(1):
1031 case V_BLEND_RGB2YCBCR_COEFF(2):
1032 case V_BLEND_RGB2YCBCR_COEFF(3):
1033 case V_BLEND_RGB2YCBCR_COEFF(4):
1034 case V_BLEND_RGB2YCBCR_COEFF(5):
1035 case V_BLEND_RGB2YCBCR_COEFF(6):
1036 case V_BLEND_RGB2YCBCR_COEFF(7):
1037 case V_BLEND_RGB2YCBCR_COEFF(8):
1038 case V_BLEND_IN1CSC_COEFF(0):
1039 case V_BLEND_IN1CSC_COEFF(1):
1040 case V_BLEND_IN1CSC_COEFF(2):
1041 case V_BLEND_IN1CSC_COEFF(3):
1042 case V_BLEND_IN1CSC_COEFF(4):
1043 case V_BLEND_IN1CSC_COEFF(5):
1044 case V_BLEND_IN1CSC_COEFF(6):
1045 case V_BLEND_IN1CSC_COEFF(7):
1046 case V_BLEND_IN1CSC_COEFF(8):
1047 case V_BLEND_IN2CSC_COEFF(0):
1048 case V_BLEND_IN2CSC_COEFF(1):
1049 case V_BLEND_IN2CSC_COEFF(2):
1050 case V_BLEND_IN2CSC_COEFF(3):
1051 case V_BLEND_IN2CSC_COEFF(4):
1052 case V_BLEND_IN2CSC_COEFF(5):
1053 case V_BLEND_IN2CSC_COEFF(6):
1054 case V_BLEND_IN2CSC_COEFF(7):
1055 case V_BLEND_IN2CSC_COEFF(8):
1056 s->vblend_registers[offset] = value & 0x0000FFFF;
1057 break;
1058 case V_BLEND_LUMA_IN1CSC_OFFSET:
1059 case V_BLEND_CR_IN1CSC_OFFSET:
1060 case V_BLEND_CB_IN1CSC_OFFSET:
1061 case V_BLEND_LUMA_IN2CSC_OFFSET:
1062 case V_BLEND_CR_IN2CSC_OFFSET:
1063 case V_BLEND_CB_IN2CSC_OFFSET:
1064 case V_BLEND_LUMA_OUTCSC_OFFSET:
1065 case V_BLEND_CR_OUTCSC_OFFSET:
1066 case V_BLEND_CB_OUTCSC_OFFSET:
1067 s->vblend_registers[offset] = value & 0x3FFF7FFF;
1068 break;
1069 case V_BLEND_CHROMA_KEY_ENABLE:
1070 s->vblend_registers[offset] = value & 0x00000003;
1071 break;
1072 case V_BLEND_CHROMA_KEY_COMP1:
1073 case V_BLEND_CHROMA_KEY_COMP2:
1074 case V_BLEND_CHROMA_KEY_COMP3:
1075 s->vblend_registers[offset] = value & 0x0FFF0FFF;
1076 break;
1077 default:
1078 s->vblend_registers[offset] = value;
1079 break;
1080 }
1081 }
1082
1083 static uint64_t xlnx_dp_vblend_read(void *opaque, hwaddr offset,
1084 unsigned size)
1085 {
1086 XlnxDPState *s = XLNX_DP(opaque);
1087
1088 DPRINTF("vblend: read @0x%" HWADDR_PRIX " = 0x%" PRIX32 "\n", offset,
1089 s->vblend_registers[offset >> 2]);
1090 return s->vblend_registers[offset >> 2];
1091 }
1092
1093 static const MemoryRegionOps vblend_ops = {
1094 .read = xlnx_dp_vblend_read,
1095 .write = xlnx_dp_vblend_write,
1096 .endianness = DEVICE_NATIVE_ENDIAN,
1097 .valid = {
1098 .min_access_size = 4,
1099 .max_access_size = 4,
1100 },
1101 .impl = {
1102 .min_access_size = 4,
1103 .max_access_size = 4,
1104 },
1105 };
1106
1107 /*
1108 * This is to handle Read/Write to the Audio Video buffer manager.
1109 */
1110 static void xlnx_dp_avbufm_write(void *opaque, hwaddr offset, uint64_t value,
1111 unsigned size)
1112 {
1113 XlnxDPState *s = XLNX_DP(opaque);
1114
1115 DPRINTF("avbufm: write @0x%" HWADDR_PRIX " = 0x%" PRIX32 "\n", offset,
1116 (uint32_t)value);
1117 offset = offset >> 2;
1118
1119 switch (offset) {
1120 case AV_BUF_FORMAT:
1121 s->avbufm_registers[offset] = value & 0x00000FFF;
1122 xlnx_dp_change_graphic_fmt(s);
1123 break;
1124 case AV_CHBUF0:
1125 case AV_CHBUF1:
1126 case AV_CHBUF2:
1127 case AV_CHBUF3:
1128 case AV_CHBUF4:
1129 case AV_CHBUF5:
1130 s->avbufm_registers[offset] = value & 0x0000007F;
1131 break;
1132 case AV_BUF_OUTPUT_AUDIO_VIDEO_SELECT:
1133 s->avbufm_registers[offset] = value & 0x0000007F;
1134 break;
1135 case AV_BUF_DITHER_CONFIG:
1136 s->avbufm_registers[offset] = value & 0x000007FF;
1137 break;
1138 case AV_BUF_DITHER_CONFIG_MAX:
1139 case AV_BUF_DITHER_CONFIG_MIN:
1140 s->avbufm_registers[offset] = value & 0x00000FFF;
1141 break;
1142 case AV_BUF_PATTERN_GEN_SELECT:
1143 s->avbufm_registers[offset] = value & 0xFFFFFF03;
1144 break;
1145 case AV_BUF_AUD_VID_CLK_SOURCE:
1146 s->avbufm_registers[offset] = value & 0x00000007;
1147 break;
1148 case AV_BUF_SRST_REG:
1149 s->avbufm_registers[offset] = value & 0x00000002;
1150 break;
1151 case AV_BUF_AUDIO_CH_CONFIG:
1152 s->avbufm_registers[offset] = value & 0x00000003;
1153 break;
1154 case AV_BUF_GRAPHICS_COMP_SCALE_FACTOR(0):
1155 case AV_BUF_GRAPHICS_COMP_SCALE_FACTOR(1):
1156 case AV_BUF_GRAPHICS_COMP_SCALE_FACTOR(2):
1157 case AV_BUF_VIDEO_COMP_SCALE_FACTOR(0):
1158 case AV_BUF_VIDEO_COMP_SCALE_FACTOR(1):
1159 case AV_BUF_VIDEO_COMP_SCALE_FACTOR(2):
1160 s->avbufm_registers[offset] = value & 0x0000FFFF;
1161 break;
1162 case AV_BUF_LIVE_VIDEO_COMP_SF(0):
1163 case AV_BUF_LIVE_VIDEO_COMP_SF(1):
1164 case AV_BUF_LIVE_VIDEO_COMP_SF(2):
1165 case AV_BUF_LIVE_VID_CONFIG:
1166 case AV_BUF_LIVE_GFX_COMP_SF(0):
1167 case AV_BUF_LIVE_GFX_COMP_SF(1):
1168 case AV_BUF_LIVE_GFX_COMP_SF(2):
1169 case AV_BUF_LIVE_GFX_CONFIG:
1170 case AV_BUF_NON_LIVE_LATENCY:
1171 case AV_BUF_STC_CONTROL:
1172 case AV_BUF_STC_INIT_VALUE0:
1173 case AV_BUF_STC_INIT_VALUE1:
1174 case AV_BUF_STC_ADJ:
1175 case AV_BUF_STC_VIDEO_VSYNC_TS_REG0:
1176 case AV_BUF_STC_VIDEO_VSYNC_TS_REG1:
1177 case AV_BUF_STC_EXT_VSYNC_TS_REG0:
1178 case AV_BUF_STC_EXT_VSYNC_TS_REG1:
1179 case AV_BUF_STC_CUSTOM_EVENT_TS_REG0:
1180 case AV_BUF_STC_CUSTOM_EVENT_TS_REG1:
1181 case AV_BUF_STC_CUSTOM_EVENT2_TS_REG0:
1182 case AV_BUF_STC_CUSTOM_EVENT2_TS_REG1:
1183 case AV_BUF_STC_SNAPSHOT0:
1184 case AV_BUF_STC_SNAPSHOT1:
1185 case AV_BUF_HCOUNT_VCOUNT_INT0:
1186 case AV_BUF_HCOUNT_VCOUNT_INT1:
1187 qemu_log_mask(LOG_UNIMP, "avbufm: unimplemented register 0x%04"
1188 PRIx64 "\n",
1189 offset << 2);
1190 break;
1191 default:
1192 s->avbufm_registers[offset] = value;
1193 break;
1194 }
1195 }
1196
1197 static uint64_t xlnx_dp_avbufm_read(void *opaque, hwaddr offset,
1198 unsigned size)
1199 {
1200 XlnxDPState *s = XLNX_DP(opaque);
1201
1202 offset = offset >> 2;
1203 return s->avbufm_registers[offset];
1204 }
1205
1206 static const MemoryRegionOps avbufm_ops = {
1207 .read = xlnx_dp_avbufm_read,
1208 .write = xlnx_dp_avbufm_write,
1209 .endianness = DEVICE_NATIVE_ENDIAN,
1210 .valid = {
1211 .min_access_size = 4,
1212 .max_access_size = 4,
1213 },
1214 .impl = {
1215 .min_access_size = 4,
1216 .max_access_size = 4,
1217 },
1218 };
1219
1220 /*
1221 * This is a global alpha blending using pixman.
1222 * Both graphic and video planes are multiplied with the global alpha
1223 * coefficient and added.
1224 */
1225 static inline void xlnx_dp_blend_surface(XlnxDPState *s)
1226 {
1227 pixman_fixed_t alpha1[] = { pixman_double_to_fixed(1),
1228 pixman_double_to_fixed(1),
1229 pixman_double_to_fixed(1.0) };
1230 pixman_fixed_t alpha2[] = { pixman_double_to_fixed(1),
1231 pixman_double_to_fixed(1),
1232 pixman_double_to_fixed(1.0) };
1233
1234 if ((surface_width(s->g_plane.surface)
1235 != surface_width(s->v_plane.surface)) ||
1236 (surface_height(s->g_plane.surface)
1237 != surface_height(s->v_plane.surface))) {
1238 return;
1239 }
1240
1241 alpha1[2] = pixman_double_to_fixed((double)(xlnx_dp_global_alpha_value(s))
1242 / 256.0);
1243 alpha2[2] = pixman_double_to_fixed((255.0
1244 - (double)xlnx_dp_global_alpha_value(s))
1245 / 256.0);
1246
1247 pixman_image_set_filter(s->g_plane.surface->image,
1248 PIXMAN_FILTER_CONVOLUTION, alpha1, 3);
1249 pixman_image_composite(PIXMAN_OP_SRC, s->g_plane.surface->image, 0,
1250 s->bout_plane.surface->image, 0, 0, 0, 0, 0, 0,
1251 surface_width(s->g_plane.surface),
1252 surface_height(s->g_plane.surface));
1253 pixman_image_set_filter(s->v_plane.surface->image,
1254 PIXMAN_FILTER_CONVOLUTION, alpha2, 3);
1255 pixman_image_composite(PIXMAN_OP_ADD, s->v_plane.surface->image, 0,
1256 s->bout_plane.surface->image, 0, 0, 0, 0, 0, 0,
1257 surface_width(s->g_plane.surface),
1258 surface_height(s->g_plane.surface));
1259 }
1260
1261 static bool xlnx_dp_update_display(void *opaque)
1262 {
1263 XlnxDPState *s = XLNX_DP(opaque);
1264
1265 if ((s->core_registers[DP_TRANSMITTER_ENABLE] & 0x01) == 0) {
1266 return true;
1267 }
1268
1269 xlnx_dpdma_trigger_vsync_irq(s->dpdma);
1270
1271 /*
1272 * Trigger the DMA channel.
1273 */
1274 if (!xlnx_dpdma_start_operation(s->dpdma, 3, false)) {
1275 /*
1276 * An error occurred don't do anything with the data..
1277 * Trigger an underflow interrupt.
1278 */
1279 s->core_registers[DP_INT_STATUS] |= (1 << 21);
1280 xlnx_dp_update_irq(s);
1281 return true;
1282 }
1283
1284 if (xlnx_dp_global_alpha_enabled(s)) {
1285 if (!xlnx_dpdma_start_operation(s->dpdma, 0, false)) {
1286 s->core_registers[DP_INT_STATUS] |= (1 << 21);
1287 xlnx_dp_update_irq(s);
1288 return true;
1289 }
1290 xlnx_dp_blend_surface(s);
1291 }
1292
1293 /*
1294 * XXX: We might want to update only what changed.
1295 */
1296 qemu_console_update_full(s->console);
1297
1298 return true;
1299 }
1300
1301 static const GraphicHwOps xlnx_dp_gfx_ops = {
1302 .gfx_update = xlnx_dp_update_display,
1303 };
1304
1305 static void xlnx_dp_init(Object *obj)
1306 {
1307 SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
1308 XlnxDPState *s = XLNX_DP(obj);
1309
1310 memory_region_init(&s->container, obj, TYPE_XLNX_DP, DP_CONTAINER_SIZE);
1311
1312 memory_region_init_io(&s->core_iomem, obj, &dp_ops, s, TYPE_XLNX_DP
1313 ".core", sizeof(s->core_registers));
1314 memory_region_add_subregion(&s->container, DP_CORE_REG_OFFSET,
1315 &s->core_iomem);
1316
1317 memory_region_init_io(&s->vblend_iomem, obj, &vblend_ops, s, TYPE_XLNX_DP
1318 ".v_blend", sizeof(s->vblend_registers));
1319 memory_region_add_subregion(&s->container, DP_VBLEND_REG_OFFSET,
1320 &s->vblend_iomem);
1321
1322 memory_region_init_io(&s->avbufm_iomem, obj, &avbufm_ops, s, TYPE_XLNX_DP
1323 ".av_buffer_manager", sizeof(s->avbufm_registers));
1324 memory_region_add_subregion(&s->container, DP_AVBUF_REG_OFFSET,
1325 &s->avbufm_iomem);
1326
1327 memory_region_init_io(&s->audio_iomem, obj, &audio_ops, s, TYPE_XLNX_DP
1328 ".audio", sizeof(s->audio_registers));
1329 memory_region_add_subregion(&s->container, 0xC000, &s->audio_iomem);
1330
1331 sysbus_init_mmio(sbd, &s->container);
1332 sysbus_init_irq(sbd, &s->irq);
1333
1334 object_property_add_link(obj, "dpdma", TYPE_XLNX_DPDMA,
1335 (Object **) &s->dpdma,
1336 xlnx_dp_set_dpdma,
1337 OBJ_PROP_LINK_STRONG);
1338
1339 /*
1340 * Initialize AUX Bus.
1341 */
1342 s->aux_bus = aux_bus_init(DEVICE(obj), "aux");
1343
1344 /*
1345 * Initialize DPCD and EDID. Once we have added the objects as
1346 * child properties of this device, we can drop the reference we
1347 * hold to them, leaving the child-property as the only reference.
1348 */
1349 s->dpcd = DPCD(qdev_new("dpcd"));
1350 object_property_add_child(OBJECT(s), "dpcd", OBJECT(s->dpcd));
1351 object_unref(s->dpcd);
1352
1353 s->edid = I2CDDC(qdev_new("i2c-ddc"));
1354 i2c_slave_set_address(I2C_SLAVE(s->edid), 0x50);
1355 object_property_add_child(OBJECT(s), "edid", OBJECT(s->edid));
1356 object_unref(s->edid);
1357
1358 fifo8_create(&s->rx_fifo, 16);
1359 fifo8_create(&s->tx_fifo, 16);
1360 }
1361
1362 static void xlnx_dp_finalize(Object *obj)
1363 {
1364 XlnxDPState *s = XLNX_DP(obj);
1365
1366 fifo8_destroy(&s->tx_fifo);
1367 fifo8_destroy(&s->rx_fifo);
1368 }
1369
1370 static void vblank_hit(void *opaque)
1371 {
1372 XlnxDPState *s = XLNX_DP(opaque);
1373
1374 s->core_registers[DP_INT_STATUS] |= DP_INT_VBLNK_START;
1375 xlnx_dp_update_irq(s);
1376 }
1377
1378 static void xlnx_dp_realize(DeviceState *dev, Error **errp)
1379 {
1380 XlnxDPState *s = XLNX_DP(dev);
1381 DisplaySurface *surface;
1382 struct audsettings as;
1383
1384 if (!audio_be_check(&s->audio_be, errp)) {
1385 return;
1386 }
1387
1388 aux_bus_realize(s->aux_bus);
1389
1390 qdev_realize(DEVICE(s->dpcd), BUS(s->aux_bus), &error_fatal);
1391 aux_map_slave(AUX_SLAVE(s->dpcd), 0x0000);
1392
1393 qdev_realize(DEVICE(s->edid), BUS(aux_get_i2c_bus(s->aux_bus)),
1394 &error_fatal);
1395
1396 s->console = qemu_graphic_console_create(dev, 0, &xlnx_dp_gfx_ops, s);
1397 surface = qemu_console_surface(s->console);
1398 xlnx_dpdma_set_host_data_location(s->dpdma, DP_GRAPHIC_DMA_CHANNEL,
1399 surface_data(surface));
1400
1401 as.freq = 44100;
1402 as.nchannels = 2;
1403 as.fmt = AUDIO_FORMAT_S16;
1404 as.big_endian = false;
1405
1406 s->amixer_output_stream = audio_be_open_out(s->audio_be,
1407 s->amixer_output_stream,
1408 "xlnx_dp.audio.out",
1409 s,
1410 xlnx_dp_audio_callback,
1411 &as);
1412 audio_be_set_volume_out_lr(s->audio_be, s->amixer_output_stream, 0, 255, 255);
1413 xlnx_dp_audio_activate(s);
1414 s->vblank = ptimer_init(vblank_hit, s, DP_VBLANK_PTIMER_POLICY);
1415 ptimer_transaction_begin(s->vblank);
1416 ptimer_set_freq(s->vblank, 30);
1417 ptimer_transaction_commit(s->vblank);
1418 }
1419
1420 static void xlnx_dp_reset(DeviceState *dev)
1421 {
1422 XlnxDPState *s = XLNX_DP(dev);
1423
1424 memset(s->core_registers, 0, sizeof(s->core_registers));
1425 s->core_registers[DP_VERSION_REGISTER] = 0x04010000;
1426 s->core_registers[DP_CORE_ID] = 0x01020000;
1427 s->core_registers[DP_REPLY_STATUS] = 0x00000010;
1428 s->core_registers[DP_MSA_TRANSFER_UNIT_SIZE] = 0x00000040;
1429 s->core_registers[DP_INIT_WAIT] = 0x00000020;
1430 s->core_registers[DP_PHY_RESET] = 0x00010003;
1431 s->core_registers[DP_INT_MASK] = 0xFFFFF03F;
1432 s->core_registers[DP_PHY_STATUS] = 0x00000043;
1433 s->core_registers[DP_INTERRUPT_SIGNAL_STATE] = 0x00000001;
1434
1435 s->vblend_registers[V_BLEND_RGB2YCBCR_COEFF(0)] = 0x00001000;
1436 s->vblend_registers[V_BLEND_RGB2YCBCR_COEFF(4)] = 0x00001000;
1437 s->vblend_registers[V_BLEND_RGB2YCBCR_COEFF(8)] = 0x00001000;
1438 s->vblend_registers[V_BLEND_IN1CSC_COEFF(0)] = 0x00001000;
1439 s->vblend_registers[V_BLEND_IN1CSC_COEFF(4)] = 0x00001000;
1440 s->vblend_registers[V_BLEND_IN1CSC_COEFF(8)] = 0x00001000;
1441 s->vblend_registers[V_BLEND_IN2CSC_COEFF(0)] = 0x00001000;
1442 s->vblend_registers[V_BLEND_IN2CSC_COEFF(4)] = 0x00001000;
1443 s->vblend_registers[V_BLEND_IN2CSC_COEFF(8)] = 0x00001000;
1444
1445 s->avbufm_registers[AV_BUF_NON_LIVE_LATENCY] = 0x00000180;
1446 s->avbufm_registers[AV_BUF_OUTPUT_AUDIO_VIDEO_SELECT] = 0x00000008;
1447 s->avbufm_registers[AV_BUF_DITHER_CONFIG_MAX] = 0x00000FFF;
1448 s->avbufm_registers[AV_BUF_GRAPHICS_COMP_SCALE_FACTOR(0)] = 0x00010101;
1449 s->avbufm_registers[AV_BUF_GRAPHICS_COMP_SCALE_FACTOR(1)] = 0x00010101;
1450 s->avbufm_registers[AV_BUF_GRAPHICS_COMP_SCALE_FACTOR(2)] = 0x00010101;
1451 s->avbufm_registers[AV_BUF_VIDEO_COMP_SCALE_FACTOR(0)] = 0x00010101;
1452 s->avbufm_registers[AV_BUF_VIDEO_COMP_SCALE_FACTOR(1)] = 0x00010101;
1453 s->avbufm_registers[AV_BUF_VIDEO_COMP_SCALE_FACTOR(2)] = 0x00010101;
1454 s->avbufm_registers[AV_BUF_LIVE_VIDEO_COMP_SF(0)] = 0x00010101;
1455 s->avbufm_registers[AV_BUF_LIVE_VIDEO_COMP_SF(1)] = 0x00010101;
1456 s->avbufm_registers[AV_BUF_LIVE_VIDEO_COMP_SF(2)] = 0x00010101;
1457 s->avbufm_registers[AV_BUF_LIVE_GFX_COMP_SF(0)] = 0x00010101;
1458 s->avbufm_registers[AV_BUF_LIVE_GFX_COMP_SF(1)] = 0x00010101;
1459 s->avbufm_registers[AV_BUF_LIVE_GFX_COMP_SF(2)] = 0x00010101;
1460
1461 memset(s->audio_registers, 0, sizeof(s->audio_registers));
1462 s->byte_left = 0;
1463
1464 xlnx_dp_aux_clear_rx_fifo(s);
1465 xlnx_dp_change_graphic_fmt(s);
1466 xlnx_dp_update_irq(s);
1467 }
1468
1469 static const Property xlnx_dp_device_properties[] = {
1470 DEFINE_AUDIO_PROPERTIES(XlnxDPState, audio_be),
1471 };
1472
1473 static void xlnx_dp_class_init(ObjectClass *oc, const void *data)
1474 {
1475 DeviceClass *dc = DEVICE_CLASS(oc);
1476
1477 dc->realize = xlnx_dp_realize;
1478 dc->vmsd = &vmstate_dp;
1479 device_class_set_legacy_reset(dc, xlnx_dp_reset);
1480 device_class_set_props(dc, xlnx_dp_device_properties);
1481 }
1482
1483 static const TypeInfo xlnx_dp_info = {
1484 .name = TYPE_XLNX_DP,
1485 .parent = TYPE_SYS_BUS_DEVICE,
1486 .instance_size = sizeof(XlnxDPState),
1487 .instance_init = xlnx_dp_init,
1488 .instance_finalize = xlnx_dp_finalize,
1489 .class_init = xlnx_dp_class_init,
1490 };
1491
1492 static void xlnx_dp_register_types(void)
1493 {
1494 type_register_static(&xlnx_dp_info);
1495 }
1496
1497 type_init(xlnx_dp_register_types)