1 // Copyright 2018 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #pragma once
6 
7 #include "edid.h"
8 #include <assert.h>
9 #include <ddk/debug.h>
10 #include <ddk/protocol/amlogiccanvas.h>
11 #include <ddk/protocol/display/controller.h>
12 #include <ddk/protocol/gpio.h>
13 #include <ddktl/mmio.h>
14 #include <stdint.h>
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <zircon/listnode.h>
19 #include <zircon/pixelformat.h>
20 
21 #include <optional>
22 
23 #include "vim-audio.h"
24 #include "vpu.h"
25 
26 __BEGIN_CDECLS
27 
28 #define DISP_ERROR(fmt, ...) zxlogf(ERROR, "[%s %d]" fmt, __func__, __LINE__, ##__VA_ARGS__)
29 #define DISP_INFO(fmt, ...) zxlogf(INFO, "[%s %d]" fmt, __func__, __LINE__, ##__VA_ARGS__)
30 #define DISP_SPEW(fmt, ...) zxlogf(SPEW, "[%s %d]" fmt, __func__, __LINE__, ##__VA_ARGS__)
31 #define DISP_TRACE  zxlogf(INFO, "[%s %d]\n", __func__, __LINE__)
32 
33 #define NUM_CANVAS_ENTRIES 256
34 #define CANVAS_BYTE_STRIDE 32
35 
36 // From uBoot source
37 #define VFIFO2VD_TO_HDMI_LATENCY 2
38 #define EDID_BUF_SIZE       256
39 
40 #define MAX_RDMA_CHANNELS 3
41 
42 // Should match display_irqs table in board driver
43 enum {
44     IRQ_VSYNC,
45     IRQ_RDMA,
46 };
47 
48 
49 // MMIO indices (based on vim2_display_mmios)
50 enum {
51     MMIO_PRESET = 0,
52     MMIO_HDMITX,
53     MMIO_HIU,
54     MMIO_VPU,
55     MMIO_HDMTX_SEC,
56     MMIO_DMC,
57     MMIO_CBUS,
58     MMIO_AUD_OUT,
59     MMIO_COUNT  // Must be the final entry
60 };
61 
62 // BTI indices (based on vim2_display_btis)
63 enum {
64     BTI_DISPLAY = 0,
65     BTI_AUDIO,
66     BTI_COUNT  // Must be the final entry
67 };
68 
69 typedef struct vim2_display {
70     zx_device_t*                        zxdev;
71     pdev_protocol_t          pdev;
72     zx_device_t*                        parent;
73     zx_device_t*                        mydevice;
74     zx_handle_t                         bti;
75     zx_handle_t                         inth;
76 
77     gpio_protocol_t                     gpio;
78     amlogic_canvas_protocol_t           canvas;
79 
80     thrd_t                              main_thread;
81     thrd_t                              vsync_thread;
82 
83     // RDMA IRQ thread
84     thrd_t                              rdma_thread;
85 
86     // Lock for general display state, in particular display_id.
87     mtx_t                               display_lock;
88     // Lock for imported images.
89     mtx_t                               image_lock;
90     mtx_t                               i2c_lock;
91 
92     // TODO(stevensd): This can race if this is changed right after
93     // vsync but before the interrupt is handled.
94     bool                                current_image_valid;
95     uint8_t                             current_image;
96     bool                                vd1_image_valid;
97     uint32_t                            vd1_image;
98 
99     std::optional<ddk::MmioBuffer>    mmio_preset;
100     std::optional<ddk::MmioBuffer>    mmio_hdmitx;
101     std::optional<ddk::MmioBuffer>    mmio_hiu;
102     std::optional<ddk::MmioBuffer>    mmio_vpu;
103     std::optional<ddk::MmioBuffer>    mmio_hdmitx_sec;
104     std::optional<ddk::MmioBuffer>    mmio_dmc;
105     std::optional<ddk::MmioBuffer>    mmio_cbus;
106 
107     zx_handle_t                         vsync_interrupt;
108     zx_handle_t                         rdma_interrupt;
109     RdmaContainer                       rdma_container;
110 
111     bool                                display_attached;
112     // The current display id (if display_attached), or the next display id
113     uint64_t                            display_id;
114     const char* manufacturer_name;
115     char monitor_name[14];
116     char monitor_serial[14];
117 
118     uint8_t                             input_color_format;
119     uint8_t                             output_color_format;
120     uint8_t                             color_depth;
121 
122     struct hdmi_param*                  p;
123     display_mode_t                      cur_display_mode;
124 
125     display_controller_interface_t      dc_intf;
126     list_node_t                         imported_images;
127 
128     // A reference to the object which controls the VIM2 DAIs used to feed audio
129     // into the HDMI stream.
130     vim2_audio_t*                       audio;
131     uint32_t                            audio_format_count;
132 } vim2_display_t;
133 
134 void disable_vd(vim2_display_t* display, uint32_t vd_index);
135 void configure_vd(vim2_display_t* display, uint32_t vd_index);
136 void flip_vd(vim2_display_t* display, uint32_t vd_index, uint32_t index);
137 
138 void disable_osd(vim2_display_t* display, uint32_t osd_index);
139 zx_status_t configure_osd(vim2_display_t* display, uint32_t osd_index);
140 void flip_osd(vim2_display_t* display, uint32_t osd_index, uint8_t idx);
141 void osd_debug_dump_register_all(vim2_display_t* display);
142 void osd_dump(vim2_display_t* display);
143 void release_osd(vim2_display_t* display);
144 zx_status_t setup_rdma(vim2_display_t* display);
145 int rdma_thread(void *arg);
146 zx_status_t get_preferred_res(vim2_display_t* display, uint16_t edid_buf_size);
147 struct hdmi_param** get_supported_formats(void);
148 
149 // TODO(johngro) : eliminate the need for these hooks if/when we start to
150 // support composite device drivers and can separate the DAI driver from the
151 // HDMI driver (which is currently playing the role of codec driver)
152 //
153 // TODO(johngro) : add any info needed to properly set up the audio info-frame.
154 zx_status_t vim2_display_configure_audio_mode(const vim2_display_t* display,
155                                               uint32_t N,
156                                               uint32_t CTS,
157                                               uint32_t frame_rate,
158                                               uint32_t bits_per_sample);
159 void vim2_display_disable_audio(const vim2_display_t* display);
160 
161 __END_CDECLS
162