• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 HiSilicon (Shanghai) Technologies CO., LIMITED.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17  */
18 
19 #include "drv_hdmi_intf.h"
20 #ifndef HDMI_LITEOS_SUPPORT
21 #include <linux/kthread.h>
22 #endif
23 #include "hdmi_hal.h"
24 #include "hdmi_product_define.h"
25 #include "drv_hdmi_intf_k.h"
26 #include "drv_hdmi_edid.h"
27 #include "drv_hdmi_event.h"
28 #include "drv_hdmi_ioctl.h"
29 #include "drv_hdmi_debug.h"
30 #include "drv_hdmi_compatibility.h"
31 #include "hi_defines.h"
32 #ifdef HDMI_CHIP_HI3559AV100
33 /* 59a need vo dither */
34 #include "vou_dev_ext.h"
35 #endif
36 #ifdef CONFIG_HI_PROC_SHOW_SUPPORT
37 #include "drv_hdmi_proc.h"
38 #endif
39 #ifdef CONFIG_DRM_HISI_HISMART
40 #include "drm_hdmi_func_ext.h"
41 #endif
42 
43 static osal_semaphore_t g_hdmi_mutex;
44 
45 hi_char *g_hdmi_reg = NULL;
46 hi_char *g_hdmi_phy = NULL;
47 hi_s32 g_hdmi_irq_timer = -1;
48 
49 #define hdmi_multiple_2p0(x)         ((x) *= 2)
50 #define hdmi_multiple_1p5(x)         ((x) = ((x) * 3) >> 1)
51 #define hdmi_multiple_1p25(x)        ((x) = ((x) * 5) >> 2)
52 #define hdmi_multiple_0p5(x)         ((x) = (x) >> 1)
53 #define MAX_DELAY_TIME_MS            10000
54 #define SCDC_ENABLE_TMDS_CHR_RATE    (600 * 1000000)
55 #define SCDC_DESABLE_TMDS_CHR_RATE   (300 * 1000000)
56 #define SCDC_SCRAMBLE_INTERVAL_RESET 20
57 #define SCDC_SCRAMBLE_TIMEOUT_RESET  200
58 #define DEV_HPD_ASSERT_WAIT_TIME     50
59 #define HDMI_THREAD_STATE_WAIT_TIME  90
60 #define HDMI_THREAD_DELAY            10
61 #define HDMI_DEV_FMT_DELAY           500
62 #define HDMI_DEV_MUTE_DELAY          120
63 #define HDMI_VIDEO_ATTR_CLK_FS       74250
64 #define ATTR_LOCK_WAIT_TIME          2
65 #define ATTR_LOCK_WAIT_TIMEOUT       5
66 #define HW_PARAM_ARRAY_COUNT         4
67 #define HDMI_READ_HPD_STATUS_DELAY   110
68 
69 #define hdmi_check_open_return(state)           \
70     do {                                        \
71         if (!((state) & HDMI_RUN_STATE_OPEN)) { \
72             hdmi_warn("device not open\n");     \
73             return HI_ERR_HDMI_DEV_NOT_OPEN;    \
74         }                                       \
75     } while (0)
76 
77 static osal_dev_t *g_hdmi_device = HI_NULL;
78 static osal_atomic_t g_hdmi_count = OSAL_ATOMIC_INIT(0);
79 static hi_s32 hdmi_file_open(void *private_data);
80 static hi_s32 hdmi_file_close(void *private_data);
81 static hi_s32 hdmi_release(hdmi_device *hdmi_dev);
82 static hi_s32 hdmi_video_path_set(hdmi_device *hdmi_dev, hdmi_vo_attr *vo_attr);
83 static hi_s32 hdmi_event_callback(hi_void *data, hdmi_event event);
84 static hi_bool vo_attr_is_changed(const hdmi_vo_attr *hw_vo_attr, hdmi_vo_attr *sw_vo_attr);
85 static hi_bool app_attr_is_changed(const hdmi_app_attr *hw_app_attr, const hdmi_app_attr *sw_app_attr);
86 static hi_void drv_hdmi_black_data_set(const hdmi_device *hdmi_dev, hi_bool enable);
87 #ifdef HDMI_HDR_SUPPORT
88 static hi_void hdmi_zero_drm_infoframe_timer_set(hdmi_device *hdmi_dev, hdmi_timer_config *timer);
89 static hi_void hdmi_zero_drm_infoframe_stop(hdmi_device *hdmi_dev);
90 static hi_void hdmi_hdr_mode_change_timer_set(const hdmi_device *hdmi_dev, hdmi_timer_config *timer);
91 static hi_void hdmi_zero_drm_infoframe_stop(hdmi_device *hdmi_dev);
92 static hi_s32 hdmi_hdr_mode_change_timeout(const hdmi_device *hdmi_dev);
93 hi_s32 hi_drv_hdmi_set_hdr_attr(hdmi_dev_id hdmi, const hdmi_hdr_attr *hdr_attr);
94 #endif
95 
96 static hdmi_device g_hdmi_ctrl[HDMI_DEVICE_ID_BUTT];
97 
98 typedef struct {
99     hi_u32 cmd;
100     hi_s32 (*hdmi_ioctrl_func)(hi_void *arg, hi_bool user);
101 } hdmi_ioctrl_func;
102 
hdmi_set_reg(hi_char * reg)103 hi_void hdmi_set_reg(hi_char *reg)
104 {
105     g_hdmi_reg = reg;
106 }
107 
hdmi_set_phy(hi_char * phy)108 hi_void hdmi_set_phy(hi_char *phy)
109 {
110     g_hdmi_phy = phy;
111 }
112 
hdmi_set_init_irq(hi_s32 hdmi_irq_timer)113 hi_void hdmi_set_init_irq(hi_s32 hdmi_irq_timer)
114 {
115     g_hdmi_irq_timer = hdmi_irq_timer;
116 }
117 
get_global_hdmi_irq_timer(hi_void)118 hi_s32 get_global_hdmi_irq_timer(hi_void)
119 {
120     return g_hdmi_irq_timer;
121 }
122 
get_hdmi_device(hdmi_device_id hdmi_id)123 hdmi_device *get_hdmi_device(hdmi_device_id hdmi_id)
124 {
125     if (hdmi_id < HDMI_DEVICE_ID_BUTT) {
126         g_hdmi_ctrl[hdmi_id].hdmi_dev_id = hdmi_id;
127         return &g_hdmi_ctrl[hdmi_id];
128     }
129     return HI_NULL;
130 }
131 
hdmi_capability_inter_section(hdmi_sink_capability * dest_cap,const hdmi_tx_capability_data * tx_cap,hi_bool auth_mode)132 static hi_s32 hdmi_capability_inter_section(hdmi_sink_capability *dest_cap,
133                                             const hdmi_tx_capability_data *tx_cap, hi_bool auth_mode)
134 {
135     dest_cap->support_hdmi = dest_cap->support_hdmi && tx_cap->tx_hdmi_14;
136     dest_cap->support_hdmi_20 = dest_cap->support_hdmi_20 && tx_cap->tx_hdmi_20;
137     dest_cap->support_scdc = dest_cap->support_scdc && tx_cap->tx_scdc;
138     dest_cap->color_space.rgb444 = dest_cap->color_space.rgb444 && tx_cap->tx_rgb444;
139     dest_cap->color_space.ycbcr444 = dest_cap->color_space.ycbcr444 && tx_cap->tx_ycbcr444;
140     dest_cap->color_space.ycbcr422 = dest_cap->color_space.ycbcr422 && tx_cap->tx_ycbcr422;
141     dest_cap->color_space.ycbcr420 = (dest_cap->color_space.ycbcr420 && tx_cap->tx_ycbcr420) || auth_mode;
142     dest_cap->deep_color.deep_color30_bit = dest_cap->deep_color.deep_color30_bit && tx_cap->tx_deep_clr10_bit;
143     dest_cap->deep_color.deep_color36_bit = dest_cap->deep_color.deep_color36_bit && tx_cap->tx_deep_clr12_bit;
144     dest_cap->deep_color.deep_color48_bit = dest_cap->deep_color.deep_color48_bit && tx_cap->tx_deep_clr16_bit;
145     dest_cap->deep_color_y420.deep_color30_bit = (dest_cap->deep_color_y420.deep_color30_bit &&
146         (tx_cap->tx_ycbcr420 && tx_cap->tx_deep_clr10_bit)) || auth_mode;
147     dest_cap->deep_color_y420.deep_color36_bit = (dest_cap->deep_color_y420.deep_color36_bit &&
148         (tx_cap->tx_ycbcr420 && tx_cap->tx_deep_clr12_bit)) || auth_mode;
149     dest_cap->deep_color_y420.deep_color48_bit = (dest_cap->deep_color_y420.deep_color48_bit &&
150         (tx_cap->tx_ycbcr420 && tx_cap->tx_deep_clr16_bit)) || auth_mode;
151     dest_cap->max_tmds_clock = dest_cap->max_tmds_clock < tx_cap->tx_max_tmds_clk ? dest_cap->max_tmds_clock :
152         tx_cap->tx_max_tmds_clk;
153     dest_cap->hdcp_support.hdcp14_support = dest_cap->hdcp_support.hdcp14_support && tx_cap->tx_hdcp_14;
154     dest_cap->hdcp_support.hdcp22_support = dest_cap->hdcp_support.hdcp22_support && tx_cap->tx_hdcp_22;
155 
156     return HI_SUCCESS;
157 }
158 
hdmi_phy_output_enable(const hdmi_device * hdmi_dev,hi_bool phy_output_enable)159 static hi_void hdmi_phy_output_enable(const hdmi_device *hdmi_dev, hi_bool phy_output_enable)
160 {
161     hal_call_void(hal_hdmi_phy_output_enable_set, hdmi_dev->hal, phy_output_enable);
162     return;
163 }
164 
165 #if !defined(HDMI_SUPPORT_LOGIC_HISIV100) && defined(HDMI_SCDC_SUPPORT)
hdmi_scramble_enable_set(const hdmi_device * hdmi_dev,hi_bool enable)166 static hi_s32 hdmi_scramble_enable_set(const hdmi_device *hdmi_dev, hi_bool enable)
167 {
168     hdmi_scdc_config scdc_config = {0};
169     hdmi_scdc_status scdc_status = {0};
170 
171     hal_call_void(hal_hdmi_scdc_status_get, hdmi_dev->hal, &scdc_status);
172 
173     if ((scdc_status.source_scramble_on && scdc_status.sink_scramble_on &&
174         scdc_status.tmds_bit_clk_ratio == SCDC_TMDS_BIT_CLK_RATIO_40X && enable) ||
175         (!scdc_status.source_scramble_on && !scdc_status.sink_scramble_on &&
176         scdc_status.tmds_bit_clk_ratio == SCDC_TMDS_BIT_CLK_RATIO_10X && !enable)) {
177         hdmi_info("scramble status is not change, so no need to config scramble\n");
178         return HI_SUCCESS;
179     }
180     hdmi_info("source_scramble_on:%u, sink_scramble_on:%u, tmds_bit_clk_ratio:%u\n",
181         scdc_status.source_scramble_on, scdc_status.sink_scramble_on, scdc_status.tmds_bit_clk_ratio);
182     scdc_config.scdc_enable = enable;
183 
184     if (enable) {
185         scdc_config.max_tmds_character_rate = SCDC_ENABLE_TMDS_CHR_RATE;
186     } else {
187         scdc_config.max_tmds_character_rate = SCDC_DESABLE_TMDS_CHR_RATE;
188     }
189 
190     scdc_config.scdc_present         = HI_TRUE;
191     scdc_config.rr_capable           = HI_FALSE;
192     scdc_config.lte340_mcsc_scramble = HI_FALSE;
193     hdmi_phy_output_enable(hdmi_dev, HI_FALSE);
194     hdmi_info("scdc_enable:%u\n", scdc_config.scdc_enable);
195     hdmi_info("scdc config: scdc_present(%u), rr_capable(%u), lte340_mcsc_scramble(%u), max_tmds_character_rate(%u)\n",
196               scdc_config.scdc_present, scdc_config.rr_capable,
197               scdc_config.lte340_mcsc_scramble, scdc_config.max_tmds_character_rate);
198     hal_call_void(hal_hdmi_video_mute_set, hdmi_dev->hal, HI_TRUE);
199     hal_call_void(hal_hdmi_scdc_config, hdmi_dev->hal, &scdc_config);
200     hal_call_void(hal_hdmi_video_mute_set, hdmi_dev->hal, HI_FALSE);
201 
202     return HI_SUCCESS;
203 }
204 #endif
205 
hdmi_ycbcr420_fmt_check(hdmi_device * hdmi_dev)206 static hi_bool hdmi_ycbcr420_fmt_check(hdmi_device *hdmi_dev)
207 {
208     hi_u32                i;
209     hdmi_video_code_vic   vic;
210     hi_bool               search_out = HI_FALSE;
211     hdmi_vo_attr         *vo_attr    = HI_NULL;
212     hdmi_sink_capability *sink_cap   = HI_NULL;
213 
214     /* auth mode donot do cb_cr420_fmt_check and return HI_TRUE */
215     if (hdmi_dev->attr.app_attr.auth_mode == HI_TRUE) {
216         hdmi_info("auth_mode: %u \n", hdmi_dev->attr.app_attr.auth_mode);
217         return HI_TRUE;
218     }
219     vo_attr = &hdmi_dev->attr.vo_attr;
220     if (drv_hdmi_edid_capability_get(&hdmi_dev->edid_info, &sink_cap) == HDMI_EDID_DATA_INVALID) {
221         hdmi_warn("get sink capability fail\n");
222     }
223     vic = drv_hdmi_vic_search(vo_attr->video_timing, vo_attr->picture_aspect, HI_FALSE);
224     if (vic != 0) {
225         for (i = 0;
226              i < sink_cap->support_y420_vic_num && i < hdmi_array_size(sink_cap->support_y420_format);
227              i++) {
228             if (vic == sink_cap->support_y420_format[i]) {
229                 search_out = HI_TRUE;
230                 break;
231             }
232         }
233         for (i = 0;
234              (!search_out) &&
235              i < sink_cap->only_support_y420_vic_num &&
236              i < hdmi_array_size(sink_cap->only_support_y420_format);
237              i++) {
238             if (vic == sink_cap->only_support_y420_format[i]) {
239                 search_out = HI_TRUE;
240                 break;
241             }
242         }
243     }
244     hdmi_info("is Y420 support vic=%u :%s\n", vic, search_out ? "YES" : "NO");
245 
246     return search_out;
247 }
248 
hdmi_color_space_check(hdmi_device * hdmi_dev,hdmi_app_attr * user_app)249 static hi_s32 hdmi_color_space_check(hdmi_device *hdmi_dev, hdmi_app_attr *user_app)
250 {
251     hdmi_tx_capability_data tx_cap            = {0};
252     hi_bool                 support_clr_space = HI_FALSE;
253     hdmi_sink_capability   *sink_cap          = HI_NULL;
254 
255     hal_call_void(hal_hdmi_tx_capability_get, hdmi_dev->hal, &tx_cap);
256     if (drv_hdmi_edid_capability_get(&hdmi_dev->edid_info, &sink_cap) == HDMI_EDID_DATA_INVALID) {
257         hdmi_warn("get sink capability fail\n");
258     }
259 
260     switch (user_app->out_color_space) {
261         case HDMI_COLORSPACE_RGB:
262             support_clr_space = HI_TRUE;
263             if (!(sink_cap->color_space.rgb444 && tx_cap.tx_rgb444)) {
264                 hdmi_warn("sink or source not support RGB!\n");
265             }
266             break;
267         case HDMI_COLORSPACE_YCBCR422:
268             support_clr_space = sink_cap->color_space.ycbcr422 && tx_cap.tx_ycbcr422;
269             break;
270         case HDMI_COLORSPACE_YCBCR444:
271             support_clr_space = sink_cap->color_space.ycbcr444 && tx_cap.tx_ycbcr444;
272             break;
273         case HDMI_COLORSPACE_YCBCR420:
274             support_clr_space = tx_cap.tx_ycbcr420 && hdmi_ycbcr420_fmt_check(hdmi_dev);
275             break;
276         default:
277             hdmi_err("un-know color_space=%u!\n", user_app->out_color_space);
278             return HI_FAILURE;
279             break;
280     }
281 
282     if (!support_clr_space) {
283 #if defined(CONFIG_HI_PLATFORM_H8)
284         hdmi_err("fail, not support color space:%u\n", user_app->out_color_space);
285         return HI_FAILURE;
286 #else
287         if (user_app->enable_clr_space_adapt) {
288             hdmi_warn("fail,clr(%u) adapt to RGB!\n", user_app->out_color_space);
289             user_app->out_color_space = HDMI_COLORSPACE_RGB;
290         } else {
291             hdmi_err("fail,adapt clrspace fail!\n");
292             return HI_FAILURE;
293         }
294 #endif
295     }
296 
297     return HI_SUCCESS;
298 }
299 
check_deep_color_10bit(const hdmi_sink_capability * sink_cap,const hdmi_app_attr * user_app,const hdmi_tx_capability_data * tx_cap,hi_u32 * fmt_pix_clk,hi_bool * support_deep_clr)300 static hi_void check_deep_color_10bit(const hdmi_sink_capability *sink_cap, const hdmi_app_attr *user_app,
301     const hdmi_tx_capability_data *tx_cap, hi_u32 *fmt_pix_clk, hi_bool *support_deep_clr)
302 {
303     hi_u32 pix_clk;
304 
305     hdmi_if_null_return_void(sink_cap);
306     hdmi_if_null_return_void(user_app);
307     hdmi_if_null_return_void(tx_cap);
308     hdmi_if_null_return_void(fmt_pix_clk);
309     hdmi_if_null_return_void(support_deep_clr);
310 
311     pix_clk = *fmt_pix_clk;
312 
313     switch (user_app->out_color_space) {
314         case HDMI_COLORSPACE_RGB:
315             hdmi_multiple_1p25(pix_clk);
316             *support_deep_clr = (sink_cap->deep_color.deep_color30_bit &&
317                 tx_cap->tx_deep_clr10_bit) ? HI_TRUE : HI_FALSE;
318             break;
319         case HDMI_COLORSPACE_YCBCR444:
320             hdmi_multiple_1p25(pix_clk);
321             *support_deep_clr = (sink_cap->deep_color.deep_color30_bit && tx_cap->tx_deep_clr10_bit &&
322                 sink_cap->deep_color.deep_color_y444) ? HI_TRUE : HI_FALSE;
323             break;
324         case HDMI_COLORSPACE_YCBCR420:
325             hdmi_multiple_1p25(pix_clk);
326             *support_deep_clr = (sink_cap->deep_color_y420.deep_color30_bit &&
327                 tx_cap->tx_deep_clr10_bit) ? HI_TRUE : HI_FALSE;
328             break;
329         default:
330             /* Y422, ignore deepclr */
331             *support_deep_clr = HI_TRUE;
332             break;
333     }
334     *fmt_pix_clk = pix_clk;
335 
336     return;
337 }
338 
check_deep_color_12bit(const hdmi_sink_capability * sink_cap,const hdmi_app_attr * user_app,const hdmi_tx_capability_data * tx_cap,hi_u32 * fmt_pix_clk,hi_bool * support_deep_clr)339 static hi_void check_deep_color_12bit(const hdmi_sink_capability *sink_cap, const hdmi_app_attr *user_app,
340     const hdmi_tx_capability_data *tx_cap, hi_u32 *fmt_pix_clk, hi_bool *support_deep_clr)
341 {
342     hi_u32 pix_clk;
343 
344     hdmi_if_null_return_void(sink_cap);
345     hdmi_if_null_return_void(user_app);
346     hdmi_if_null_return_void(tx_cap);
347     hdmi_if_null_return_void(fmt_pix_clk);
348     hdmi_if_null_return_void(support_deep_clr);
349 
350     pix_clk = *fmt_pix_clk;
351 
352     switch (user_app->out_color_space) {
353         case HDMI_COLORSPACE_RGB:
354             hdmi_multiple_1p5(pix_clk);
355             *support_deep_clr = (sink_cap->deep_color.deep_color36_bit &&
356                 tx_cap->tx_deep_clr12_bit) ? HI_TRUE : HI_FALSE;
357             break;
358         case HDMI_COLORSPACE_YCBCR444:
359             hdmi_multiple_1p5(pix_clk);
360             *support_deep_clr = (sink_cap->deep_color.deep_color36_bit && tx_cap->tx_deep_clr12_bit &&
361                 sink_cap->deep_color.deep_color_y444) ? HI_TRUE : HI_FALSE;
362             break;
363         case HDMI_COLORSPACE_YCBCR420:
364             hdmi_multiple_1p5(pix_clk);
365             *support_deep_clr = (sink_cap->deep_color_y420.deep_color36_bit &&
366                 tx_cap->tx_deep_clr12_bit) ? HI_TRUE : HI_FALSE;
367             break;
368         default:
369             /* Y422, ignore deepclr */
370             *support_deep_clr = HI_TRUE;
371             break;
372     }
373     *fmt_pix_clk = pix_clk;
374 
375     return;
376 }
377 
hdmi_current_id_get(const hdmi_device * hdmi_dev)378 static hi_u32 hdmi_current_id_get(const hdmi_device *hdmi_dev)
379 {
380     hi_u32 id;
381 #ifdef HDMI_LITEOS_SUPPORT
382     hi_u32 total = 0;
383 #endif
384     id = hdmi_get_current_id();
385 
386 #ifdef HDMI_LITEOS_SUPPORT
387     /*
388      * lite_os only support thread, each thread id is different(such as sample and HDMI poll event thread).
389      * so return pool[0]'s ID when get current ID.
390      */
391     drv_hdmi_event_pool_total_get(hdmi_dev->hdmi_dev_id, &total);
392     if (total > 0) {
393         drv_hdmi_event_pool_id_get(hdmi_dev->hdmi_dev_id, &id);
394     }
395 #else
396     hi_unused(hdmi_dev);
397 #endif
398 
399     return id;
400 }
401 
check_deep_color(const hdmi_sink_capability * sink_cap,hdmi_app_attr * user_app,const hdmi_tx_capability_data * tx_cap,hi_u32 * fmt_pix_clk,hi_bool * support_deep_clr)402 static hi_void check_deep_color(const hdmi_sink_capability *sink_cap, hdmi_app_attr *user_app,
403     const hdmi_tx_capability_data *tx_cap, hi_u32 *fmt_pix_clk, hi_bool *support_deep_clr)
404 {
405     switch (user_app->deep_color_mode) {
406         case HDMI_DEEP_COLOR_30BIT:
407             check_deep_color_10bit(sink_cap, user_app, tx_cap, fmt_pix_clk, support_deep_clr);
408             break;
409         case HDMI_DEEP_COLOR_36BIT:
410             check_deep_color_12bit(sink_cap, user_app, tx_cap, fmt_pix_clk, support_deep_clr);
411             break;
412         default:
413 #ifndef HDMI_SUPPORT_LOGIC_HISIV100
414             user_app->deep_color_mode = HDMI_DEEP_COLOR_24BIT;
415 #endif
416             *support_deep_clr = HI_TRUE;
417             break;
418     }
419 
420     return;
421 }
422 
hdmi_deep_color_check(hdmi_device * hdmi_dev,hdmi_app_attr * user_app,hi_u32 max_tmds_clk)423 static hi_s32 hdmi_deep_color_check(hdmi_device *hdmi_dev, hdmi_app_attr *user_app, hi_u32 max_tmds_clk)
424 {
425     hi_u32                  fmt_pix_clk;
426     hdmi_vo_attr           *vo_attr          = HI_NULL;
427     hdmi_sink_capability   *sink_cap         = HI_NULL;
428     hdmi_tx_capability_data tx_cap           = {0};
429     hi_bool                 adapt_to_y422    = HI_FALSE;
430     hi_bool                 support_deep_clr = HI_FALSE;
431 
432     hdmi_if_null_return(hdmi_dev->hal, HI_ERR_NULL_PTR);
433 
434     vo_attr = &hdmi_dev->attr.vo_attr;
435     hdmi_dev->hal->hal_hdmi_tx_capability_get(hdmi_dev->hal, &tx_cap);
436     if (drv_hdmi_edid_capability_get(&hdmi_dev->edid_info, &sink_cap) == HDMI_EDID_DATA_INVALID) {
437         hdmi_warn("get sink capability fail\n");
438     }
439 
440     fmt_pix_clk = vo_attr->clk_fs;
441     if (user_app->out_color_space == HDMI_COLORSPACE_YCBCR420) {
442         hdmi_multiple_0p5(fmt_pix_clk);
443     }
444     check_deep_color(sink_cap, user_app, &tx_cap, &fmt_pix_clk, &support_deep_clr);
445 
446     if (support_deep_clr && (fmt_pix_clk < max_tmds_clk)) {
447         vo_attr->hdmi_adapt_pix_clk = fmt_pix_clk;
448         return HI_SUCCESS;
449     } else {
450         vo_attr->hdmi_adapt_pix_clk = vo_attr->clk_fs;
451         if (user_app->out_color_space == HDMI_COLORSPACE_YCBCR420) {
452             hdmi_multiple_0p5(vo_attr->hdmi_adapt_pix_clk);
453         }
454 
455         adapt_to_y422 = ((user_app->out_color_space == HDMI_COLORSPACE_YCBCR444) &&
456                          (user_app->enable_clr_space_adapt) &&
457                          (user_app->deep_color_mode != HDMI_DEEP_COLOR_24BIT) &&
458                          (user_app->deep_color_mode != HDMI_DEEP_COLOR_OFF) &&
459                          (user_app->deep_color_mode != HDMI_DEEP_COLOR_48BIT) &&
460                          (sink_cap->color_space.ycbcr422 && tx_cap.tx_ycbcr422));
461 
462         /* Y444 12/10bit */
463         if (adapt_to_y422) {
464             hdmi_warn("fail, Y444 adapt to Y422!\n");
465             user_app->out_color_space = HDMI_COLORSPACE_YCBCR422;
466         } else if (user_app->enable_deep_clr_adapt) { /* Y444 16bit/ RGB / Y420 */
467             hdmi_warn("fail, deepclr(%u) adapt to 8bit!\n", user_app->deep_color_mode);
468             user_app->deep_color_mode = HDMI_DEEP_COLOR_24BIT;
469         } else {
470             hdmi_err("fail, adapt deepclr fail!\n");
471             return HI_FAILURE;
472         }
473 
474         return HI_SUCCESS;
475     }
476 }
477 
adapt_to_420(const hdmi_vo_attr * vo_attr,hdmi_app_attr * user_app,hi_u32 max_tmds_clk)478 static hi_s32 adapt_to_420(const hdmi_vo_attr *vo_attr, hdmi_app_attr *user_app, hi_u32 max_tmds_clk)
479 {
480     if (vo_attr->clk_fs <= max_tmds_clk) {
481         return HI_SUCCESS;
482     }
483 
484     hdmi_warn("pix_clk(%u) > max_tmds_clk(%u)\n", vo_attr->clk_fs, max_tmds_clk);
485     // add user_app->out_color_space to avoid set yuv420 failed after the timing set success
486 #if defined(CONFIG_HI_PLATFORM_H8)
487     /* in h8, hdmi can adapt to yuv420 just in yuv444 */
488     if (user_app->out_color_space == HDMI_COLORSPACE_YCBCR444) {
489 #else
490     if (user_app->out_color_space != HDMI_COLORSPACE_YCBCR420) {
491 #endif
492         if (user_app->enable_clr_space_adapt) {
493             hdmi_warn("clr(%u) adapt to Y420 or user clr is Y420!\n", user_app->out_color_space);
494             user_app->out_color_space = HDMI_COLORSPACE_YCBCR420;
495         } else {
496             hdmi_err("adapt Y420 fail!\n");
497             return HI_FAILURE;
498         }
499     }
500 
501     return HI_SUCCESS;
502 }
503 
504 #ifdef HDMI_FRL_SUPPORT
505 static hi_void tmds_clk_calc(hdmi_device *hdmi_dev, const hdmi_app_attr *user_app)
506 {
507     hdmi_vo_attr *vo_attr = HI_NULL;
508 
509     vo_attr = &hdmi_dev->attr.vo_attr;
510     vo_attr->tmds_clk =
511         (user_app->out_color_space == HDMI_COLORSPACE_YCBCR420) ? (vo_attr->clk_fs >> 1) : vo_attr->clk_fs;
512 
513     if (user_app->out_color_space != HDMI_COLORSPACE_YCBCR422) {
514         switch (user_app->deep_color_mode) {
515             case HDMI_DEEP_COLOR_48BIT:
516                 hdmi_multiple_2p0(vo_attr->tmds_clk);
517                 break;
518             case HDMI_DEEP_COLOR_36BIT:
519                 hdmi_multiple_1p5(vo_attr->tmds_clk);
520                 break;
521             case HDMI_DEEP_COLOR_30BIT:
522                 hdmi_multiple_1p25(vo_attr->tmds_clk);
523                 break;
524             default:
525                 break;
526         }
527     }
528 
529     return;
530 }
531 #endif
532 
533 static hi_void edid_invalid_or_auth_mode(hdmi_device *hdmi_dev, hdmi_app_attr *user_app)
534 {
535     hdmi_vo_attr *vo_attr = HI_NULL;
536 
537     vo_attr = &hdmi_dev->attr.vo_attr;
538     vo_attr->hdmi_adapt_pix_clk =
539         (user_app->out_color_space == HDMI_COLORSPACE_YCBCR420) ? (vo_attr->clk_fs >> 1) : vo_attr->clk_fs;
540 
541     if (user_app->out_color_space != HDMI_COLORSPACE_YCBCR422) {
542         switch (user_app->deep_color_mode) {
543             case HDMI_DEEP_COLOR_48BIT:
544                 hdmi_multiple_2p0(vo_attr->hdmi_adapt_pix_clk);
545                 break;
546             case HDMI_DEEP_COLOR_36BIT:
547                 hdmi_multiple_1p5(vo_attr->hdmi_adapt_pix_clk);
548                 break;
549             case HDMI_DEEP_COLOR_30BIT:
550                 hdmi_multiple_1p25(vo_attr->hdmi_adapt_pix_clk);
551                 break;
552             default:
553                 break;
554         }
555     } else {
556         if ((user_app->deep_color_mode != HDMI_DEEP_COLOR_OFF) &&
557             (user_app->deep_color_mode != HDMI_DEEP_COLOR_24BIT)) {
558             hdmi_info("Y422 foce deepcolor 8bit");
559             user_app->deep_color_mode = HDMI_DEEP_COLOR_24BIT;
560         }
561         if (hdmi_dev->attr.vo_attr.video_timing == HDMI_VIDEO_TIMING_1440X480I_60000 ||
562             hdmi_dev->attr.vo_attr.video_timing == HDMI_VIDEO_TIMING_1440X576I_50000) {
563             hdmi_warn("Y422 is not support at pal and ntsc, force adapt to rgb!\n");
564             user_app->out_color_space = HDMI_COLORSPACE_RGB;
565         }
566     }
567 
568     return;
569 }
570 
571 static hi_s32 dvi_color_and_bit_strategy(hdmi_device *hdmi_dev, hdmi_app_attr *user_app)
572 {
573     hdmi_vo_attr *vo_attr = HI_NULL;
574 
575     vo_attr = &hdmi_dev->attr.vo_attr;
576 #if (defined(CONFIG_HI_PLATFORM_H8))
577     if (user_app->out_color_space != HDMI_COLORSPACE_RGB) {
578         hdmi_err("DVI mode, but the color space is not RGB!");
579         return HI_FAILURE;
580     }
581 #else
582     hdmi_info("DVI mode, force deep_color %u -> OFF, color_space %u -> RGB!\n",
583               user_app->deep_color_mode, user_app->out_color_space);
584     user_app->out_color_space = HDMI_COLORSPACE_RGB;
585 #endif
586     user_app->deep_color_mode = HDMI_DEEP_COLOR_OFF;
587     vo_attr->hdmi_adapt_pix_clk = vo_attr->clk_fs;
588 
589     return HI_SUCCESS;
590 }
591 
592 static hi_s32 hdmi_deep_color_adapt(const hdmi_device *hdmi_dev, hdmi_app_attr *user_app)
593 {
594     /* Y422 default 12bit output, deep_color force adapt to 8bit(24bit). */
595     if (user_app->out_color_space == HDMI_COLORSPACE_YCBCR422) {
596         if (hdmi_dev->attr.vo_attr.video_timing == HDMI_VIDEO_TIMING_1440X480I_60000 ||
597             hdmi_dev->attr.vo_attr.video_timing == HDMI_VIDEO_TIMING_1440X576I_50000) {
598 #if defined(CONFIG_HI_PLATFORM_H8)
599             hdmi_err("Y422 is not support at pal and ntsc!\n");
600             return HI_FAILURE;
601 #else
602             hdmi_warn("Y422 is not support at pal and ntsc!\n");
603             if (user_app->enable_clr_space_adapt != HI_TRUE) {
604                 return HI_FAILURE;
605             } else {
606                 hdmi_warn("force change colorspace to RGB!\n");
607                 user_app->out_color_space = HDMI_COLORSPACE_RGB;
608             }
609 #endif
610         }
611         if ((user_app->deep_color_mode != HDMI_DEEP_COLOR_24BIT) &&
612             (user_app->deep_color_mode != HDMI_DEEP_COLOR_OFF)) {
613             user_app->deep_color_mode = HDMI_DEEP_COLOR_OFF;
614             hdmi_warn("when Y422, deep_color not support 10/12bit!\n");
615         }
616     }
617 
618     return HI_SUCCESS;
619 }
620 
621 static hi_s32 hdmi_color_and_bit_strategy(hdmi_device *hdmi_dev, hdmi_app_attr *user_app)
622 {
623     hi_s32                  ret;
624     hdmi_edid_data          edid_ret;
625     hi_u32                  max_tmds_clk = 0;
626     hdmi_vo_attr           *vo_attr      = HI_NULL;
627     hdmi_sink_capability   *sink_cap     = HI_NULL;
628     hdmi_tx_capability_data tx_cap       = {0};
629 
630     vo_attr = &hdmi_dev->attr.vo_attr;
631     /* DVI mode, must set RGB & deep_color off */
632     if (!user_app->enable_hdmi) {
633         return dvi_color_and_bit_strategy(hdmi_dev, user_app);
634     }
635 #ifdef HDMI_FRL_SUPPORT
636     tmds_clk_calc(hdmi_dev, user_app);
637     if (vo_attr->tmds_clk > HDMI_EDID_MAX_HDMI20_TMDS_RATE) {
638         vo_attr->hdmi_adapt_pix_clk = vo_attr->tmds_clk;
639         hdmi_warn("HDMI2.1 no hdmi adapt hdmi_adapt_pix_clk=%u\n", vo_attr->hdmi_adapt_pix_clk);
640         return HI_SUCCESS;
641     }
642 #endif
643     hal_call_void(hal_hdmi_tx_capability_get, hdmi_dev->hal, &tx_cap);
644     edid_ret = drv_hdmi_edid_capability_get(&hdmi_dev->edid_info, &sink_cap);
645     if (edid_ret == HDMI_EDID_DATA_INVALID || (user_app->auth_mode == HI_TRUE)) {
646         edid_invalid_or_auth_mode(hdmi_dev, user_app);
647         /* get edid_capability fail means cannot do strategy, according to appatrr */
648         hdmi_warn("get sink capability fail or auth_mode=%u, adapt hdmi_adapt_pix_clk=%u\n",
649                   hdmi_dev->attr.app_attr.auth_mode, vo_attr->hdmi_adapt_pix_clk);
650         return HI_SUCCESS;
651     } else {
652         /* get max_tmds_clk, in k_hz. */
653         if (sink_cap->max_tmds_clock == 0) {
654             /*
655              * but when the sink's max_tmds_clock is 0_m_hz, app can not set attr success.
656              * then set max_tmds_clk = 300M default.
657              */
658             max_tmds_clk = 300;
659         } else {
660             max_tmds_clk =
661                 sink_cap->max_tmds_clock < tx_cap.tx_max_tmds_clk ? sink_cap->max_tmds_clock : tx_cap.tx_max_tmds_clk;
662         }
663         max_tmds_clk *= 1000; /* k_hz*1000, M_hz */
664     }
665     /* whether adapt to ycbcr420 */
666     ret = adapt_to_420(vo_attr, user_app, max_tmds_clk);
667     hdmi_if_failure_return(ret, HI_FAILURE);
668     /* color_space check & adapt */
669     ret = hdmi_color_space_check(hdmi_dev, user_app);
670     hdmi_if_failure_return(ret, HI_FAILURE);
671     /* deep_color check & adapt */
672     ret = hdmi_deep_color_check(hdmi_dev, user_app, max_tmds_clk);
673     hdmi_if_failure_return(ret, HI_FAILURE);
674     /* deep color adapt */
675     ret = hdmi_deep_color_adapt(hdmi_dev, user_app);
676     hdmi_if_failure_return(ret, HI_FAILURE);
677     hdmi_info("clr_space_adapt=%u, deep_clr_adapt=%u, adptclrspace=%u, adptbit=%u, adptclk=%u, max_clk=%u\n",
678               user_app->enable_clr_space_adapt, user_app->enable_deep_clr_adapt, user_app->out_color_space,
679               user_app->deep_color_mode, vo_attr->hdmi_adapt_pix_clk, max_tmds_clk);
680 
681     return HI_SUCCESS;
682 }
683 
684 #ifdef HDMI_SCDC_SUPPORT
685 static hi_s32 hdmi_scdc_status_get(const hdmi_app_attr *app_attr, const hdmi_vo_attr *vo_attr,
686                                    hdmi_scdc_status *scdc_status, hdmi_tmds_mode *tmds_mode)
687 {
688     if (!app_attr->enable_hdmi) {
689         /* DVI mode */
690         *tmds_mode = HDMI_TMDS_MODE_DVI;
691         scdc_status->sink_scramble_on   = HI_FALSE;
692         scdc_status->source_scramble_on = HI_FALSE;
693         scdc_status->tmds_bit_clk_ratio = SCDC_TMDS_BIT_CLK_RATIO_10X;
694         if ((vo_attr->hdmi_adapt_pix_clk > HDMI_EDID_MAX_HDMI14_TMDS_RATE) && (!app_attr->enable_clr_space_adapt)) {
695             hdmi_err("tmds_clk=%u can't support in DVI mode. \n", vo_attr->hdmi_adapt_pix_clk);
696             return HI_FAILURE;
697         }
698     } else if (vo_attr->hdmi_adapt_pix_clk > HDMI_EDID_MAX_HDMI14_TMDS_RATE) {
699         *tmds_mode = HDMI_TMDS_MODE_HDMI_2_0;
700         scdc_status->sink_scramble_on   = HI_TRUE;
701         scdc_status->source_scramble_on = HI_TRUE;
702         scdc_status->tmds_bit_clk_ratio = SCDC_TMDS_BIT_CLK_RATIO_40X;
703     } else {
704         *tmds_mode = HDMI_TMDS_MODE_HDMI_1_4;
705         scdc_status->sink_scramble_on   = HI_FALSE;
706         scdc_status->source_scramble_on = HI_FALSE;
707         scdc_status->tmds_bit_clk_ratio = SCDC_TMDS_BIT_CLK_RATIO_10X;
708     }
709 
710     return HI_SUCCESS;
711 }
712 #endif
713 
714 #if defined HDMI_SUPPORT_LOGIC_HISIV100
715 hi_s32 hdmi_mode_strategy(hdmi_device *hdmi_dev)
716 {
717     hdmi_tmds_mode tmds_mode;
718     hdmi_app_attr *app_attr = HI_NULL;
719 #ifdef HDMI_SCDC_SUPPORT
720     hdmi_edid_data        edid_ret;
721     hdmi_scdc_status      scdc_get    = {0};
722     hdmi_scdc_status      scdc_status = {0};
723     hdmi_vo_attr         *vo_attr     = HI_NULL;
724     hdmi_sink_capability *sink_cap    = HI_NULL;
725 #endif
726 
727     hdmi_if_null_return(hdmi_dev, HI_ERR_NULL_PTR);
728     app_attr = &hdmi_dev->attr.app_attr;
729     hdmi_if_null_return(app_attr, HI_ERR_NULL_PTR);
730 
731 #ifdef HDMI_SCDC_SUPPORT
732     vo_attr = &hdmi_dev->attr.vo_attr;
733     edid_ret = drv_hdmi_edid_capability_get(&hdmi_dev->edid_info, &sink_cap);
734     if (edid_ret == HDMI_EDID_DATA_INVALID) {
735         hdmi_warn("invalid edid_capability!\n");
736     }
737     if (hdmi_scdc_status_get(app_attr, vo_attr, &scdc_status, &tmds_mode) != HI_SUCCESS) {
738         return HI_FAILURE;
739     }
740 #else
741     tmds_mode = (app_attr->enable_hdmi == HI_TRUE) ? HDMI_TMDS_MODE_HDMI_1_4 : HDMI_TMDS_MODE_DVI;
742 #endif
743 
744     hdmi_info("tmds mode %u->%u.\n", hdmi_dev->tmds_mode, tmds_mode);
745     hdmi_dev->tmds_mode = tmds_mode;
746     hal_call_void(hal_hdmi_tmds_mode_set, hdmi_dev->hal, hdmi_dev->tmds_mode);
747     /* reset controller when the controller and phy configuration is completed. */
748     hal_call_void(hal_hdmi_ctrl_reset, hdmi_dev->hal);
749 
750 #ifdef HDMI_SCDC_SUPPORT
751     if (sink_cap->support_scdc == HI_TRUE || hdmi_dev->attr.app_attr.auth_mode == HI_TRUE) {
752         hal_call_void(hal_hdmi_scdc_status_get, hdmi_dev->hal, &scdc_get);
753         if ((scdc_get.sink_scramble_on != scdc_status.sink_scramble_on ||
754             scdc_get.source_scramble_on != scdc_status.source_scramble_on ||
755             scdc_get.tmds_bit_clk_ratio != scdc_status.tmds_bit_clk_ratio) ||
756             (hdmi_dev->attr.app_attr.auth_mode == HI_TRUE)) {
757             scdc_status.scramble_interval = SCDC_SCRAMBLE_INTERVAL_RESET;
758             scdc_status.scramble_timeout = SCDC_SCRAMBLE_TIMEOUT_RESET;
759             scdc_status.sink_read_quest = HI_FALSE;
760             hal_call_void(hal_hdmi_scdc_status_set, hdmi_dev->hal, &scdc_status);
761         }
762     } else {
763         hdmi_info("sink not support SCDC\n");
764     }
765 #endif
766 
767     return HI_SUCCESS;
768 }
769 
770 #else
771 hi_s32 hdmi_mode_strategy(hdmi_device *hdmi_dev)
772 {
773     hdmi_vo_attr  *vo_attr  = HI_NULL;
774     hdmi_app_attr *app_attr = HI_NULL;
775     hdmi_tmds_mode tmds_mode;
776 
777     hdmi_if_null_return(hdmi_dev, HI_ERR_NULL_PTR);
778     hdmi_if_null_return(hdmi_dev->hal, HI_ERR_NULL_PTR);
779 
780     vo_attr  = &hdmi_dev->attr.vo_attr;
781     app_attr = &hdmi_dev->attr.app_attr;
782 
783     hdmi_if_null_return(app_attr, HI_ERR_NULL_PTR);
784 
785     if (!app_attr->enable_hdmi) {  // DVI
786         tmds_mode = HDMI_TMDS_MODE_DVI;
787         if (vo_attr->hdmi_adapt_pix_clk > HDMI_EDID_MAX_HDMI14_TMDS_RATE) {
788             if (app_attr->enable_clr_space_adapt) {
789                 app_attr->enable_hdmi = HI_TRUE;
790                 tmds_mode = HDMI_TMDS_MODE_HDMI_2_0;
791                 hdmi_warn("tmds_clk=%u can't support in DVI, adapt to hdmi2.0\n", vo_attr->hdmi_adapt_pix_clk);
792             } else {
793                 hdmi_err("tmds_clk=%u can't support in DVI mode", vo_attr->hdmi_adapt_pix_clk);
794                 return HI_FAILURE;
795             }
796         }
797     } else {  // HDMI
798         tmds_mode = vo_attr->hdmi_adapt_pix_clk < HDMI_EDID_MAX_HDMI14_TMDS_RATE ?
799             HDMI_TMDS_MODE_HDMI_1_4 : HDMI_TMDS_MODE_HDMI_2_0;
800     }
801 
802     hdmi_info("tmds mode %u->%u.\n", hdmi_dev->tmds_mode, tmds_mode);
803     hdmi_dev->tmds_mode = tmds_mode;
804     hal_call_void(hal_hdmi_tmds_mode_set, hdmi_dev->hal, hdmi_dev->tmds_mode);
805 
806 #ifdef HDMI_SCDC_SUPPORT
807     if (hdmi_dev->edid_info.capability.support_scdc == HI_TRUE || hdmi_dev->attr.app_attr.auth_mode == HI_TRUE) {
808         if (hdmi_dev->tmds_mode == HDMI_TMDS_MODE_HDMI_2_0) {
809             hdmi_scramble_enable_set(hdmi_dev, HI_TRUE);
810         } else {
811             hdmi_scramble_enable_set(hdmi_dev, HI_FALSE);
812         }
813     } else {
814         hdmi_info("can't support SCDC \n");
815     }
816 #endif
817 
818     return HI_SUCCESS;
819 }
820 #endif
821 
822 hi_s32 drv_hdmi_init(hi_void)
823 {
824     return HI_SUCCESS;
825 }
826 
827 hi_s32 drv_hdmi_deinit(hi_void)
828 {
829     return HI_SUCCESS;
830 }
831 
832 static hdmi_deep_color depth_convert_to_deep_color(hdmi_video_bit_depth bit_depth)
833 {
834     hdmi_deep_color deep_color;
835 
836     switch (bit_depth) {
837         case HDMI_VIDEO_BITDEPTH_8:
838             deep_color = HDMI_DEEP_COLOR_24BIT;
839             break;
840         case HDMI_VIDEO_BITDEPTH_10:
841             deep_color = HDMI_DEEP_COLOR_30BIT;
842             break;
843         case HDMI_VIDEO_BITDEPTH_12:
844             deep_color = HDMI_DEEP_COLOR_36BIT;
845             break;
846         case HDMI_VIDEO_BITDEPTH_16:
847             deep_color = HDMI_DEEP_COLOR_48BIT;
848             break;
849         case HDMI_VIDEO_BITDEPTH_OFF:
850             deep_color = HDMI_DEEP_COLOR_OFF;
851             break;
852         default:
853             deep_color = HDMI_DEEP_COLOR_BUTT;
854             break;
855     }
856 
857     return deep_color;
858 }
859 
860 static hi_void hdmi_user_attr_construct(hdmi_device *hdmi_dev, hdmi_attr *attr, const hdmi_hardware_status *hw_status)
861 {
862     hdmi_app_attr       *app_attr   = HI_NULL;
863 #ifdef HDMI_HDR_SUPPORT
864     hi_bool is_dolby = HI_FALSE;
865 #endif
866 
867     app_attr   = &attr->app_attr;
868     hdmi_dev->tmds_mode = hw_status->common_status.tmds_mode;
869     switch (hdmi_dev->tmds_mode) {
870         case HDMI_TMDS_MODE_HDMI_1_4:
871         case HDMI_TMDS_MODE_HDMI_2_0:
872             app_attr->enable_hdmi = HI_TRUE;
873             app_attr->enable_video = HI_TRUE;
874             break;
875         case HDMI_TMDS_MODE_DVI:
876             app_attr->enable_hdmi = HI_FALSE;
877             app_attr->enable_video = HI_TRUE;
878             break;
879         default:
880             app_attr->enable_hdmi = HI_FALSE;
881             app_attr->enable_video = HI_FALSE;
882             break;
883     }
884 
885     app_attr->enable_audio = (hw_status->audio_status.audio_enable && hw_status->info_frame_status.audio_enable);
886 #ifdef HDMI_HDR_SUPPORT
887     /* out colorspace is yuv444 when the hdr mode is dolby. */
888     is_dolby = ((hdmi_dev->attr.hdr_attr.user_hdr_mode == HDMI_HDR_USERMODE_DOLBY) &&
889                 ((!hw_status->video_status.rgb2ycbcr) && (!hw_status->video_status.ycbcr2rgb) &&
890                 (!hw_status->video_status.ycbcr444_422) && (!hw_status->video_status.ycbcr422_420) &&
891                 (!hw_status->video_status.ycbcr422_444) && (!hw_status->video_status.ycbcr420_422)));
892     app_attr->out_color_space =
893         (is_dolby == HI_TRUE) ? HDMI_COLORSPACE_YCBCR444 : hw_status->video_status.out_color_space;
894 #else
895     app_attr->out_color_space = hw_status->video_status.out_color_space;
896 #endif
897     app_attr->deep_color_mode      = depth_convert_to_deep_color(hw_status->video_status.out_bit_depth);
898     app_attr->enable_avi_infoframe = hw_status->info_frame_status.avi_enable;
899     app_attr->enable_aud_infoframe = hw_status->info_frame_status.audio_enable;
900     app_attr->xvycc_mode = hw_status->info_frame_status.gbd_enable;
901 
902     return;
903 }
904 
905 static hi_void hdmi_video_attr_construct(hdmi_attr *attr, const hdmi_hardware_status *hw_status)
906 {
907     hdmi_app_attr       *app_attr   = HI_NULL;
908     hdmi_vo_attr        *video_attr = HI_NULL;
909     hi_bool in_clr_is_rgb = HI_FALSE;
910     hi_bool aspect_is256  = HI_FALSE;
911 
912     app_attr   = &attr->app_attr;
913     video_attr = &attr->vo_attr;
914     video_attr->in_color_space = app_attr->out_color_space;
915     video_attr->v_sync_pol     = hw_status->video_status.v_sync_pol;
916     video_attr->h_sync_pol     = hw_status->video_status.h_sync_pol;
917     video_attr->de_pol         = hw_status->video_status.de_pol;
918 
919     in_clr_is_rgb = ((hw_status->video_status.rgb2ycbcr) || ((!hw_status->video_status.ycbcr2rgb) &&
920                      (hw_status->video_status.out_color_space == HDMI_COLORSPACE_RGB)));
921     video_attr->in_color_space = (in_clr_is_rgb == HI_TRUE) ? HDMI_COLORSPACE_RGB : HDMI_COLORSPACE_YCBCR444;
922     if (hw_status->info_frame_status.avi_enable) {
923         hdmi_video_code_vic video_code = hw_status->info_frame_status.avi[7];
924         /*
925          * when the timing is 4096*2160, the aspect ratio in AVI infoframe is 0
926          * (but the real aspect ratio is 256:135<0x04>, the video_code is 0)
927          */
928         aspect_is256 = (((video_code == 0) && (hw_status->info_frame_status.vsif[8] == 0x04)) ||
929                         ((video_code >= HDMI_4096X2160P25_256_135) && (video_code <= HDMI_4096X2160P60_256_135)));
930         video_attr->picture_aspect = (aspect_is256 == HI_TRUE) ?
931             HDMI_PICTURE_ASPECT_256_135 : ((hw_status->info_frame_status.avi[5] >> 4) & 0x3); /* 4'b, BIT[2:1] */
932         video_attr->active_aspect        = hw_status->info_frame_status.avi[5] & 0xf;
933         video_attr->colorimetry          = (hw_status->info_frame_status.avi[5] >> 6) & 0x3; /* 6'b, BIT[2:1] */
934         video_attr->rgb_quantization     = (hw_status->info_frame_status.avi[6] >> 2) & 0x3; /* 2'b, BIT[2:1] */
935         video_attr->ycc_quantization     = (hw_status->info_frame_status.avi[8] >> 6) & 0x3; /* 6'b, BIT[2:1] */
936         video_attr->pixel_repeat         = (hw_status->info_frame_status.avi[8] & 0xf) + 1;
937         video_attr->extended_colorimetry = (hw_status->info_frame_status.avi[6] >> 4) & 0x07; /* 4'b, BIT[3:1] */
938         video_attr->video_timing         = drv_hdmi_video_timing_lookup(video_code, video_attr->picture_aspect);
939         hdmi_info("video_timing: %u, video_code: %u, picture_aspect: %u\n",
940             video_attr->video_timing, video_code, video_attr->picture_aspect);
941         if ((!hw_status->info_frame_status.vsif_enable) && (!video_code)) {
942             video_attr->video_timing = HDMI_VIDEO_TIMING_UNKNOWN;
943         }
944         app_attr->out_csc_quantization = (app_attr->out_color_space == HDMI_COLORSPACE_RGB) ?
945             video_attr->rgb_quantization : (video_attr->ycc_quantization + 1);
946         hdmi_info("get hw out_csc_quantization: %u\n", app_attr->out_csc_quantization);
947     }
948     video_attr->stereo_mode = HDMI_3D_BUTT;
949     if (hw_status->info_frame_status.vsif_enable) {
950         enum hdmi_video_format format = (hw_status->info_frame_status.vsif[7] >> 5) & 0x3; /* 5'b, BIT[2:1] */
951         if (format == HDMI_VIDEO_FORMAT_4K) {
952             hdmi_vsif_vic video_code = hw_status->info_frame_status.vsif[8];
953             video_attr->video_timing = drv_hdmi_vsif_video_timing_lookup(video_code);
954         } else if (format == HDMI_VIDEO_FORMAT_3D) {
955             video_attr->stereo_mode = (hw_status->info_frame_status.vsif[8] >> 4) & 0xf; /* 4'b, BIT[4:1] */
956         }
957     }
958 
959     return;
960 }
961 
962 static hi_s32 hdmi_attr_construct(hdmi_device *hdmi_dev, hdmi_attr *attr)
963 {
964     hdmi_hardware_status hw_status  = {0};
965     hdmi_ao_attr        *audio_attr = HI_NULL;
966 
967     audio_attr = &attr->ao_attr;
968     hal_call_void(hal_hdmi_hardware_status_get, hdmi_dev->hal, &hw_status);
969 
970     /* user attribute construct */
971     hdmi_user_attr_construct(hdmi_dev, attr, &hw_status);
972     /* video attribute construct */
973     hdmi_video_attr_construct(attr, &hw_status);
974     /* audio attrbute construct */
975     audio_attr->down_sample  = hw_status.audio_status.down_sample;
976     audio_attr->channels     = hw_status.audio_status.layout;
977     audio_attr->sample_depth = hw_status.audio_status.sample_depth;
978     audio_attr->sample_fs    = hw_status.audio_status.sample_fs;
979     audio_attr->sound_intf   = hw_status.audio_status.sound_intf;
980     if (hw_status.info_frame_status.audio_enable) {
981         audio_attr->audio_code = (hw_status.info_frame_status.audio[4] >> 4) & 0xf; /* 4'b, BIT[4:1] */
982     }
983 
984     return HI_SUCCESS;
985 }
986 
987 static hi_s32 hpd_event(hdmi_device *hdmi_dev)
988 {
989     hi_s32 ret         = HI_SUCCESS;
990     hi_u32 timeout_cnt = 5;
991 
992     hdmi_if_null_return(hdmi_dev, HI_ERR_NULL_PTR);
993     hdmi_if_null_return(hdmi_dev->hal, HI_ERR_NULL_PTR);
994 
995     /* update edid from sink */
996     if (hdmi_dev->hpd_detected == HI_FALSE) {
997         drv_hdmi_edid_reset(&hdmi_dev->edid_info);
998         do {
999             /*
1000              * 1.for some TV ,EDID need to read more times;
1001              * 2.for some repeater, EDID is readable after HPD assert 250ms.
1002              */
1003             ret = drv_hdmi_edid_update(&hdmi_dev->edid_info, HDMI_EDID_UPDATE_SINK);
1004             if (ret == HI_SUCCESS) {
1005                 hdmi_dev->hpd_detected = HI_TRUE;
1006                 break;
1007             }
1008             osal_msleep(DEV_HPD_ASSERT_WAIT_TIME);
1009         } while (timeout_cnt--);
1010 
1011         if (ret != HI_SUCCESS) {
1012             hdmi_warn("update EDID fail,timeout_cnt=%u\n", timeout_cnt);
1013         }
1014     }
1015     compatibility_info_update(hdmi_dev->hdmi_dev_id);
1016 
1017     return ret;
1018 }
1019 
1020 static hi_void event_notify(hdmi_device *hdmi_dev, hdmi_event event)
1021 {
1022     if (event <= HDMI_EVENT_HDCP_USERSETTING) {
1023         hdmi_mutex_unlock(g_hdmi_mutex);
1024         hdmi_mutex_lock(hdmi_dev->mutex_thread);
1025         if (hdmi_dev->k_callback == HI_NULL) { /* notify to user */
1026             hdmi_info("notify event(0x%x) to user\n", event);
1027             drv_hdmi_event_pool_write(hdmi_dev->hdmi_dev_id, event);
1028         } else { /* notify to kernel */
1029             hdmi_info("notify event(0x%x) to kernel\n", event);
1030             if (hdmi_dev->k_callback != HI_NULL) {
1031                 hdmi_dev->k_callback((hi_void *)&(hdmi_dev->hdmi_dev_id), event);
1032             }
1033             if (event == HDMI_EVENT_HOTPLUG) {
1034                 hdmi_dev->hpd_notified = HI_TRUE;
1035             }
1036         }
1037         hdmi_mutex_unlock(hdmi_dev->mutex_thread);
1038         hdmi_mutex_lock(g_hdmi_mutex);
1039     }
1040 
1041     return;
1042 }
1043 
1044 static hi_s32 hdmi_event_callback(hi_void *data, hdmi_event event)
1045 {
1046     hi_s32 ret = HI_SUCCESS;
1047     hdmi_device *hdmi_dev = (hdmi_device *)data;
1048 
1049     switch (event) {
1050         case HDMI_EVENT_HOTPLUG:
1051             hpd_event(hdmi_dev);
1052             break;
1053         case HDMI_EVENT_HOTUNPLUG:
1054             hdmi_dev->hpd_detected = HI_FALSE;
1055             break;
1056 #ifdef HDMI_HDR_SUPPORT
1057         case HDMI_EVENT_ZERO_DRMIF_TIMEOUT:
1058             hdmi_zero_drm_infoframe_stop(hdmi_dev);
1059             break;
1060         case HDMI_EVENT_SWITCH_TO_HDRMODE_TIMEOUT:
1061             hdmi_hdr_mode_change_timeout(hdmi_dev);
1062             break;
1063 #endif
1064         default:
1065             break;
1066     }
1067     event_notify(hdmi_dev, event);
1068 
1069     return ret;
1070 }
1071 
1072 static hi_s32 hdmi_kthread_timer(void *data)
1073 {
1074     hdmi_device *hdmi_dev = (hdmi_device *)data;
1075 #ifdef HDMI_FRL_SUPPORT
1076     hdmi_frl_info *frl_info = HI_NULL;
1077 #endif
1078     hdmi_if_null_return(hdmi_dev, HI_ERR_NULL_PTR);
1079 #ifdef HDMI_FRL_SUPPORT
1080     frl_info = &hdmi_dev->frl_info;
1081 #endif
1082 
1083     while (1) {
1084 #ifdef HDMI_LITEOS_SUPPORT
1085         if (hdmi_dev->thread_info.thread_run == HI_FALSE) {
1086             hdmi_dev->thread_info.thread_exit = HI_TRUE;
1087             osal_wakeup(&hdmi_dev->thread_info.wait_destroy);
1088             break;
1089         }
1090 #else
1091         if (kthread_should_stop()) {
1092             break;
1093         }
1094 #endif
1095         if (hdmi_dev->thread_info.thread_timer_sate == HDMI_THREAD_STATE_STOP) {
1096             osal_msleep(HDMI_THREAD_STATE_WAIT_TIME);
1097             continue;
1098         }
1099 
1100 #ifdef HDMI_FRL_SUPPORT
1101         if (frl_info->state_mach_info.start_mach) {
1102             drv_hdmi_frl_train_mach(hdmi_dev->hdmi_dev_id);
1103         }
1104 #endif
1105         if (hdmi_dev->hal != HI_NULL) {
1106             if (hdmi_dev->hal->hal_hdmi_sequencer_handler_process != HI_NULL &&
1107                 (((hi_u32)hdmi_dev->run_state & HDMI_RUN_STATE_OPEN) ||
1108                 ((hi_u32)hdmi_dev->run_state & HDMI_RUN_STATE_START) ||
1109                 ((hi_u32)hdmi_dev->run_state & HDMI_RUN_STATE_STOP))) {
1110                 hdmi_dev->hal->hal_hdmi_sequencer_handler_process((struct hdmi_hal_ *)hdmi_dev);
1111             }
1112         } else {
1113             hdmi_info("input param is NULL\n");
1114         }
1115 
1116 #if defined(HDMI_SUPPORT_LOGIC_HISIV100)
1117         osal_msleep(HDMI_THREAD_DELAY);
1118 #endif
1119     }
1120 
1121     return HI_SUCCESS;
1122 }
1123 
1124 static hi_void hdmi_vo_attr_init(hdmi_vo_attr *video_attr)
1125 {
1126     hi_bool colorimetry_is601;
1127 
1128     colorimetry_is601 = ((video_attr->video_timing == HDMI_VIDEO_TIMING_720X480P_60000) ||
1129                          (video_attr->video_timing == HDMI_VIDEO_TIMING_720X576P_50000) ||
1130                          (video_attr->video_timing == HDMI_VIDEO_TIMING_1440X240P_60000) ||
1131                          (video_attr->video_timing == HDMI_VIDEO_TIMING_1440X480I_60000) ||
1132                          (video_attr->video_timing == HDMI_VIDEO_TIMING_1440X576I_50000) ||
1133                          (video_attr->video_timing == HDMI_VIDEO_TIMING_1440X576P_50000) ||
1134                          (video_attr->video_timing == HDMI_VIDEO_TIMING_1440X576I_60000));
1135 
1136     if (video_attr->video_timing == HDMI_VIDEO_TIMING_640X480P_60000) {
1137         video_attr->colorimetry = HDMI_COLORIMETRY_ITU_709;
1138         video_attr->picture_aspect = HDMI_PICTURE_ASPECT_4_3;
1139     } else if (colorimetry_is601 == HI_TRUE) {
1140         video_attr->colorimetry = HDMI_COLORIMETRY_ITU_601;
1141         video_attr->picture_aspect = HDMI_PICTURE_ASPECT_4_3;
1142     } else if (video_attr->video_timing <= HDMI_VIDEO_TIMING_4096X2160P_120000 &&
1143                video_attr->video_timing >= HDMI_VIDEO_TIMING_4096X2160P_24000) {
1144         video_attr->colorimetry = HDMI_COLORIMETRY_ITU_709;
1145         video_attr->picture_aspect = HDMI_PICTURE_ASPECT_256_135;
1146     } else {
1147         video_attr->colorimetry = HDMI_COLORIMETRY_ITU_709;
1148         video_attr->picture_aspect = HDMI_PICTURE_ASPECT_16_9;
1149     }
1150 
1151     video_attr->pixel_repeat = 1;
1152     if (video_attr->video_timing == HDMI_VIDEO_TIMING_1440X480I_60000 ||
1153         video_attr->video_timing == HDMI_VIDEO_TIMING_1440X576I_50000) {
1154         video_attr->pixel_repeat = 2; /* 2, pixel repeat count */
1155     }
1156 
1157     if (video_attr->video_timing <= HDMI_VIDEO_TIMING_640X480P_60000) {
1158         // cts1.4 test_id 7-24 required rgb_quantization is default or limited when the timing is 640x480p60
1159         video_attr->rgb_quantization = HDMI_QUANTIZATION_RANGE_DEFAULT;
1160     } else {
1161         video_attr->ycc_quantization = HDMI_YCC_QUANTIZATION_RANGE_LIMITED;
1162     }
1163 
1164     if (video_attr->video_timing != HDMI_VIDEO_TIMING_UNKNOWN &&
1165         video_attr->video_timing != HDMI_VIDEO_TIMING_640X480P_60000) {
1166         video_attr->in_color_space = HDMI_COLORSPACE_YCBCR444;
1167     } else {
1168         video_attr->in_color_space = HDMI_COLORSPACE_RGB;
1169     }
1170 
1171     video_attr->stereo_mode   = HDMI_3D_BUTT;
1172     video_attr->in_bit_depth  = HDMI_VIDEO_BITDEPTH_10;
1173     video_attr->active_aspect = HDMI_ACTIVE_ASPECT_PICTURE;
1174 }
1175 
1176 static hi_void hdmi_user_attr_init(hdmi_device *hdmi_dev)
1177 {
1178     hdmi_app_attr     *app_attr = HI_NULL;
1179 #ifdef HDMI_HDR_SUPPORT
1180     drv_hdmi_hdr_attr *hdr_attr = HI_NULL;
1181 #endif
1182 
1183     app_attr = &hdmi_dev->attr.app_attr;
1184 #ifdef HDMI_HDR_SUPPORT
1185     hdr_attr = &hdmi_dev->attr.hdr_attr;
1186 #endif
1187     app_attr->enable_hdmi            = HI_TRUE;
1188     app_attr->enable_video           = HI_TRUE;
1189     app_attr->enable_audio           = HI_TRUE;
1190     app_attr->enable_aud_infoframe   = HI_TRUE;
1191     app_attr->enable_avi_infoframe   = HI_TRUE;
1192     app_attr->deep_color_mode        = HDMI_DEEP_COLOR_24BIT;
1193     app_attr->out_color_space        = HDMI_COLORSPACE_YCBCR444;
1194     app_attr->enable_clr_space_adapt = HI_TRUE;
1195     app_attr->enable_deep_clr_adapt  = HI_TRUE;
1196     app_attr->out_csc_quantization   = HDMI_QUANTIZATION_RANGE_LIMITED;
1197 #ifdef HDMI_HDR_SUPPORT
1198 #if defined(HDMI_CHIP_HI3559AV100)
1199     hdr_attr->user_hdr_mode = HDMI_HDR_USERMODE_HDR10;
1200 #else
1201     hdr_attr->user_hdr_mode = HDMI_HDR_USERMODE_SDR;
1202 #endif
1203     hdr_attr->colorimetry   = HDMI_HDR_COLORIMETRY_ITU_601;
1204 
1205     app_attr->enable_drm_infoframe    = HI_TRUE;
1206     hdmi_dev->hdr_mutex.attr_busy     = HI_FALSE;
1207     hdmi_dev->hdr_mutex.attr_set      = HI_FALSE;
1208     hdmi_dev->hdr_info.hdr_debug_mode = HDMI_HDR_DEBUG_MODE_NONE;
1209     hdmi_dev->hdr_info.hdr_mode_chn_timer.timer_start = HI_FALSE;
1210     hdmi_dev->hdr_info.hdr_mode_chn_timer.timer_type  = HDMI_TIMER_SDR_TO_HDR10;
1211     hdmi_dev->hdr_info.hdr_mode_chn_timer.time        = HDRMODE_CHANGE_TIME;
1212     hdmi_dev->hdr_info.zero_drm_if_timer.timer_start  = HI_FALSE;
1213     hdmi_dev->hdr_info.zero_drm_if_timer.timer_type   = HDMI_TIMER_ZERO_DRMIF;
1214     hdmi_dev->hdr_info.zero_drm_if_timer.time         = ZERO_DRMIF_SEND_TIME;
1215 #endif
1216 
1217     return;
1218 }
1219 
1220 static hi_s32 hdmi_device_init(hdmi_device *hdmi_dev)
1221 {
1222     hdmi_ao_attr *audio_attr = HI_NULL;
1223     hdmi_vo_attr *video_attr = HI_NULL;
1224 
1225     audio_attr = &hdmi_dev->attr.ao_attr;
1226     video_attr = &hdmi_dev->attr.vo_attr;
1227     get_hdmi_default_action_set(hdmi_dev, HDMI_DEFAULT_ACTION_HDMI);
1228 
1229 #ifdef HDMI_EMI_ENABLE
1230     hdmi_dev->emi_enable = HI_TRUE;
1231 #else
1232     hdmi_dev->emi_enable = HI_FALSE;
1233 #endif
1234     /* common para init */
1235     hdmi_dev->debug.stop_delay = 0;
1236     hdmi_dev->delay.fmt_delay  = HDMI_DEV_FMT_DELAY;
1237     hdmi_dev->delay.mute_delay = HDMI_DEV_MUTE_DELAY;
1238     /* user attribute init */
1239     hdmi_user_attr_init(hdmi_dev);
1240     /* video attribute init */
1241     video_attr->video_timing = HDMI_VIDEO_TIMING_1280X720P_50000;
1242     video_attr->clk_fs       = HDMI_VIDEO_ATTR_CLK_FS;
1243     video_attr->h_sync_pol   = HI_FALSE;
1244     video_attr->v_sync_pol   = HI_FALSE;
1245     video_attr->de_pol       = HI_FALSE;
1246     (hi_void)memset_s(&(hdmi_dev->debug.intf_status), sizeof(hdmi_dev->debug.intf_status), 0, sizeof(hdmi_intf_status));
1247     hdmi_vo_attr_init(video_attr);
1248 
1249 #if defined(CONFIG_HI_PLATFORM_H8)
1250     hdmi_dev->attr.app_attr.out_csc_quantization = hdmi_dev->csc_param.quantization;
1251     hdmi_dev->attr.app_attr.out_color_space = hdmi_dev->csc_param.pixel_encoding;
1252     video_attr->in_color_space = hdmi_dev->csc_param.pixel_encoding;
1253     video_attr->colorimetry = hdmi_dev->csc_param.colorimetry;
1254 #endif
1255     /* audio attribute init */
1256     audio_attr->sound_intf   = HDMI_AUDIO_INTF_I2S;
1257     audio_attr->sample_fs    = HDMI_SAMPLE_RATE_48K;
1258     audio_attr->sample_depth = HDMI_AUDIO_BIT_DEPTH_16;
1259     audio_attr->channels     = HDMI_AUDIO_FORMAT_2CH;
1260 #if defined(HDMI_CHIP_HI3519AV100)
1261     hdmi_dev->mode_param.trace_len = HDMI_TRACE_LEN_2;
1262 #elif defined(HDMI_CHIP_HI3559AV100)
1263     hdmi_dev->mode_param.trace_len = HDMI_TRACE_LEN_1;
1264 #elif defined(HDMI_CHIP_HI3516CV500)
1265     hdmi_dev->mode_param.trace_len = HDMI_TRACE_LEN_0;
1266 #elif defined(PHY_CRAFT_S28)
1267     hdmi_dev->mode_param.trace_len = HDMI_TRACE_BUTT;
1268 #endif
1269 
1270     compatibility_info_default_set(hdmi_dev->hdmi_dev_id);
1271     hdmi_info("video_timing:%u\n", video_attr->video_timing);
1272 
1273     return HI_SUCCESS;
1274 }
1275 
1276 static hi_void hdmi_dev_deinit(hdmi_device *hdmi_dev)
1277 {
1278     hdmi_dev->emi_enable        = HI_FALSE;
1279     hdmi_dev->hpd_detected      = HI_FALSE;
1280     hdmi_dev->hpd_notified      = HI_FALSE;
1281     hdmi_dev->run_state         = HDMI_RUN_STATE_NONE;
1282     hdmi_dev->tmds_mode         = HDMI_TMDS_MODE_NONE;
1283     hdmi_dev->transition_state  = HDMI_TRANSITION_NONE;
1284     hdmi_dev->k_callback        = HI_NULL;
1285     hdmi_dev->hal               = HI_NULL;
1286     hdmi_dev->hdmi_dev_id       = 0;
1287     hdmi_dev->kernel_cnt        = 0;
1288     hdmi_dev->user_callback_cnt = 0;
1289     hdmi_dev->user_cnt          = 0;
1290 
1291     (hi_void)memset_s(&hdmi_dev->attr, sizeof(hdmi_dev->attr), 0, sizeof(hdmi_dev->attr));
1292     (hi_void)memset_s(&hdmi_dev->debug, sizeof(hdmi_dev->debug), 0, sizeof(hdmi_dev->debug));
1293     (hi_void)memset_s(&hdmi_dev->delay, sizeof(hdmi_dev->delay), 0, sizeof(hdmi_dev->delay));
1294     (hi_void)memset_s(&hdmi_dev->edid_info, sizeof(hdmi_dev->edid_info), 0, sizeof(hdmi_dev->edid_info));
1295     (hi_void)memset_s(&hdmi_dev->info_frame, sizeof(hdmi_dev->info_frame), 0, sizeof(hdmi_dev->info_frame));
1296     (hi_void)memset_s(&hdmi_dev->thread_info, sizeof(hdmi_dev->thread_info), 0, sizeof(hdmi_dev->thread_info));
1297 #ifdef HDMI_HDR_SUPPORT
1298     hdmi_dev->hdr_mutex.attr_busy = HI_FALSE;
1299     (hi_void)memset_s(&hdmi_dev->hdr_info, sizeof(hdmi_dev->hdr_info), 0, sizeof(hdmi_dev->hdr_info));
1300 #endif
1301 
1302     return;
1303 }
1304 
1305 static hi_s32 create_task(hdmi_device *hdmi_dev, hdmi_hal_init *hal_cfg)
1306 {
1307     hi_s32 ret = HI_SUCCESS;
1308 
1309     hdmi_if_null_return(hdmi_dev, HI_ERR_NULL_PTR);
1310 
1311     if (hdmi_dev->thread_info.thread_timer == HI_NULL) {
1312         /* open hal module */
1313         hal_cfg->base_addr      = g_hdmi_reg;
1314         hal_cfg->phy_addr       = g_hdmi_phy;
1315         hal_cfg->event_callback = hdmi_event_callback;
1316         hal_cfg->event_data     = hdmi_dev;
1317         hal_cfg->hdmi_dev_id    = hdmi_dev->hdmi_dev_id;
1318 
1319         ret = hal_hdmi_open(hal_cfg, &hdmi_dev->hal);
1320         if (hdmi_dev->hal == HI_NULL || ret != HI_SUCCESS) {
1321             hdmi_err("hal_hdmi_open fail\n");
1322             return HI_FAILURE;
1323         }
1324         hdmi_dev->hal->hal_ctx.hdmi_dev = hdmi_dev;
1325         hdmi_dev->hal->hal_ctx.hdmi_id = hdmi_dev->hdmi_dev_id;
1326 
1327         hdmi_info("create HDMI timer thread \n");
1328 #ifdef HDMI_LITEOS_SUPPORT
1329         hdmi_dev->thread_info.thread_run = HI_TRUE;
1330         osal_wait_init(&hdmi_dev->thread_info.wait_destroy);
1331         hdmi_dev->thread_info.thread_exit = HI_FALSE;
1332 #endif
1333         hdmi_dev->thread_info.thread_timer = osal_kthread_create(hdmi_kthread_timer, hdmi_dev, "hi_hdmi_k_thread");
1334         if (hdmi_dev->thread_info.thread_timer == HI_NULL) {
1335             hdmi_err("create HDMI timer thread fail\n");
1336             return HI_FAILURE;
1337         }
1338 
1339         hdmi_device_init(hdmi_dev);
1340     }
1341 
1342     return ret;
1343 }
1344 
1345 static hi_s32 hdmi_oe_transition_state_set(hdmi_device *hdmi_dev, hi_bool user, hi_bool hdmi_on)
1346 {
1347     hi_s32 ret = HI_SUCCESS;
1348 
1349 #ifndef HDMI_FPGA_SUPPORT
1350     if (hdmi_on == HI_FALSE) {
1351         hdmi_info("hdmi_on:%u, hardware init...\n", hdmi_on);
1352         hdmi_dev->transition_state = HDMI_TRANSITION_NONE;
1353         hal_call_void(hal_hdmi_hardware_init, hdmi_dev->hal);
1354     } else {
1355         hdmi_info("hdmi_on:%u...\n", hdmi_on);
1356         if (user) {
1357             hdmi_dev->transition_state = (hdmi_dev->kernel_cnt > 0) ?
1358                 HDMI_TRANSITION_MCE_APP : HDMI_TRANSITION_BOOT_APP;
1359         } else {
1360             hdmi_dev->transition_state = HDMI_TRANSITION_BOOT_MCE;
1361         }
1362     }
1363 #else
1364     hdmi_info("hdmi_on:%u...\n", hdmi_on);
1365     if (user) {
1366         hdmi_dev->transition_state = (hdmi_dev->kernel_cnt > 0) ?
1367             HDMI_TRANSITION_MCE_APP : HDMI_TRANSITION_BOOT_APP;
1368     } else {
1369         hdmi_dev->transition_state = HDMI_TRANSITION_BOOT_MCE;
1370     }
1371 #endif
1372 
1373     return ret;
1374 }
1375 
1376 static hi_void drv_hdmi_hpd_status_delay_get (hdmi_device *hdmi_dev, hi_bool *hotplug)
1377 {
1378     hi_u32 i;
1379 
1380     for (i = 0; i < HDMI_READ_HPD_STATUS_DELAY; i++) {
1381         hal_call_void(hal_hdmi_hot_plug_status_get, hdmi_dev->hal, hotplug);
1382         if (*hotplug) {
1383             break;
1384         }
1385         osal_msleep(1);
1386     }
1387     hdmi_info("delay %d times, hot plug status is 0X%x\n", i, (*hotplug ? HDMI_EVENT_HOTPLUG : HDMI_EVENT_HOTUNPLUG));
1388 
1389     return;
1390 }
1391 
1392 static hi_void notify_event_in_open(hdmi_device *hdmi_dev, hi_bool hdmi_on, hi_bool hotplug)
1393 {
1394     if (hdmi_on == HI_TRUE) { /* need to updata event in open, when there is boot logo. */
1395         hdmi_event_callback(hdmi_dev, hotplug ? HDMI_EVENT_HOTPLUG : HDMI_EVENT_HOTUNPLUG);
1396     } else {
1397         if (hotplug == HI_TRUE) {
1398             hpd_event(hdmi_dev);
1399         } else {
1400             hdmi_dev->hpd_detected = HI_FALSE;
1401         }
1402     }
1403 
1404     return;
1405 }
1406 
1407 hi_s32 drv_hdmi_open(hdmi_device *hdmi_dev, hi_bool user)
1408 {
1409     hi_s32 ret;
1410     hdmi_hal_init hal_cfg       = {0};
1411     hi_u32        event_pool_id = 0;
1412     hi_bool       hotplug       = HI_FALSE;
1413     hi_bool       hdmi_on       = HI_FALSE;
1414 
1415     /* create hdmi task, every hdmi device only create once */
1416     if (create_task(hdmi_dev, &hal_cfg) != HI_SUCCESS) {
1417         return HI_ERR_HDMI_CREATE_TESK_FAILED;
1418     }
1419 
1420     drv_hdmi_event_init(hdmi_dev->hdmi_dev_id);
1421 #ifdef HDMI_FRL_SUPPORT
1422     drv_hdmi_frl_mach_init(hdmi_dev->hdmi_dev_id);
1423 #endif
1424 
1425     if (user == HI_TRUE) {
1426         /* must create event queue first */
1427         ret = drv_hdmi_event_pool_malloc(hdmi_dev->hdmi_dev_id, &event_pool_id);
1428         if (ret != HI_SUCCESS) {
1429             if (ret != HDMI_EVENT_ID_EXIST) {
1430                 hdmi_err("drv_hdmi_event_pool_malloc fail\n");
1431                 return HI_ERR_HDMI_MALLOC_FAILED;
1432             }
1433         } else {
1434             hdmi_dev->user_cnt++;
1435         }
1436         hdmi_info("create event queue for process:%u \n", hdmi_current_id_get(hdmi_dev));
1437     } else {
1438         hdmi_dev->kernel_cnt++;
1439     }
1440 
1441     if (hdmi_dev->user_callback_cnt == 0) {
1442         hdmi_mutex_unlock(g_hdmi_mutex);
1443         hdmi_mutex_lock(hdmi_dev->mutex_thread);
1444         hdmi_dev->k_callback = hi_drv_hdmi_kernel_event_callback;
1445         hdmi_mutex_unlock(hdmi_dev->mutex_thread);
1446         hdmi_mutex_lock(g_hdmi_mutex);
1447     }
1448     hdmi_info("user_cnt: %u, kernel_cnt: %u, user_call_back_cnt: %u\n",
1449               hdmi_dev->user_cnt, hdmi_dev->kernel_cnt, hdmi_dev->user_callback_cnt);
1450 
1451     hal_call_void(hal_hdmi_phy_output_enable_get, hdmi_dev->hal, &hdmi_on);
1452     ret = hdmi_oe_transition_state_set(hdmi_dev, user, hdmi_on);
1453     hdmi_if_failure_return(ret, HI_FAILURE);
1454     /* insure that get sink caps success immediately after open HDMI when no boot or no output. */
1455     drv_hdmi_hpd_status_delay_get(hdmi_dev, &hotplug);
1456     notify_event_in_open(hdmi_dev, hdmi_on, hotplug);
1457     hdmi_info("transition_state: %u\n", hdmi_dev->transition_state);
1458     hdmi_dev->run_state = HDMI_RUN_STATE_OPEN;
1459     hdmi_info("<<< out...\n");
1460 
1461     return HI_SUCCESS;
1462 }
1463 
1464 #ifdef HDMI_LITEOS_SUPPORT
1465 static hi_s32 hdmi_wait_thread_exit_callback(const hi_void *param)
1466 {
1467     hi_s32 result = HI_FALSE;
1468     const hdmi_device *hdmi_dev = (const hdmi_device *)param;
1469 
1470     if (hdmi_dev == HI_NULL) {
1471         return result;
1472     }
1473     result = (hdmi_dev->thread_info.thread_exit == HI_TRUE);
1474 
1475     return result;
1476 }
1477 #endif
1478 
1479 static hi_s32 hdmi_release(hdmi_device *hdmi_dev)
1480 {
1481     hdmi_info(">>> in...\n");
1482 
1483     if ((hi_u32)hdmi_dev->run_state & HDMI_RUN_STATE_START) {
1484         drv_hdmi_stop(hdmi_dev);
1485     }
1486 
1487     if (hdmi_dev->user_cnt == 0) {
1488         if (hdmi_dev->kernel_cnt == 0) {
1489             if (hdmi_dev->thread_info.thread_timer) {
1490                 hdmi_info("stop hdmi kernel thread timer\n");
1491 #ifdef HDMI_LITEOS_SUPPORT
1492                 hdmi_dev->thread_info.thread_run = HI_FALSE;
1493                 osal_wait_event_uninterruptible(&hdmi_dev->thread_info.wait_destroy,
1494                     hdmi_wait_thread_exit_callback, (hi_void *)hdmi_dev);
1495                 /*
1496                  * note: in liteos,
1497                  * when call the kthread_stop function,
1498                  * the thread function should be finished,
1499                  * if task(hdmi_kthread_timer) get a mutex is deleted or automatically deleted before release
1500                  * this mutex, other tasks pended this mutex maybe never be scheduled.
1501                  */
1502                 osal_kthread_destroy(hdmi_dev->thread_info.thread_timer, HI_TRUE);
1503                 osal_wait_destroy(&hdmi_dev->thread_info.wait_destroy);
1504 #else
1505                 /*
1506                  * note: in linux,
1507                  * when call the kthread_stop function,
1508                  * the thread function cannot be finished, otherwise it will oops.
1509                  */
1510                 osal_kthread_destroy(hdmi_dev->thread_info.thread_timer, HI_TRUE);
1511 #endif
1512                 hdmi_dev->thread_info.thread_timer = HI_NULL;
1513                 get_hdmi_thread_state_set(hdmi_dev, HDMI_THREAD_STATE_STOP);
1514             }
1515             drv_hdmi_event_deinit(hdmi_dev->hdmi_dev_id);
1516             hdmi_mutex_lock(hdmi_dev->mutex_proc);
1517             if (hdmi_dev->hal != HI_NULL) {
1518                 hal_hdmi_close(hdmi_dev->hal);
1519                 hdmi_dev->hal = HI_NULL;
1520             }
1521             hdmi_dev_deinit(hdmi_dev);
1522             hdmi_mutex_unlock(hdmi_dev->mutex_proc);
1523         } else {
1524             drv_hdmi_event_deinit(hdmi_dev->hdmi_dev_id);
1525             hdmi_mutex_unlock(g_hdmi_mutex);
1526             hdmi_mutex_lock(hdmi_dev->mutex_thread);
1527             hdmi_dev->k_callback = hi_drv_hdmi_kernel_event_callback;
1528             hdmi_mutex_unlock(hdmi_dev->mutex_thread);
1529             hdmi_mutex_lock(g_hdmi_mutex);
1530         }
1531     }
1532     hdmi_info("<<< out...\n");
1533 
1534     return HI_SUCCESS;
1535 }
1536 
1537 hi_s32 drv_hdmi_close(hdmi_device *hdmi_dev, hi_bool user)
1538 {
1539     hi_s32 ret;
1540 #if defined(HDMI_FPGA_SUPPORT) && defined(HDMI_HDR_SUPPORT)
1541     /* to avoid HDR mode change error when app exit. delete it after ASIC back. */
1542     drv_hdmi_hdr_attr hdr_attr = {0};
1543 #endif
1544 
1545     hdmi_info(">>> in...\n");
1546     hdmi_check_open_return((hi_u32)hdmi_dev->run_state);
1547 
1548     hdmi_info("user: %u\n", user);
1549     hdmi_info("user_cnt: %u, kernel_cnt: %u\n", hdmi_dev->user_cnt, hdmi_dev->kernel_cnt);
1550 
1551     hdmi_dev->hpd_notified = HI_FALSE;
1552 
1553     if (user && hdmi_dev->user_cnt > 0) {
1554         hdmi_info("delete event queue for process:%u \n", hdmi_current_id_get(hdmi_dev));
1555         ret = drv_hdmi_event_pool_free(hdmi_dev->hdmi_dev_id, hdmi_current_id_get(hdmi_dev));
1556         if (ret != HI_SUCCESS) {
1557             hdmi_err("drv_hdmi_event_pool_free fail\n");
1558             return HI_ERR_HDMI_FREE_FAILED;
1559         }
1560 #if defined(HDMI_FPGA_SUPPORT) && defined(HDMI_HDR_SUPPORT)
1561         /* to avoid HDR mode change error when app exit. delete it after ASIC back. */
1562         if (hdmi_dev->user_cnt == 1) {
1563             hdr_attr.hdr_mode = HI_HDMI_HDR_MODE_DISABLE;
1564             hdr_attr.eotf_type = HI_HDMI_EOTF_SDR_LUMIN;
1565             hdr_attr.colorimetry = HI_HDMI_COLORIMETRY_ITU709;
1566             hi_drv_hdmi_set_hdr_attr(HI_HDMI_DEV_ID_0, &hdr_attr);
1567         }
1568 #endif
1569         hdmi_dev->user_cnt--;
1570         if (hdmi_dev->user_cnt == 0 && hdmi_dev->kernel_cnt > 0) {
1571             hdmi_mutex_unlock(g_hdmi_mutex);
1572             hdmi_mutex_lock(hdmi_dev->mutex_thread);
1573             hdmi_dev->k_callback = hi_drv_hdmi_kernel_event_callback;
1574             hdmi_mutex_unlock(hdmi_dev->mutex_thread);
1575             hdmi_mutex_lock(g_hdmi_mutex);
1576         } else {
1577             hdmi_mutex_unlock(g_hdmi_mutex);
1578             hdmi_mutex_lock(hdmi_dev->mutex_thread);
1579             hdmi_dev->k_callback = HI_NULL;
1580             hdmi_mutex_unlock(hdmi_dev->mutex_thread);
1581             hdmi_mutex_lock(g_hdmi_mutex);
1582         }
1583     } else if (!user && hdmi_dev->kernel_cnt > 0) {
1584         hdmi_dev->kernel_cnt--;
1585     }
1586 
1587     if (hdmi_dev->user_cnt == 0 && hdmi_dev->kernel_cnt == 0) {
1588         hdmi_release(hdmi_dev);
1589         hdmi_dev->run_state = HDMI_RUN_STATE_CLOSE;
1590     }
1591 
1592     hdmi_info("<<< out...\n");
1593 
1594     return HI_SUCCESS;
1595 }
1596 
1597 hi_s32 drv_hdmi_start(hdmi_device *hdmi_dev)
1598 {
1599     hi_bool audio_enable = HI_FALSE;
1600     hdmi_app_attr *app_attr = HI_NULL;
1601 
1602     hdmi_info(">>> in...\n");
1603 
1604     hdmi_if_null_return(hdmi_dev, HI_ERR_NULL_PTR);
1605     hdmi_check_open_return((hi_u32)hdmi_dev->run_state);
1606 
1607     app_attr = &hdmi_dev->attr.app_attr;
1608     audio_enable = (hdmi_dev->attr.app_attr.enable_audio) && (app_attr->enable_hdmi);
1609     /* enable clk */
1610     drv_hdmi_low_power_set(HI_FALSE);
1611 
1612 #ifdef HDMI_FRL_SUPPORT
1613     if (hdmi_dev->frl_info.mode != HDMI_FRL_MODE_FRL) {
1614         if (hdmi_mode_strategy(hdmi_dev) != HI_SUCCESS) {
1615             hdmi_err(" hdmi_mode_strategy fail\n");
1616         }
1617     }
1618 #else
1619     if (hdmi_mode_strategy(hdmi_dev) != HI_SUCCESS) {
1620         hdmi_err(" hdmi_mode_strategy fail\n");
1621     }
1622 #endif
1623     /*
1624      * 20160415, fix SAM doesn't show at 10bit/12bit.
1625      * this TV clear mute must after phy enable when the deepcolor is 10bit and 12bit.
1626      */
1627     hal_call_void(hal_hdmi_avmute_set, hdmi_dev->hal, HI_FALSE);
1628 
1629 #ifdef HDMI_FRL_SUPPORT
1630     if (hdmi_dev->frl_info.mode != HDMI_FRL_MODE_TMDS) {
1631         hdmi_info("start frl...\n");
1632         drv_hdmi_frl_enable(hdmi_dev->hdmi_dev_id, HI_TRUE);
1633     } else {
1634         hdmi_info("TMDS phy config\n");
1635         hdmi_phy_output_enable(hdmi_dev, HI_TRUE);
1636     }
1637 #else
1638     hdmi_info("TMDS phy config\n");
1639     hdmi_phy_output_enable(hdmi_dev, HI_TRUE);
1640 #endif
1641     drv_hdmi_avmute_set(hdmi_dev, HI_FALSE);
1642     drv_hdmi_audio_path_enable(hdmi_dev, audio_enable);
1643 
1644     if (hdmi_dev->attr.app_attr.enable_video == HI_FALSE) {
1645         /* if video is disable, send black video. */
1646         hdmi_info("video was disable by user, so send blackframe.\n");
1647         drv_hdmi_black_data_set(hdmi_dev, HI_TRUE);
1648     } else if (hdmi_dev->attr.app_attr.hdcp_enable == HI_FALSE) {
1649         /* stop black frame here if hdcp is disable, otherwise stop it when the hdcp auth success. */
1650         drv_hdmi_black_data_set(hdmi_dev, HI_FALSE);
1651     }
1652     hdmi_dev->run_state = (hi_u32)hdmi_dev->run_state & (~(HDMI_RUN_STATE_STOP));
1653     hdmi_dev->run_state = (hi_u32)hdmi_dev->run_state | (HDMI_RUN_STATE_START);
1654     hdmi_info("<<< out...\n");
1655 
1656     return HI_SUCCESS;
1657 }
1658 
1659 static hi_void hdmi_debug_delay(hdmi_device *hdmi_dev, const hi_char *info)
1660 {
1661     hdmi_if_null_return_void(info);
1662 
1663     osal_msleep(hdmi_dev->debug.stop_delay);
1664 
1665     if (hdmi_dev->debug.stop_delay > 0) {
1666         hdmi_info("%s, delay %ums...\n", info, hdmi_dev->debug.stop_delay);
1667     }
1668 }
1669 
1670 hi_s32 drv_hdmi_stop(hdmi_device *hdmi_dev)
1671 {
1672     hdmi_info(">>> in...\n");
1673 
1674     hdmi_if_null_return(hdmi_dev, HI_ERR_NULL_PTR);
1675     hdmi_if_null_return(hdmi_dev->hal, HI_ERR_NULL_PTR);
1676 
1677     hdmi_debug_delay(hdmi_dev, "drv_hdmi_stop debug start");
1678     if (!((hi_u32)hdmi_dev->run_state & HDMI_RUN_STATE_START) || ((hi_u32)hdmi_dev->run_state & HDMI_RUN_STATE_STOP)) {
1679         return HI_SUCCESS;
1680     }
1681     hdmi_debug_delay(hdmi_dev, "drv_hdmi_stop audio path disable");
1682     drv_hdmi_audio_path_enable(hdmi_dev, HI_FALSE);
1683     hdmi_debug_delay(hdmi_dev, "drv_hdmi_stop black data enable");
1684     drv_hdmi_black_data_set(hdmi_dev, HI_TRUE);
1685     hdmi_debug_delay(hdmi_dev, "drv_hdmi_stop avmute enable");
1686     drv_hdmi_avmute_set(hdmi_dev, HI_TRUE);
1687     hdmi_debug_delay(hdmi_dev, "drv_hdmi_stop phy disable");
1688 #ifdef HDMI_FRL_SUPPORT
1689     if (hdmi_dev->frl_info.mode != HDMI_FRL_MODE_TMDS) {
1690         drv_hdmi_frl_enable(hdmi_dev->hdmi_dev_id, HI_FALSE);
1691     } else {
1692         hdmi_phy_output_enable(hdmi_dev, HI_FALSE);
1693     }
1694 #else
1695     hdmi_phy_output_enable(hdmi_dev, HI_FALSE);
1696 #endif
1697 
1698     /* disable clk for low power */
1699     drv_hdmi_low_power_set(HI_TRUE);
1700     hdmi_dev->run_state = (hi_u32)hdmi_dev->run_state  & (~(HDMI_RUN_STATE_START));
1701     hdmi_dev->run_state = (hi_u32)hdmi_dev->run_state | HDMI_RUN_STATE_STOP;
1702     drv_hdmi_compat_stop_delay(hdmi_dev->hdmi_dev_id);
1703     hdmi_debug_delay(hdmi_dev, "stop delay");
1704     hdmi_info("<<< out...\n");
1705 
1706     return HI_SUCCESS;
1707 }
1708 
1709 hi_void drv_hdmi_avmute_set(const hdmi_device *hdmi_dev, hi_bool av_mute)
1710 {
1711     hdmi_delay delay = {0};
1712 
1713     hdmi_info(">>> in..., avmute: %u\n", av_mute);
1714 
1715     hdmi_if_null_return_void(hdmi_dev);
1716     hdmi_if_null_return_void(hdmi_dev->hal);
1717 
1718     delay.fmt_delay  = hdmi_dev->delay.fmt_delay;
1719     delay.mute_delay = hdmi_dev->delay.mute_delay;
1720     drv_hdmi_compat_delay_get(hdmi_dev->hdmi_dev_id, &delay);
1721 
1722     if (hdmi_dev->attr.app_attr.auth_mode != HI_TRUE) {
1723         /* fix compatibility problem */
1724         if (!av_mute) {
1725             hdmi_info("format_delay %u ms \n", delay.fmt_delay);
1726             osal_msleep(delay.fmt_delay);
1727         }
1728     }
1729     hal_call_void(hal_hdmi_avmute_set, hdmi_dev->hal, av_mute);
1730 
1731     if (hdmi_dev->attr.app_attr.auth_mode != HI_TRUE) {
1732         /* fix compatibility problem */
1733         if (av_mute) {
1734             hdmi_info("mute_delay %u ms \n", delay.mute_delay);
1735             osal_msleep(delay.mute_delay);
1736         }
1737     }
1738     hdmi_info("<<< out...\n");
1739 
1740     return;
1741 }
1742 
1743 static hi_void drv_hdmi_black_data_set(const hdmi_device *hdmi_dev, hi_bool enable)
1744 {
1745     hdmi_black_frame_info black_info;
1746     hdmi_if_null_return_void(hdmi_dev);
1747 
1748     black_info.black_enable = enable;
1749     black_info.in_bit_depth = hdmi_dev->attr.vo_attr.in_bit_depth;
1750     black_info.in_color_space = hdmi_dev->attr.vo_attr.in_color_space;
1751     black_info.in_quantization = (black_info.in_color_space == HDMI_COLORSPACE_RGB) ?
1752         hdmi_dev->attr.vo_attr.rgb_quantization : hdmi_dev->attr.vo_attr.ycc_quantization;
1753     hal_call_void(hal_hdmi_black_data_set, hdmi_dev->hal, &black_info);
1754 
1755     return;
1756 }
1757 
1758 hi_s32 drv_hdmi_deep_color_set(hdmi_device *hdmi_dev, hdmi_deep_color deep_color)
1759 {
1760     hi_s32 ret;
1761     hdmi_attr attr = {0};
1762 
1763     hdmi_info(">>> in...\n");
1764 
1765     hdmi_if_null_return(hdmi_dev, HI_ERR_NULL_PTR);
1766     hdmi_if_null_return(hdmi_dev->hal, HI_ERR_NULL_PTR);
1767 
1768     hdmi_info("deep_color: %u\n", deep_color);
1769 
1770     ret = drv_hdmi_attr_get(hdmi_dev, &attr);
1771     if (attr.app_attr.out_color_space == HDMI_COLORSPACE_YCBCR422) {
1772         if ((deep_color != HDMI_DEEP_COLOR_24BIT) && (deep_color != HDMI_DEEP_COLOR_OFF)) {
1773             hdmi_err("not support deepcolor:%u when colorspace is ycbcr422. \n", deep_color);
1774             return HI_ERR_HDMI_INVALID_PARA;
1775         }
1776     }
1777 #ifdef HDMI_HDR_SUPPORT
1778     /* if the current hdmi mode is dolby, deep_color_set is invalid. */
1779     if (attr.hdr_attr.hdr_mode == HDMI_HDR_MODE_DOLBY_NORMAL ||
1780         attr.hdr_attr.hdr_mode == HDMI_HDR_MODE_DOLBY_TUNNELING) {
1781         hdmi_warn("don't change deepcolor when dolby mode is:%u \n", attr.hdr_attr.hdr_mode);
1782         return HI_FAILURE;
1783     }
1784 #endif
1785     attr.app_attr.deep_color_mode = deep_color;
1786     drv_hdmi_avmute_set(hdmi_dev, HI_TRUE);
1787     ret = drv_hdmi_attr_set(hdmi_dev, &attr);
1788     drv_hdmi_avmute_set(hdmi_dev, HI_FALSE);
1789     hdmi_info("<<< out...\n");
1790 
1791     return ret;
1792 }
1793 
1794 hi_s32 drv_hdmi_deep_color_get(hdmi_device *hdmi_dev, hdmi_deep_color *deep_color)
1795 {
1796     hdmi_app_attr *app_attr = HI_NULL;
1797 
1798     hdmi_info(">>> in...\n");
1799 
1800     hdmi_if_null_return(hdmi_dev, HI_ERR_NULL_PTR);
1801     hdmi_if_null_return(deep_color, HI_ERR_NULL_PTR);
1802 
1803     app_attr = &hdmi_dev->attr.app_attr;
1804     *deep_color = app_attr->deep_color_mode;
1805 
1806     hdmi_info("deep_color: %u\n", *deep_color);
1807     hdmi_info("<<< out...\n");
1808 
1809     return HI_SUCCESS;
1810 }
1811 
1812 static hi_s32 check_audio_attr(const hdmi_ao_attr *ao_attr)
1813 {
1814     if (ao_attr->sound_intf != HDMI_AUDIO_INTF_I2S &&
1815         ao_attr->sound_intf != HDMI_AUDIO_INTF_SPDIF &&
1816         ao_attr->sound_intf != HDMI_AUDIO_INTF_HBRA) {
1817         hdmi_err("the audio interface(%u) is invalid\n", ao_attr->sound_intf);
1818         return HI_FAILURE;
1819     }
1820 
1821     if (ao_attr->channels < HDMI_AUDIO_FORMAT_2CH || ao_attr->channels > HDMI_AUDIO_FORMAT_8CH) {
1822         hdmi_err("the audio channel number(%u) is invalid\n", ao_attr->channels);
1823         return HI_FAILURE;
1824     }
1825 
1826     if (ao_attr->sample_fs < HDMI_SAMPLE_RATE_32K || ao_attr->sample_fs > HDMI_SAMPLE_RATE_768K) {
1827         hdmi_err("the input audio frequency(%u) is invalid\n", ao_attr->sample_fs);
1828         return HI_FAILURE;
1829     }
1830 
1831     return HI_SUCCESS;
1832 }
1833 
1834 hi_s32 drv_hdmi_ao_attr_set(hdmi_device *hdmi_dev, const hdmi_ao_attr *ao_attr)
1835 {
1836     errno_t errnumber;
1837     hi_s32            ret        = HI_SUCCESS;
1838     hdmi_attr         hw_attr    = {0};
1839     hdmi_audio_config audio_cfg  = {0};
1840     hdmi_app_attr    *app_attr   = HI_NULL;
1841     hdmi_ao_attr     *audio_attr = HI_NULL;
1842     hdmi_vo_attr     *video_attr = HI_NULL;
1843 
1844     hdmi_info(">>> in...\n");
1845 
1846     hdmi_if_null_return(hdmi_dev, HI_ERR_NULL_PTR);
1847     hdmi_if_null_return(ao_attr, HI_ERR_NULL_PTR);
1848 
1849     if (check_audio_attr(ao_attr) != HI_SUCCESS) {
1850         hdmi_err("check_audio_attr fail\n");
1851         return HI_FAILURE;
1852     }
1853     app_attr   = &hdmi_dev->attr.app_attr;
1854     video_attr = &hdmi_dev->attr.vo_attr;
1855     audio_attr = &hdmi_dev->attr.ao_attr;
1856 
1857     errnumber = memcpy_s(audio_attr, sizeof(hdmi_dev->attr.ao_attr), ao_attr, sizeof(hdmi_ao_attr));
1858     hdmi_unequal_eok_return(errnumber, HI_ERR_HDMI_INVALID_PARA);
1859     hdmi_attr_construct(hdmi_dev, &hw_attr);
1860 
1861     hdmi_info("down_sample: %u\n", audio_attr->down_sample);
1862     hdmi_info("sample_fs: %u\n", audio_attr->sample_fs);
1863     hdmi_info("channels: %u\n", audio_attr->channels);
1864     hdmi_info("sound_intf: %u\n", audio_attr->sound_intf);
1865     hdmi_info("sample_depth: %u\n", audio_attr->sample_depth);
1866     hdmi_info("audio_code: %u\n", audio_attr->audio_code);
1867 
1868     audio_cfg.down_sample  = ao_attr->down_sample;
1869     audio_cfg.layout       = ao_attr->channels;
1870     audio_cfg.sample_depth = ao_attr->sample_depth;
1871     audio_cfg.sample_fs    = ao_attr->sample_fs;
1872     audio_cfg.sound_intf   = ao_attr->sound_intf;
1873     audio_cfg.enable_audio = (hdmi_dev->attr.app_attr.enable_audio) && (app_attr->enable_hdmi);
1874     audio_cfg.tmds_clk     = video_attr->hdmi_adapt_pix_clk;
1875     audio_cfg.pixel_repeat = video_attr->pixel_repeat;
1876     hal_call_void(hal_hdmi_audio_path_enable_set, hdmi_dev->hal, HI_FALSE);
1877     hal_call_ret(ret, hal_hdmi_audio_path_set, hdmi_dev->hal, &audio_cfg);
1878     drv_hdmi_audio_infoframe_send(&hdmi_dev->info_frame, (app_attr->enable_audio && app_attr->enable_aud_infoframe));
1879     hal_call_void(hal_hdmi_audio_path_enable_set, hdmi_dev->hal, audio_cfg.enable_audio);
1880     hdmi_info("<<< out...\n");
1881 
1882     return ret;
1883 }
1884 
1885 hi_void drv_hdmi_audio_path_enable(const hdmi_device *hdmi_dev, hi_bool enable)
1886 {
1887     hal_call_void(hal_hdmi_audio_path_enable_set, hdmi_dev->hal, enable);
1888     return;
1889 }
1890 
1891 hi_s32 drv_hdmi_ao_attr_get(const hdmi_device *hdmi_dev, hdmi_ao_attr *ao_attr)
1892 {
1893     errno_t errnumber;
1894     hdmi_info(">>> in...\n");
1895 
1896     hdmi_if_null_return(hdmi_dev, HI_ERR_NULL_PTR);
1897     hdmi_if_null_return(ao_attr, HI_ERR_NULL_PTR);
1898 
1899     errnumber = memcpy_s(ao_attr, sizeof(*ao_attr), &hdmi_dev->attr.ao_attr, sizeof(hdmi_ao_attr));
1900     hdmi_unequal_eok_return(errnumber, HI_ERR_HDMI_INVALID_PARA);
1901     hdmi_info("<<< out...\n");
1902 
1903     return HI_SUCCESS;
1904 }
1905 
1906 hi_s32 drv_hdmi_audio_output_enable_set(const hdmi_device *hdmi_dev, hi_bool enable)
1907 {
1908     hi_bool mute = enable ? HI_FALSE : HI_TRUE;
1909     hal_call_void(hal_hdmi_audio_mute_set, hdmi_dev->hal, mute);
1910     return HI_SUCCESS;
1911 }
1912 
1913 hi_s32 get_hdmi_thread_state_set(hdmi_device *hdmi_dev, hdmi_thread_state state)
1914 {
1915     hdmi_info(">>> in...\n");
1916 
1917     hdmi_if_null_return(hdmi_dev, HI_ERR_NULL_PTR);
1918 
1919     hdmi_info("state: %u\n", state);
1920     hdmi_dev->thread_info.thread_timer_sate = state;
1921     hdmi_info("<<< out...\n");
1922 
1923     return HI_SUCCESS;
1924 }
1925 
1926 static hi_s32 check_video_attr(const hdmi_vo_attr *vo_attr)
1927 {
1928     hdmi_if_null_return(vo_attr, HI_ERR_NULL_PTR);
1929 
1930     if (vo_attr->video_timing >= HDMI_VIDEO_TIMING_BUTT) {
1931         hdmi_err("video timing(%u) is wrong\n", vo_attr->video_timing);
1932         return HI_FAILURE;
1933     }
1934 
1935     if (vo_attr->in_color_space >= HDMI_COLORSPACE_BUTT) {
1936         hdmi_err("video in_color_space(%u) is wrong\n", vo_attr->in_color_space);
1937         return HI_FAILURE;
1938     }
1939 
1940     if (vo_attr->colorimetry != HDMI_COLORIMETRY_ITU_601 &&
1941         vo_attr->colorimetry != HDMI_COLORIMETRY_ITU_709 &&
1942         vo_attr->colorimetry != HDMI_COLORIMETRY_EXTEND) {
1943         hdmi_err("video colorimetry(%u) is wrong\n", vo_attr->colorimetry);
1944         return HI_FAILURE;
1945     }
1946 
1947     if (vo_attr->rgb_quantization > HDMI_QUANTIZATION_RANGE_FULL) {
1948         hdmi_err("video rgb_quantization(%u) is wrong\n", vo_attr->rgb_quantization);
1949         return HI_FAILURE;
1950     }
1951 
1952     if (vo_attr->picture_aspect != HDMI_PICTURE_ASPECT_4_3 &&
1953         vo_attr->picture_aspect != HDMI_PICTURE_ASPECT_16_9 &&
1954         vo_attr->picture_aspect != HDMI_PICTURE_ASPECT_64_27 &&
1955         vo_attr->picture_aspect != HDMI_PICTURE_ASPECT_256_135) {
1956         hdmi_err("video picture_aspect(%u) is wrong\n", vo_attr->picture_aspect);
1957         return HI_FAILURE;
1958     }
1959 
1960     if (vo_attr->in_bit_depth != HDMI_VIDEO_BITDEPTH_8 &&
1961         vo_attr->in_bit_depth != HDMI_VIDEO_BITDEPTH_10 &&
1962         vo_attr->in_bit_depth != HDMI_VIDEO_BITDEPTH_12) {
1963         hdmi_err("video in_bit_depth(%u) is wrong\n", vo_attr->in_bit_depth);
1964         return HI_FAILURE;
1965     }
1966 
1967     return HI_SUCCESS;
1968 }
1969 
1970 static hi_void hdmi_vo_colorimetry_cfg(const hdmi_vo_attr *vo_attr, hdmi_video_config *video_cfg)
1971 {
1972     switch (vo_attr->colorimetry) {
1973         case HDMI_COLORIMETRY_ITU_601:
1974             video_cfg->conv_std = HDMI_CONV_STD_BT_601;
1975             break;
1976         case HDMI_COLORIMETRY_ITU_709:
1977             video_cfg->conv_std = HDMI_CONV_STD_BT_709;
1978             break;
1979         case HDMI_COLORIMETRY_EXTEND:
1980             if (vo_attr->extended_colorimetry == HDMI_EXTENDED_COLORIMETRY_2020_NON_CONST_LUMINOUS) {
1981                 video_cfg->conv_std = HDMI_CONV_STD_BT_2020_NON_CONST_LUMINOUS;
1982             } else if (vo_attr->extended_colorimetry == HDMI_EXTENDED_COLORIMETRY_2020_CONST_LUMINOUS) {
1983                 video_cfg->conv_std = HDMI_CONV_STD_BT_2020_CONST_LUMINOUS;
1984             }
1985             break;
1986         default:
1987             video_cfg->conv_std = HDMI_CONV_STD_BT_709;
1988             break;
1989     }
1990 
1991     return;
1992 }
1993 
1994 static hi_void hdmi_attr_to_vid_cfg(hdmi_vo_attr *vo_attr, const hdmi_app_attr *app_attr, hdmi_video_config *video_cfg)
1995 {
1996     hdmi_if_null_return_void(vo_attr);
1997     hdmi_if_null_return_void(app_attr);
1998 
1999     video_cfg->pixel_clk =
2000         (app_attr->out_color_space == HDMI_COLORSPACE_YCBCR420) ? (vo_attr->clk_fs >> 1) : vo_attr->clk_fs;
2001     video_cfg->tmds_clk        = vo_attr->hdmi_adapt_pix_clk;
2002     video_cfg->in_bit_depth    = vo_attr->in_bit_depth;
2003     video_cfg->quantization    = vo_attr->rgb_quantization;
2004     video_cfg->in_color_space  = vo_attr->in_color_space;
2005     video_cfg->deep_color      = app_attr->deep_color_mode;
2006     video_cfg->out_color_space = app_attr->out_color_space;
2007     video_cfg->v_sync_pol      = vo_attr->v_sync_pol;
2008     video_cfg->h_sync_pol      = vo_attr->h_sync_pol;
2009     video_cfg->de_pol          = vo_attr->de_pol;
2010 
2011     if (video_cfg->out_color_space == HDMI_COLORSPACE_RGB) {
2012         vo_attr->rgb_quantization = app_attr->out_csc_quantization;
2013         vo_attr->ycc_quantization = (vo_attr->rgb_quantization == HDMI_QUANTIZATION_RANGE_FULL) ?
2014             HDMI_YCC_QUANTIZATION_RANGE_FULL : HDMI_YCC_QUANTIZATION_RANGE_LIMITED;
2015     } else {
2016         vo_attr->ycc_quantization = (app_attr->out_csc_quantization == HDMI_QUANTIZATION_RANGE_FULL) ?
2017             HDMI_YCC_QUANTIZATION_RANGE_FULL : HDMI_YCC_QUANTIZATION_RANGE_LIMITED;
2018         if (vo_attr->ycc_quantization == HDMI_YCC_QUANTIZATION_RANGE_FULL) {
2019             vo_attr->rgb_quantization = HDMI_QUANTIZATION_RANGE_FULL;
2020         } else {
2021             vo_attr->rgb_quantization = HDMI_QUANTIZATION_RANGE_DEFAULT;
2022         }
2023     }
2024 
2025     if (app_attr->out_color_space == HDMI_COLORSPACE_RGB) {
2026         video_cfg->out_csc_quantization = vo_attr->rgb_quantization;
2027     } else {
2028         switch (vo_attr->ycc_quantization) {
2029             case HDMI_YCC_QUANTIZATION_RANGE_FULL:
2030                 video_cfg->out_csc_quantization = HDMI_QUANTIZATION_RANGE_FULL;
2031                 break;
2032             default:
2033                 video_cfg->out_csc_quantization = HDMI_QUANTIZATION_RANGE_LIMITED;
2034                 break;
2035         }
2036     }
2037     hdmi_vo_colorimetry_cfg(vo_attr, video_cfg);
2038 
2039     return;
2040 }
2041 
2042 static hi_s32 hdmi_phy_set(hdmi_device *hdmi_dev, const hdmi_vo_attr *vo_attr)
2043 {
2044     hi_s32         ret      = HI_SUCCESS;
2045 #ifndef HDMI_FPGA_SUPPORT
2046     hdmi_phy_cfg   phy_cfg  = {0};
2047     hdmi_app_attr *app_attr = HI_NULL;
2048 
2049     hdmi_if_null_return(hdmi_dev, HI_ERR_NULL_PTR);
2050     app_attr = &hdmi_dev->attr.app_attr;
2051 
2052     /* PHY config */
2053     phy_cfg.pixel_clk  =
2054         (app_attr->out_color_space == HDMI_COLORSPACE_YCBCR420) ? (vo_attr->clk_fs >> 1) : vo_attr->clk_fs;
2055     phy_cfg.emi_enable = hdmi_dev->emi_enable;
2056     phy_cfg.tmds_clk   = vo_attr->hdmi_adapt_pix_clk;
2057     phy_cfg.deep_color = app_attr->deep_color_mode;
2058     phy_cfg.trace_len  = hdmi_dev->mode_param.trace_len;
2059 #ifdef HDMI_FRL_SUPPORT
2060     phy_cfg.color_space = app_attr->out_color_space;
2061     if (hdmi_dev->frl_info.mode == HDMI_FRL_MODE_FRL) {
2062         phy_cfg.mode_cfg = HDMI_PHY_MODE_CFG_FRL;
2063         (hi_void)memset_s(phy_cfg.aen_tx_ffe, sizeof(phy_cfg.aen_tx_ffe), FRL_TXFFE_MODE_0, sizeof(phy_cfg.aen_tx_ffe));
2064         phy_cfg.rate = (hdmi_work_mode)hdmi_dev->frl_info.rate_info.cur_rate;
2065     }
2066 #endif
2067     hal_call_void(hal_hdmi_phy_set, hdmi_dev->hal, &phy_cfg);
2068 #endif
2069 
2070     return ret;
2071 }
2072 
2073 static hi_s32 hdmi_csc_set(hdmi_device *hdmi_dev, hdmi_vo_attr *vo_attr)
2074 {
2075     hi_s32 ret = HI_SUCCESS;
2076     hdmi_video_config video_cfg = {0};
2077     hdmi_app_attr *app_attr = HI_NULL;
2078 
2079     hdmi_if_null_return(hdmi_dev, HI_ERR_NULL_PTR);
2080 
2081     app_attr = &hdmi_dev->attr.app_attr;
2082     hdmi_attr_to_vid_cfg(vo_attr, app_attr, &video_cfg);
2083     hal_call_void(hal_hdmi_csc_param_set, hdmi_dev->hal, &video_cfg);
2084 
2085     return ret;
2086 }
2087 
2088 static hi_s32 hdmi_video_path_set(hdmi_device *hdmi_dev, hdmi_vo_attr *vo_attr)
2089 {
2090     hdmi_video_config video_cfg = {0};
2091     hdmi_app_attr *app_attr = HI_NULL;
2092     hi_s32 ret = HI_SUCCESS;
2093 
2094     hdmi_if_null_return(hdmi_dev, HI_ERR_NULL_PTR);
2095 
2096     app_attr = &hdmi_dev->attr.app_attr;
2097     video_cfg.emi_enable = hdmi_dev->emi_enable;
2098 
2099     hdmi_attr_to_vid_cfg(vo_attr, app_attr, &video_cfg);
2100     hal_call_ret(ret, hal_hdmi_video_path_set, hdmi_dev->hal, &video_cfg);
2101     hdmi_csc_set(hdmi_dev, vo_attr);
2102 
2103 #ifdef HDMI_FRL_SUPPORT
2104     if (hdmi_dev->frl_info.mode == HDMI_FRL_MODE_TMDS) {
2105         hdmi_phy_set(hdmi_dev, vo_attr);
2106     }
2107 #else
2108     hdmi_phy_set(hdmi_dev, vo_attr);
2109 #endif
2110     return ret;
2111 }
2112 
2113 static hi_bool app_attr_is_changed(const hdmi_app_attr *hw_app_attr, const hdmi_app_attr *sw_app_attr)
2114 {
2115     hdmi_if_null_return(hw_app_attr, HI_FALSE);
2116     hdmi_if_null_return(sw_app_attr, HI_FALSE);
2117 
2118     if (hw_app_attr->enable_hdmi != sw_app_attr->enable_hdmi) {
2119         hdmi_info("hdmi enable change, old(%u)->new(%u)\n", hw_app_attr->enable_hdmi, sw_app_attr->enable_hdmi);
2120         return HI_TRUE;
2121     }
2122 
2123     if (hw_app_attr->out_color_space != sw_app_attr->out_color_space) {
2124         hdmi_info("out color_space change,old(%u)->new(%u)\n",
2125             hw_app_attr->out_color_space, sw_app_attr->out_color_space);
2126         return HI_TRUE;
2127     }
2128 
2129     if (((sw_app_attr->deep_color_mode == HDMI_DEEP_COLOR_OFF) ||
2130         (sw_app_attr->deep_color_mode == HDMI_DEEP_COLOR_24BIT)) &&
2131         ((hw_app_attr->deep_color_mode == HDMI_DEEP_COLOR_OFF) ||
2132         (hw_app_attr->deep_color_mode == HDMI_DEEP_COLOR_24BIT))) {
2133         hdmi_info("deepcolor mode not change: %u\n", hw_app_attr->deep_color_mode);
2134     } else if (hw_app_attr->deep_color_mode != sw_app_attr->deep_color_mode) {
2135         hdmi_info("deepcolor mode change,old(%u)->new(%u)\n",
2136             hw_app_attr->deep_color_mode, sw_app_attr->deep_color_mode);
2137         return HI_TRUE;
2138     }
2139 
2140     if (hw_app_attr->xvycc_mode != sw_app_attr->xvycc_mode) {
2141         hdmi_info("xvycc_mode mode change,old(%u)->new(%u)\n",
2142             hw_app_attr->xvycc_mode, sw_app_attr->xvycc_mode);
2143         return HI_TRUE;
2144     }
2145 
2146     if (hw_app_attr->enable_avi_infoframe != sw_app_attr->enable_avi_infoframe) {
2147         hdmi_info("avi infoframe enable change, old(%u)->new(%u)\n",
2148             hw_app_attr->enable_avi_infoframe, sw_app_attr->enable_avi_infoframe);
2149         return HI_TRUE;
2150     }
2151 
2152     if (hw_app_attr->out_csc_quantization != sw_app_attr->out_csc_quantization) {
2153         hdmi_info("out_csc_quantization change, old(%u)->new(%u)\n",
2154             hw_app_attr->out_csc_quantization, sw_app_attr->out_csc_quantization);
2155         return HI_TRUE;
2156     }
2157 
2158     return HI_FALSE;
2159 }
2160 
2161 static hi_bool vo_attr_is_changed(const hdmi_vo_attr *hw_vo_attr, hdmi_vo_attr *sw_vo_attr)
2162 {
2163     hdmi_if_null_return(hw_vo_attr, HI_FALSE);
2164     hdmi_if_null_return(sw_vo_attr, HI_FALSE);
2165 
2166     if (hw_vo_attr->video_timing != sw_vo_attr->video_timing) {
2167         hdmi_info("video timing change,old(%u)->new(%u)\n", hw_vo_attr->video_timing, sw_vo_attr->video_timing);
2168         return HI_TRUE;
2169     } else {
2170         /*
2171          * if timing is change, the sync param need according to user config, or not,
2172          * should not change the sync param.
2173          */
2174         sw_vo_attr->v_sync_pol = hw_vo_attr->v_sync_pol;
2175         sw_vo_attr->h_sync_pol = hw_vo_attr->h_sync_pol;
2176         sw_vo_attr->de_pol     = hw_vo_attr->de_pol;
2177     }
2178 
2179     if (hw_vo_attr->in_color_space != sw_vo_attr->in_color_space) {
2180         hdmi_info("input colorspace change, old(%u)->new(%u)\n",
2181             hw_vo_attr->in_color_space, sw_vo_attr->in_color_space);
2182         return HI_TRUE;
2183     }
2184     if (hw_vo_attr->stereo_mode != sw_vo_attr->stereo_mode) {
2185         hdmi_info("3d mode change, old(%u)->new(%u)\n", hw_vo_attr->stereo_mode, sw_vo_attr->stereo_mode);
2186         return HI_TRUE;
2187     }
2188     if (hw_vo_attr->pixel_repeat != sw_vo_attr->pixel_repeat) {
2189         hdmi_info("pixel repeation change, old(%u)->new(%u)\n", hw_vo_attr->pixel_repeat, sw_vo_attr->pixel_repeat);
2190         return HI_TRUE;
2191     }
2192     if (hw_vo_attr->colorimetry != sw_vo_attr->colorimetry) {
2193         hdmi_info("colorimetry change, old(%u)->new(%u)\n", hw_vo_attr->colorimetry, sw_vo_attr->colorimetry);
2194         return HI_TRUE;
2195     }
2196     if (hw_vo_attr->extended_colorimetry != sw_vo_attr->extended_colorimetry) {
2197         hdmi_info("extended_colorimetry change, old(%u)->new(%u)\n",
2198             hw_vo_attr->extended_colorimetry, sw_vo_attr->extended_colorimetry);
2199         return HI_TRUE;
2200     }
2201     if (hw_vo_attr->rgb_quantization != sw_vo_attr->rgb_quantization) {
2202         hdmi_info("RGB quantization change, old(%u)->new(%u)\n",
2203             hw_vo_attr->rgb_quantization, sw_vo_attr->rgb_quantization);
2204         return HI_TRUE;
2205     }
2206     if (hw_vo_attr->ycc_quantization != sw_vo_attr->ycc_quantization) {
2207         hdmi_info("YCC quantization change, old(%u)->new(%u)\n",
2208             hw_vo_attr->ycc_quantization, sw_vo_attr->ycc_quantization);
2209         return HI_TRUE;
2210     }
2211     if (hw_vo_attr->picture_aspect != sw_vo_attr->picture_aspect) {
2212         hdmi_info("picture aspect change, old(%u)->new(%u)\n", hw_vo_attr->picture_aspect, sw_vo_attr->picture_aspect);
2213         return HI_TRUE;
2214     }
2215 
2216     return HI_FALSE;
2217 }
2218 
2219 static hi_s32 check_app_attr(const hdmi_app_attr *app_attr)
2220 {
2221     hi_s32 ret = HI_SUCCESS;
2222 
2223     if (app_attr->out_color_space != HDMI_COLORSPACE_RGB &&
2224         app_attr->out_color_space != HDMI_COLORSPACE_YCBCR422 &&
2225         app_attr->out_color_space != HDMI_COLORSPACE_YCBCR444 &&
2226         app_attr->out_color_space != HDMI_COLORSPACE_YCBCR420) {
2227         hdmi_err("out_color_space=%u is wrong\n", app_attr->out_color_space);
2228         ret += HI_FAILURE;
2229     }
2230 
2231     if (app_attr->deep_color_mode != HDMI_DEEP_COLOR_24BIT &&
2232         app_attr->deep_color_mode != HDMI_DEEP_COLOR_30BIT &&
2233         app_attr->deep_color_mode != HDMI_DEEP_COLOR_36BIT &&
2234         app_attr->deep_color_mode != HDMI_DEEP_COLOR_48BIT &&
2235         app_attr->deep_color_mode != HDMI_DEEP_COLOR_OFF) {
2236         hdmi_err("deep_clr_mode=%u is wrong\n", app_attr->deep_color_mode);
2237         ret += HI_FAILURE;
2238     }
2239 
2240     if (app_attr->hdcp_mode != HDMI_HDCP_MODE_1_4 &&
2241         app_attr->hdcp_mode != HDMI_HDCP_MODE_2_2 &&
2242         app_attr->hdcp_mode != HDMI_HDCP_MODE_AUTO) {
2243         hdmi_err("hdcp_mode=%u is wrong\n", app_attr->hdcp_mode);
2244         ret += HI_FAILURE;
2245     }
2246 
2247     return (ret != HI_SUCCESS) ? HI_FAILURE : HI_SUCCESS;
2248 }
2249 
2250 #ifdef HDMI_HDR_SUPPORT
2251 static hi_void colormetry_hdr2vo(hdmi_hdr_colormetry hdr_colorimetry, hdmi_colormetry *vo_colorimetry)
2252 {
2253     switch (hdr_colorimetry) {
2254         case HDMI_HDR_COLORIMETRY_NONE:
2255             *vo_colorimetry = HDMI_COLORIMETRY_NONE;
2256             break;
2257         case HDMI_HDR_COLORIMETRY_ITU_601:
2258             *vo_colorimetry = HDMI_COLORIMETRY_ITU_601;
2259             break;
2260         case HDMI_HDR_COLORIMETRY_ITU_709:
2261             *vo_colorimetry = HDMI_COLORIMETRY_ITU_709;
2262             break;
2263         case HDMI_HDR_COLORIMETRY_EXTENDED:
2264             *vo_colorimetry = HDMI_COLORIMETRY_EXTEND;
2265             break;
2266         default:
2267             break;
2268     }
2269 
2270     return;
2271 }
2272 
2273 static hi_void hdr_mode_check(hdmi_device *hdmi_dev, hdmi_vo_attr *vo_attr, hdmi_app_attr *app_attr)
2274 {
2275     drv_hdmi_hdr_attr *hdr_attr = HI_NULL;
2276 
2277     hdmi_if_null_return_void(hdmi_dev);
2278     hdmi_if_null_return_void(vo_attr);
2279 
2280     hdr_attr = &(hdmi_dev->attr.hdr_attr);
2281     switch (hdr_attr->user_hdr_mode) {
2282         case HDMI_HDR_USERMODE_DOLBY:
2283             vo_attr->ycc_quantization   = HDMI_YCC_QUANTIZATION_RANGE_LIMITED;
2284             app_attr->out_color_space   = HDMI_COLORSPACE_YCBCR444;
2285             vo_attr->hdmi_adapt_pix_clk = vo_attr->clk_fs;
2286             app_attr->deep_color_mode   = HDMI_DEEP_COLOR_24BIT;
2287             vo_attr->rgb_quantization   = HDMI_QUANTIZATION_RANGE_DEFAULT;
2288             break;
2289         case HDMI_HDR_USERMODE_HDR10:
2290             if (hdr_attr->hdr_mode == HDMI_HDR_MODE_CEA_861_3) {
2291                 if (hdr_attr->colorimetry > HDMI_HDR_COLORIMETRY_EXTENDED) {
2292                     vo_attr->colorimetry = HDMI_COLORIMETRY_EXTEND;
2293                     vo_attr->extended_colorimetry =
2294                         hdr_attr->colorimetry - HDMI_HDR_EXTENDED_COLORIMETRY_XV_YCC_601;
2295                 } else {
2296                     colormetry_hdr2vo(hdr_attr->colorimetry, &vo_attr->colorimetry);
2297                     vo_attr->extended_colorimetry = HDMI_EXTENDED_COLORIMETRY_BUTT;
2298                 }
2299                 app_attr->xvycc_mode = HI_FALSE;
2300             }
2301             break;
2302         default:
2303             break;
2304     }
2305     hdmi_info("user hdr mode:%u, actual hdr mode:%u \n", hdr_attr->user_hdr_mode, hdr_attr->hdr_mode);
2306 
2307     return;
2308 }
2309 #endif
2310 
2311 static hi_void drv_hdmi_vou_dither_set(const hdmi_app_attr *app_attr)
2312 {
2313 #ifdef HDMI_CHIP_HI3559AV100
2314     vou_export_func *vo_export_func = HI_NULL;
2315     vo_dither_out_bitwidth vou_dither_mode;
2316 
2317     vo_export_func = func_entry(vou_export_func, HI_ID_VO);
2318     if (vo_export_func != HI_NULL && vo_export_func->pfn_vou_set_dither_out_bit_width != HI_NULL) {
2319         if (app_attr->out_color_space == HDMI_COLORSPACE_YCBCR422) {
2320             /* 422 must disable dither */
2321             vou_dither_mode = DITHER_OUT_BITWIDTH_10;
2322         } else {
2323             vou_dither_mode = DITHER_OUT_BITWIDTH_10;
2324             if (app_attr->deep_color_mode == HDMI_DEEP_COLOR_24BIT ||
2325                 app_attr->deep_color_mode == HDMI_DEEP_COLOR_OFF) {
2326                 vou_dither_mode = DITHER_OUT_BITWIDTH_8;
2327             }
2328         }
2329         vo_export_func->pfn_vou_set_dither_out_bit_width(HI_ID_HDMI, 0, vou_dither_mode);
2330         hdmi_info("set VOU dither mode(%u)\n", vou_dither_mode);
2331     } else {
2332         hdmi_err("vo_export_func is NULL, VOU dither set error\n");
2333     }
2334 #else
2335     hi_unused(app_attr);
2336 #endif
2337 
2338     return;
2339 }
2340 
2341 static hi_bool hdmi_mode_change(const hdmi_device *hdmi_dev)
2342 {
2343 #ifdef HDMI_FRL_SUPPORT
2344     static hdmi_frl_mode pre_mode = HDMI_FRL_MODE_TMDS;
2345 
2346     if (pre_mode != hdmi_dev->frl_info.mode) {
2347         hdmi_info("hdmi mode change, %u to %u\n", pre_mode, hdmi_dev->frl_info.mode);
2348         pre_mode = hdmi_dev->frl_info.mode;
2349         return HI_TRUE;
2350     }
2351 #else
2352     hi_unused(hdmi_dev);
2353 #endif
2354 
2355     return HI_FALSE;
2356 }
2357 
2358 static hi_void hdmi_vo_attr_info(const hdmi_device *hdmi_dev, const hdmi_vo_attr *video_attr)
2359 {
2360     hdmi_info("clk_fs: %u\n", video_attr->clk_fs);
2361     hdmi_info("pixel_repeat: %u\n", video_attr->pixel_repeat);
2362     hdmi_info("video_timing: %u\n", video_attr->video_timing);
2363     hdmi_info("stereo_mode: %u\n", video_attr->stereo_mode);
2364     hdmi_info("in_color_space: %u\n", video_attr->in_color_space);
2365     hdmi_info("colorimetry: %u\n", video_attr->colorimetry);
2366     hdmi_info("extended_colorimetry: %u\n", video_attr->extended_colorimetry);
2367     hdmi_info("rgb_quantization: %u\n", video_attr->rgb_quantization);
2368     hdmi_info("ycc_quantization: %u\n", video_attr->ycc_quantization);
2369     hdmi_info("picture_aspect: %u\n", video_attr->picture_aspect);
2370     hdmi_info("active_aspect: %u\n", video_attr->active_aspect);
2371     hdmi_info("picture_scaling: %u\n", video_attr->picture_scaling);
2372     hdmi_info("in_bit_depth: %u\n", video_attr->in_bit_depth);
2373     hdmi_info("disp_fmt: %u\n", video_attr->disp_fmt);
2374     hdmi_info("v_sync_pol: %u\n", video_attr->v_sync_pol);
2375     hdmi_info("h_sync_pol: %u\n", video_attr->h_sync_pol);
2376     hdmi_info("de_pol: %u\n", video_attr->de_pol);
2377 #ifdef HDMI_HDR_SUPPORT
2378     hdmi_info("user_hdr_mode: %u\n", hdmi_dev->attr.hdr_attr.user_hdr_mode);
2379 #else
2380     hi_unused(hdmi_dev);
2381 #endif
2382 
2383     return;
2384 }
2385 
2386 static hi_s32 hdmi_format_is_change(hdmi_device *hdmi_dev, const hdmi_vo_attr *video_attr)
2387 {
2388     errno_t ret;
2389     hdmi_app_attr           tmp_app                     = {0};
2390     hdmi_app_attr          *app_attr                    = HI_NULL;
2391     hi_bool                 enable_clr_space_adapt_back = HI_TRUE;
2392     hi_bool                 enable_deep_clr_adapt_back  = HI_TRUE;
2393     static hdmi_disp_format disp_fmt                    = HDMI_VIDEO_FORMAT_BUTT;
2394 
2395     app_attr = &hdmi_dev->attr.app_attr;
2396     enable_clr_space_adapt_back = app_attr->enable_clr_space_adapt;
2397     enable_deep_clr_adapt_back = app_attr->enable_deep_clr_adapt;
2398     ret = memcpy_s(&tmp_app, sizeof(tmp_app), app_attr, sizeof(*app_attr));
2399     hdmi_unequal_eok_return(ret, HI_ERR_HDMI_INVALID_PARA);
2400 
2401     /* when format is changed, force to enable  hdmi_color_and_bit_strategy */
2402     if (disp_fmt != video_attr->disp_fmt) {
2403         tmp_app.enable_clr_space_adapt = HI_TRUE;
2404         tmp_app.enable_deep_clr_adapt = HI_TRUE;
2405         disp_fmt = video_attr->disp_fmt;
2406     }
2407     if (hdmi_color_and_bit_strategy(hdmi_dev, &tmp_app) != HI_SUCCESS) {
2408         hdmi_err(" hdmi_color_and_bit_strategy fail\n");
2409         return HI_ERR_HDMI_STRATEGY_FAILED;
2410     }
2411 
2412     ret = memcpy_s(app_attr, sizeof(hdmi_dev->attr.app_attr), &tmp_app, sizeof(tmp_app));
2413     hdmi_unequal_eok_return(ret, HI_ERR_HDMI_INVALID_PARA);
2414     app_attr->enable_clr_space_adapt = enable_clr_space_adapt_back;
2415     app_attr->enable_deep_clr_adapt  = enable_deep_clr_adapt_back;
2416 
2417     return HI_SUCCESS;
2418 }
2419 
2420 hi_s32 drv_hdmi_vo_attr_set(hdmi_device *hdmi_dev, const hdmi_vo_attr *vo_attr)
2421 {
2422     errno_t ret;
2423     hdmi_attr hw_attr = {0};
2424     hdmi_vo_attr *video_attr = HI_NULL;
2425     hdmi_app_attr *app_attr = HI_NULL;
2426 
2427     hdmi_if_null_return(hdmi_dev, HI_ERR_NULL_PTR);
2428     hdmi_if_null_return(vo_attr, HI_ERR_NULL_PTR);
2429 
2430     if (check_video_attr(vo_attr) != HI_SUCCESS) {
2431         hdmi_err("check_video_attr fail\n");
2432         return HI_ERR_HDMI_INVALID_PARA;
2433     }
2434     video_attr = &hdmi_dev->attr.vo_attr;
2435     app_attr   = &hdmi_dev->attr.app_attr;
2436     ret = memcpy_s(video_attr, sizeof(*video_attr), vo_attr, sizeof(hdmi_vo_attr));
2437     hdmi_unequal_eok_return(ret, HI_ERR_HDMI_INVALID_PARA);
2438     hdmi_vo_attr_info(hdmi_dev, video_attr);
2439     if (hdmi_format_is_change(hdmi_dev, video_attr) != HI_SUCCESS) {
2440         return HI_ERR_HDMI_STRATEGY_FAILED;
2441     }
2442 #ifdef HDMI_HDR_SUPPORT
2443     hdmi_dev->hdr_mutex.attr_set = HI_TRUE;
2444     hdr_mode_check(hdmi_dev, video_attr, app_attr);
2445 #endif
2446 #ifdef HDMI_FRL_SUPPORT
2447     ret = drv_hdmi_frl_mode_strategy(hdmi_dev->hdmi_dev_id);
2448     if (ret == HDMI_EDID_DATA_INVALID) {
2449         return HI_SUCCESS;
2450     } else if (ret != HI_SUCCESS) {
2451         hdmi_err("FRL strategy fail\n");
2452         return HI_ERR_HDMI_FEATURE_NO_SUPPORT;
2453     }
2454 #endif
2455     hdmi_attr_construct(hdmi_dev, &hw_attr);
2456     if (!vo_attr_is_changed(&hw_attr.vo_attr, video_attr) &&
2457         !app_attr_is_changed(&hw_attr.app_attr, app_attr) && hdmi_mode_change(hdmi_dev) == HI_FALSE) {
2458         hdmi_info("the video and app attr is not changed\n");
2459         return HI_SUCCESS;
2460     }
2461     if (app_attr->enable_video) {
2462         hdmi_video_path_set(hdmi_dev, video_attr);
2463     }
2464     /*
2465      * HDMI is not support dither on hi3559_av100.
2466      * set output bit to VO. VO decide to whether enable dither or not.
2467      */
2468     drv_hdmi_vou_dither_set(app_attr);
2469     drv_hdmi_avi_infoframe_send(&hdmi_dev->info_frame, (app_attr->enable_hdmi && app_attr->enable_avi_infoframe));
2470     drv_hdmi_vendor_infoframe_send(&hdmi_dev->info_frame, app_attr->enable_hdmi, app_attr->enable_vsif_dolby);
2471 #ifdef HDMI_HDR_SUPPORT
2472     /* the drm infoframe is stop because software was reset in videopath, so re-enable it if the mode is HDR10. */
2473     if (hdmi_dev->attr.hdr_attr.hdr_mode == HDMI_HDR_MODE_CEA_861_3) {
2474         drv_hdmi_drm_infoframe_send(&hdmi_dev->info_frame, HI_FALSE);
2475         drv_hdmi_drm_infoframe_send(&hdmi_dev->info_frame, HI_TRUE);
2476     }
2477 #endif
2478 
2479     return HI_SUCCESS;
2480 }
2481 
2482 hi_s32 drv_hdmi_vo_attr_get(hdmi_device *hdmi_dev, hdmi_vo_attr *vo_attr)
2483 {
2484     errno_t ret;
2485     hdmi_info(">>> in...\n");
2486 
2487     hdmi_if_null_return(hdmi_dev, HI_ERR_NULL_PTR);
2488     hdmi_if_null_return(vo_attr, HI_ERR_NULL_PTR);
2489 
2490     ret = memcpy_s(vo_attr, sizeof(*vo_attr), &hdmi_dev->attr.vo_attr, sizeof(hdmi_vo_attr));
2491     hdmi_unequal_eok_return(ret, HI_ERR_HDMI_INVALID_PARA);
2492     hdmi_info("<<< out...\n");
2493 
2494     return HI_SUCCESS;
2495 }
2496 
2497 #ifdef HDMI_HDR_SUPPORT
2498 hi_s32 hdmi_hdr_attr_lock(hdmi_device *hdmi_dev)
2499 {
2500     hi_s32 ret = HI_FAILURE;
2501 
2502     hdmi_if_null_return(hdmi_dev, HI_ERR_NULL_PTR);
2503 
2504     osal_spin_lock(&hdmi_dev->hdr_mutex.attr_spin);
2505     if ((hdmi_dev->hdr_mutex.attr_busy == HI_TRUE) || (hdmi_dev->hdr_mutex.attr_set == HI_FALSE)) {
2506         osal_spin_unlock(&hdmi_dev->hdr_mutex.attr_spin);
2507         hdmi_warn("attr busy(%u), attr set(%u)!\n", hdmi_dev->hdr_mutex.attr_busy, hdmi_dev->hdr_mutex.attr_set);
2508         goto exit;
2509     }
2510 
2511     hdmi_dev->hdr_mutex.attr_busy = HI_TRUE;
2512     osal_spin_unlock(&hdmi_dev->hdr_mutex.attr_spin);
2513     ret = HI_SUCCESS;
2514 
2515 exit:
2516     return ret;
2517 }
2518 
2519 hi_s32 hdmi_attr_un_lock(hdmi_device *hdmi_dev)
2520 {
2521     hdmi_if_null_return(hdmi_dev, HI_ERR_NULL_PTR);
2522 
2523     osal_spin_lock(&hdmi_dev->hdr_mutex.attr_spin);
2524     hdmi_dev->hdr_mutex.attr_busy = HI_FALSE;
2525     osal_spin_unlock(&hdmi_dev->hdr_mutex.attr_spin);
2526 
2527     return HI_SUCCESS;
2528 }
2529 
2530 hi_s32 hdmi_attr_lock(hdmi_device *hdmi_dev)
2531 {
2532     hi_u32 timeout = ATTR_LOCK_WAIT_TIMEOUT;
2533 
2534     hdmi_if_null_return(hdmi_dev, HI_ERR_NULL_PTR);
2535 
2536     osal_spin_lock(&hdmi_dev->hdr_mutex.attr_spin);
2537     if (hdmi_dev->hdr_mutex.attr_busy == HI_FALSE) {
2538         hdmi_dev->hdr_mutex.attr_busy = HI_TRUE;
2539         osal_spin_unlock(&hdmi_dev->hdr_mutex.attr_spin);
2540         goto exit;
2541     }
2542     osal_spin_unlock(&hdmi_dev->hdr_mutex.attr_spin);
2543     while (timeout-- > 0) {
2544         osal_msleep(ATTR_LOCK_WAIT_TIME);
2545         osal_spin_lock(&hdmi_dev->hdr_mutex.attr_spin);
2546         if (hdmi_dev->hdr_mutex.attr_busy == HI_FALSE) {
2547             hdmi_dev->hdr_mutex.attr_busy = HI_TRUE;
2548             osal_spin_unlock(&hdmi_dev->hdr_mutex.attr_spin);
2549             goto exit;
2550         }
2551         osal_spin_unlock(&hdmi_dev->hdr_mutex.attr_spin);
2552     }
2553     hdmi_dev->hdr_mutex.attr_busy = HI_TRUE;
2554     hdmi_warn("time out(%u), force set attr!\n", timeout);
2555 
2556 exit:
2557     return HI_SUCCESS;
2558 }
2559 
2560 static hi_bool hdr_attr_is_change(const drv_hdmi_hdr *app_hdr_attr, const drv_hdmi_hdr_attr *hdr_attr)
2561 {
2562     hdmi_check_is_change_return(hdr_attr->hdr_mode, app_hdr_attr->hdr_attr.hdr_mode, HI_TRUE);
2563     hdmi_check_is_change_return(hdr_attr->eotf_type, app_hdr_attr->hdr_attr.eotf_type, HI_TRUE);
2564     hdmi_check_is_change_return(hdr_attr->metadata_id, app_hdr_attr->hdr_attr.metadata_id, HI_TRUE);
2565     hdmi_check_is_change_return(hdr_attr->colorimetry, app_hdr_attr->hdr_attr.colorimetry, HI_TRUE);
2566     hdmi_check_is_change_return(hdr_attr->un_descriptor.type1.primaries0_x,
2567                                 app_hdr_attr->hdr_attr.un_descriptor.type1.primaries0_x, HI_TRUE);
2568     hdmi_check_is_change_return(hdr_attr->un_descriptor.type1.primaries0_y,
2569                                 app_hdr_attr->hdr_attr.un_descriptor.type1.primaries0_y, HI_TRUE);
2570     hdmi_check_is_change_return(hdr_attr->un_descriptor.type1.primaries1_x,
2571                                 app_hdr_attr->hdr_attr.un_descriptor.type1.primaries1_x, HI_TRUE);
2572     hdmi_check_is_change_return(hdr_attr->un_descriptor.type1.primaries1_y,
2573                                 app_hdr_attr->hdr_attr.un_descriptor.type1.primaries1_y, HI_TRUE);
2574     hdmi_check_is_change_return(hdr_attr->un_descriptor.type1.primaries2_x,
2575                                 app_hdr_attr->hdr_attr.un_descriptor.type1.primaries2_x, HI_TRUE);
2576     hdmi_check_is_change_return(hdr_attr->un_descriptor.type1.primaries2_y,
2577                                 app_hdr_attr->hdr_attr.un_descriptor.type1.primaries2_y, HI_TRUE);
2578     hdmi_check_is_change_return(hdr_attr->un_descriptor.type1.max_luminance,
2579                                 app_hdr_attr->hdr_attr.un_descriptor.type1.max_luminance, HI_TRUE);
2580     hdmi_check_is_change_return(hdr_attr->un_descriptor.type1.min_luminance,
2581                                 app_hdr_attr->hdr_attr.un_descriptor.type1.min_luminance, HI_TRUE);
2582     hdmi_check_is_change_return(hdr_attr->un_descriptor.type1.max_light_level,
2583                                 app_hdr_attr->hdr_attr.un_descriptor.type1.max_light_level, HI_TRUE);
2584     hdmi_check_is_change_return(hdr_attr->un_descriptor.type1.average_light_level,
2585                                 app_hdr_attr->hdr_attr.un_descriptor.type1.average_light_level, HI_TRUE);
2586 
2587     return HI_FALSE;
2588 }
2589 
2590 static hi_s32 hdr_attr_check(const drv_hdmi_hdr *app_hdr_attr)
2591 {
2592     hdmi_if_null_return(app_hdr_attr, HI_ERR_NULL_PTR);
2593 
2594     if (app_hdr_attr->hdr_attr.hdr_mode >= HDMI_HDR_MODE_BUTT) {
2595         hdmi_err("hdmi hdr hdr_mode(%u) is wrong\n", app_hdr_attr->hdr_attr.hdr_mode);
2596         return HI_FAILURE;
2597     }
2598     if (app_hdr_attr->hdr_attr.eotf_type >= HDMI_EOTF_BUTT) {
2599         hdmi_err("hdmi hdr eotf_type(%u) is wrong\n", app_hdr_attr->hdr_attr.eotf_type);
2600         return HI_FAILURE;
2601     }
2602     if (app_hdr_attr->hdr_attr.metadata_id >= HDMI_HDR_METADATA_ID_BUTT) {
2603         hdmi_err("hdmi hdr metadata_id(%u) is wrong\n", app_hdr_attr->hdr_attr.metadata_id);
2604         return HI_FAILURE;
2605     }
2606     if (app_hdr_attr->hdr_attr.colorimetry > HDMI_HDR_EXTENDED_COLORIMETRY_2020_NON_CONST_LUMINOUW) {
2607         hdmi_err("hdmi hdr colorimetry(%u) is wrong\n", app_hdr_attr->hdr_attr.colorimetry);
2608         return HI_FAILURE;
2609     }
2610 
2611     return HI_SUCCESS;
2612 }
2613 
2614 static hi_void hdmi_zero_drm_infoframe_stop(hdmi_device *hdmi_dev)
2615 {
2616     if (hdmi_dev->attr.hdr_attr.hdr_mode != HDMI_HDR_MODE_CEA_861_3) {
2617         drv_hdmi_drm_infoframe_send(&hdmi_dev->info_frame, HI_FALSE);
2618         hdmi_info("zero DRM infoframe send timeout.\n");
2619     }
2620     return;
2621 }
2622 
2623 static hi_s32 hdmi_hdr_mode_change_timeout(const hdmi_device *hdmi_dev)
2624 {
2625     hi_s32 ret = HI_SUCCESS;
2626 
2627     if (hdmi_dev->hdr_info.hdr_debug_mode == HDMI_HDR_DEBUG_MODE_OE) {
2628         hdmi_phy_output_enable(hdmi_dev, HI_TRUE);
2629     }
2630     hal_call_void(hal_hdmi_avmute_set, hdmi_dev->hal, HI_FALSE);
2631     if (hdmi_dev->hdr_info.hdr_debug_mode == HDMI_HDR_DEBUG_MODE_OE) {
2632         drv_hdmi_black_data_set(hdmi_dev, HI_FALSE);
2633         ret = drv_hdmi_audio_output_enable_set(hdmi_dev, HI_TRUE);
2634     }
2635     hdmi_info("HDR mode change timeout, debug mode: %u.\n", hdmi_dev->hdr_info.hdr_debug_mode);
2636 
2637     return ret;
2638 }
2639 
2640 static hi_void hdmi_zero_drm_infoframe_timer_set(hdmi_device *hdmi_dev, hdmi_timer_config *timer)
2641 {
2642     hdmi_attr *attr = HI_NULL;
2643     hdmi_timer_config timer_cfg = {0};
2644 
2645     hdmi_if_null_return_void(hdmi_dev);
2646 
2647     attr = &hdmi_dev->attr;
2648     timer_cfg.timer_type  = HDMI_TIMER_ZERO_DRMIF;
2649     timer_cfg.timer_start = HI_FALSE;
2650     timer_cfg.time        = ZERO_DRMIF_SEND_TIME;
2651     hal_call_void(hal_hdmi_hdr_timer_set, hdmi_dev->hal, &timer_cfg);
2652     if (timer->timer_start == HI_FALSE) {
2653         return;
2654     }
2655     attr->hdr_attr.eotf_type   = HDMI_EOTF_SDR_LUMIN;
2656     attr->hdr_attr.metadata_id = HDMI_HDR_METADATA_ID_0;
2657     (hi_void)memset_s(&(attr->hdr_attr.un_descriptor), sizeof(attr->hdr_attr.un_descriptor),
2658         0, sizeof(hdmi_meta_descriptor));
2659     drv_hdmi_drm_infoframe_send(&hdmi_dev->info_frame, HI_TRUE);
2660 
2661     timer->timer_type = HDMI_TIMER_ZERO_DRMIF;
2662     hal_call_void(hal_hdmi_hdr_timer_set, hdmi_dev->hal, timer);
2663 
2664     return;
2665 }
2666 
2667 static hi_void hdmi_hdr_mode_change_timer_set(const hdmi_device *hdmi_dev, hdmi_timer_config *timer)
2668 {
2669     hdmi_timer_config timer_cfg = {0};
2670 
2671     hdmi_if_null_return_void(hdmi_dev);
2672 
2673     timer_cfg.timer_type  = HDMI_TIMER_SDR_TO_HDR10;
2674     timer_cfg.time        = HDRMODE_CHANGE_TIME;
2675     timer_cfg.timer_start = HI_FALSE;
2676 
2677     /* stop timer first. */
2678     hal_call_void(hal_hdmi_hdr_timer_set, hdmi_dev->hal, &timer_cfg);
2679     if (timer->timer_start == HI_FALSE) {
2680         return;
2681     }
2682     timer->timer_type = HDMI_TIMER_SDR_TO_HDR10;
2683     hal_call_void(hal_hdmi_hdr_timer_set, hdmi_dev->hal, timer);
2684 
2685     return;
2686 }
2687 
2688 static hi_void hdmi_timer_set(hdmi_device *hdmi_dev, hdmi_timer_config *timer)
2689 {
2690     hdmi_if_null_return_void(hdmi_dev);
2691 
2692     switch (timer->timer_type) {
2693         case HDMI_TIMER_ZERO_DRMIF:
2694             hdmi_zero_drm_infoframe_timer_set(hdmi_dev, timer);
2695             break;
2696         case HDMI_TIMER_SDR_TO_HDR10:
2697             hdmi_hdr_mode_change_timer_set(hdmi_dev, timer);
2698             break;
2699         default:
2700             break;
2701     }
2702 
2703     return;
2704 }
2705 
2706 static hi_void hdr_colorimetry_conv(hdmi_hdr_colormetry colorimetry, hdmi_vo_attr *vo_attr)
2707 {
2708     if (colorimetry >= HDMI_HDR_COLORIMETRY_EXTENDED) {
2709         vo_attr->colorimetry = HDMI_COLORIMETRY_EXTEND;
2710         vo_attr->extended_colorimetry = colorimetry - HDMI_HDR_EXTENDED_COLORIMETRY_XV_YCC_601;
2711     } else {
2712         switch (colorimetry) {
2713             case HDMI_HDR_COLORIMETRY_NONE:
2714                 vo_attr->colorimetry = HDMI_COLORIMETRY_NONE;
2715                 break;
2716             case HDMI_HDR_COLORIMETRY_ITU_601:
2717                 vo_attr->colorimetry = HDMI_COLORIMETRY_ITU_601;
2718                 break;
2719             case HDMI_HDR_COLORIMETRY_ITU_709:
2720                 vo_attr->colorimetry = HDMI_COLORIMETRY_ITU_709;
2721                 break;
2722             default:
2723                 break;
2724         }
2725         vo_attr->extended_colorimetry = HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
2726     }
2727 
2728     return;
2729 }
2730 
2731 static hi_s32 disable_hdr(hdmi_device *hdmi_dev, const drv_hdmi_hdr *app_hdr_attr)
2732 {
2733     hi_s32             ret      = HI_SUCCESS;
2734     hdmi_attr         *attr     = HI_NULL;
2735     drv_hdmi_hdr_attr *hdr_attr = HI_NULL;
2736     drv_hdmi_hdr_info *hdr_info = HI_NULL;
2737 
2738     hdmi_if_null_return(hdmi_dev, HI_ERR_NULL_PTR);
2739     hdmi_if_null_return(app_hdr_attr, HI_ERR_NULL_PTR);
2740 
2741     attr     = &(hdmi_dev->attr);
2742     hdr_attr = &(attr->hdr_attr);
2743     hdr_info = &(hdmi_dev->hdr_info);
2744 
2745     switch (hdr_attr->hdr_mode) {
2746         case HDMI_HDR_MODE_DISABLE:
2747             break;
2748         case HDMI_HDR_MODE_CEA_861_3:
2749             ret = memcpy_s(&attr->hdr_attr, sizeof(attr->hdr_attr),
2750                 &(app_hdr_attr->hdr_attr), sizeof(drv_hdmi_hdr_attr));
2751             hdmi_unequal_eok_return(ret, HI_ERR_HDMI_INVALID_PARA);
2752             if (hdr_info->hdr_debug_mode != HDMI_HDR_DEBUG_MODE_NONE) {
2753                 /* to solve the problem of some TV can not switch smoothly from HDR10 to non-HDR10. */
2754                 if (hdr_info->hdr_debug_mode == HDMI_HDR_DEBUG_MODE_OE) {
2755                     drv_hdmi_audio_output_enable_set(hdmi_dev, HI_FALSE);
2756                     drv_hdmi_black_data_set(hdmi_dev, HI_TRUE);
2757                 }
2758                 hal_call_void(hal_hdmi_avmute_set, hdmi_dev->hal, HI_TRUE);
2759 
2760                 if (hdr_info->hdr_debug_mode == HDMI_HDR_DEBUG_MODE_OE) {
2761                     hdmi_phy_output_enable(hdmi_dev, HI_FALSE);
2762                 }
2763                 hdr_info->hdr_mode_chn_timer.timer_start = HI_TRUE;
2764                 hdmi_timer_set(hdmi_dev, &(hdr_info->hdr_mode_chn_timer));
2765                 drv_hdmi_drm_infoframe_send(&hdmi_dev->info_frame, HI_FALSE);
2766             } else {
2767                 /* start timer, send zero DRMIF and stop after 2 seconds. */
2768                 hdr_info->zero_drm_if_timer.timer_start = HI_TRUE;
2769                 hdmi_timer_set(hdmi_dev, &(hdr_info->zero_drm_if_timer));
2770             }
2771             break;
2772         case HDMI_HDR_MODE_CEA_861_3_AUTHEN:
2773         case HDMI_HDR_MODE_DOLBY_NORMAL:
2774         case HDMI_HDR_MODE_DOLBY_TUNNELING:
2775             if (hdr_attr->hdr_mode != HDMI_HDR_MODE_DOLBY_NORMAL) {
2776                 hdmi_dev->attr.app_attr.out_color_space = HDMI_COLORSPACE_YCBCR444;
2777             }
2778             attr->vo_attr.rgb_quantization = HDMI_QUANTIZATION_RANGE_DEFAULT;
2779             attr->vo_attr.ycc_quantization = HDMI_YCC_QUANTIZATION_RANGE_LIMITED;
2780             break;
2781         default:
2782             ret = HI_FAILURE;
2783             break;
2784     }
2785 
2786     return ret;
2787 }
2788 
2789 hi_s32 change_to_hdr(hdmi_device *hdmi_dev, const drv_hdmi_hdr *app_hdr_attr)
2790 {
2791     hi_s32             ret      = HI_SUCCESS;
2792     hdmi_attr         *attr     = HI_NULL;
2793     hdmi_app_attr     *app_attr = HI_NULL;
2794     drv_hdmi_hdr_attr *hdr_attr = HI_NULL;
2795     drv_hdmi_hdr_info *hdr_info = HI_NULL;
2796 
2797     hdmi_if_null_return(hdmi_dev, HI_ERR_NULL_PTR);
2798     hdmi_if_null_return(app_hdr_attr, HI_ERR_NULL_PTR);
2799 
2800     attr     = &(hdmi_dev->attr);
2801     hdr_attr = &(attr->hdr_attr);
2802     app_attr = &(hdmi_dev->attr.app_attr);
2803     hdr_info = &(hdmi_dev->hdr_info);
2804 
2805     hdr_info->zero_drm_if_timer.timer_start = HI_FALSE;
2806     hdmi_zero_drm_infoframe_timer_set(hdmi_dev, &(hdr_info->zero_drm_if_timer));
2807     if (hdr_attr->user_hdr_mode != HDMI_HDR_USERMODE_HDR10) {
2808         hdmi_err("usermode is not HDR10/HLG.\n");
2809         return HI_FAILURE;
2810     }
2811     app_attr->enable_drm_infoframe = HI_TRUE;
2812 
2813     if (hdr_info->hdr_debug_mode != HDMI_HDR_DEBUG_MODE_NONE) {
2814         /* to solve the problem of some TV can not switch smoothly from non-HDR10 to HDR10. */
2815         if (hdr_info->hdr_debug_mode == HDMI_HDR_DEBUG_MODE_OE) {
2816             ret = drv_hdmi_audio_output_enable_set(hdmi_dev, HI_FALSE);
2817             drv_hdmi_black_data_set(hdmi_dev, HI_TRUE);
2818         }
2819         hal_call_void(hal_hdmi_avmute_set, hdmi_dev->hal, HI_TRUE);
2820         if (hdr_info->hdr_debug_mode == HDMI_HDR_DEBUG_MODE_OE) {
2821             hdmi_phy_output_enable(hdmi_dev, HI_FALSE);
2822         }
2823         hdr_info->hdr_mode_chn_timer.timer_start = HI_TRUE;
2824         hdmi_timer_set(hdmi_dev, &(hdr_info->hdr_mode_chn_timer));
2825     }
2826 
2827     return ret;
2828 }
2829 
2830 static hi_s32 hdmi_hdr_strategy(hdmi_device *hdmi_dev, const drv_hdmi_hdr *app_hdr_attr)
2831 {
2832     hdmi_attr         *attr     = HI_NULL;
2833     hdmi_app_attr     *app_attr = HI_NULL;
2834     drv_hdmi_hdr_attr *hdr_attr = HI_NULL;
2835 
2836     attr     = &hdmi_dev->attr;
2837     hdr_attr = &attr->hdr_attr;
2838     app_attr = &attr->app_attr;
2839 
2840     switch (app_hdr_attr->hdr_attr.hdr_mode) {
2841         case HDMI_HDR_MODE_CEA_861_3:
2842             change_to_hdr(hdmi_dev, app_hdr_attr);
2843             app_attr->enable_vsif_dolby = HI_FALSE;
2844             hdmi_info("HDR10 mode, colorimetry(%u), extended_colorimetry(%u)\n",
2845                       attr->vo_attr.colorimetry, attr->vo_attr.extended_colorimetry);
2846             break;
2847         case HDMI_HDR_MODE_CEA_861_3_AUTHEN:
2848             /* HDR10 authen mode, HDMI must bypass. */
2849             if (hdr_attr->user_hdr_mode != HDMI_HDR_USERMODE_DOLBY) {
2850                 hdmi_err("usermode is not dolby.\n");
2851                 return HI_FAILURE;
2852             }
2853             app_attr->enable_drm_infoframe = HI_TRUE;
2854             app_attr->enable_vsif_dolby = HI_FALSE;
2855             hdmi_info("hdr authen mode is enable! \n");
2856             break;
2857         case HDMI_HDR_MODE_DOLBY_NORMAL:
2858         case HDMI_HDR_MODE_DOLBY_TUNNELING:
2859             if (hdr_attr->user_hdr_mode != HDMI_HDR_USERMODE_DOLBY) {
2860                 hdmi_err("usermode is not dolby.\n");
2861                 return HI_FAILURE;
2862             }
2863             app_attr->enable_drm_infoframe = HI_FALSE;
2864             app_attr->enable_vsif_dolby = HI_TRUE;
2865             hdmi_info("dolby mode(%u) is enable! \n", app_hdr_attr->hdr_attr.hdr_mode);
2866             break;
2867         default:
2868             return HI_FAILURE;
2869     }
2870 
2871     return HI_SUCCESS;
2872 }
2873 
2874 static hi_s32 drv_hdmi_hdr_attr_set(hdmi_device *hdmi_dev, const drv_hdmi_hdr *app_hdr_attr)
2875 {
2876     errno_t errnumber;
2877     hi_s32 ret = HI_FAILURE;
2878     hdmi_app_attr *app_attr = HI_NULL;
2879 
2880     hdmi_if_null_return(hdmi_dev->hal, HI_ERR_NULL_PTR);
2881 
2882     app_attr = &hdmi_dev->attr.app_attr;
2883 
2884     if (hdr_attr_check(app_hdr_attr) != HI_SUCCESS) {
2885         hdmi_err("app_hdr_attr check failed!\n");
2886         return HI_FAILURE;
2887     }
2888     if (hdr_attr_is_change(app_hdr_attr, &hdmi_dev->attr.hdr_attr) == HI_FALSE) {
2889         hdmi_info("hdr attr not change, return.\n");
2890         return HI_SUCCESS;
2891     }
2892 
2893     if (hdmi_hdr_attr_lock(hdmi_dev) == HI_FAILURE) {
2894         goto exit;
2895     }
2896 
2897     if (app_hdr_attr->hdr_attr.colorimetry != hdmi_dev->attr.hdr_attr.colorimetry) {
2898         hdr_colorimetry_conv(app_hdr_attr->hdr_attr.colorimetry, &hdmi_dev->attr.vo_attr);
2899         hdmi_info("change colorimetry = %u, ext_colorimety = %u\n",
2900             hdmi_dev->attr.vo_attr.colorimetry, hdmi_dev->attr.vo_attr.extended_colorimetry);
2901     }
2902     /* change to SDR */
2903     if (app_hdr_attr->hdr_attr.hdr_mode == HDMI_HDR_MODE_DISABLE) {
2904         if (disable_hdr(hdmi_dev, app_hdr_attr) == HI_SUCCESS) {
2905             app_attr->enable_vsif_dolby = HI_FALSE;
2906             errnumber = memcpy_s(&hdmi_dev->attr.hdr_attr, sizeof(hdmi_dev->attr.hdr_attr),
2907                 &(app_hdr_attr->hdr_attr), sizeof(drv_hdmi_hdr_attr));
2908             hdmi_unequal_eok_return(errnumber, HI_ERR_HDMI_INVALID_PARA);
2909             goto send_inforame;
2910         } else {
2911             goto exit;
2912         }
2913     }
2914     /* change to HDR */
2915     errnumber = memcpy_s(&hdmi_dev->attr.hdr_attr, sizeof(hdmi_dev->attr.hdr_attr),
2916         &(app_hdr_attr->hdr_attr), sizeof(drv_hdmi_hdr_attr));
2917     hdmi_unequal_eok_return(errnumber, HI_ERR_HDMI_INVALID_PARA);
2918     ret = hdmi_hdr_strategy(hdmi_dev, app_hdr_attr);
2919     if (ret == HI_FAILURE) {
2920         goto exit;
2921     }
2922     drv_hdmi_drm_infoframe_send(&hdmi_dev->info_frame, app_attr->enable_hdmi && app_attr->enable_drm_infoframe);
2923 
2924 send_inforame:
2925     drv_hdmi_avi_infoframe_send(&hdmi_dev->info_frame, (app_attr->enable_hdmi && app_attr->enable_avi_infoframe));
2926     drv_hdmi_vendor_infoframe_send(&hdmi_dev->info_frame, app_attr->enable_hdmi, app_attr->enable_vsif_dolby);
2927     hdmi_csc_set(hdmi_dev, &hdmi_dev->attr.vo_attr);
2928 
2929 exit:
2930     hdmi_attr_un_lock(hdmi_dev);
2931 
2932     return ret;
2933 }
2934 #endif
2935 
2936 hi_s32 drv_hdmi_attr_get(const hdmi_device *hdmi_dev, hdmi_attr *attr)
2937 {
2938     errno_t errnumber;
2939     hdmi_info(">>> in...\n");
2940 
2941     hdmi_if_null_return(hdmi_dev, HI_ERR_NULL_PTR);
2942     hdmi_if_null_return(attr, HI_ERR_NULL_PTR);
2943 
2944     errnumber = memcpy_s(attr, sizeof(*attr), &hdmi_dev->attr, sizeof(hdmi_attr));
2945     hdmi_unequal_eok_return(errnumber, HI_ERR_HDMI_INVALID_PARA);
2946     hdmi_info("<<< out...\n");
2947 
2948     return HI_SUCCESS;
2949 }
2950 
2951 hi_s32 drv_hdmi_attr_set(hdmi_device *hdmi_dev, hdmi_attr *attr)
2952 {
2953     errno_t errnumber;
2954     hdmi_app_attr *app_attr = HI_NULL;
2955 
2956     hdmi_info(">>> in...\n");
2957 
2958     hdmi_if_null_return(hdmi_dev, HI_ERR_NULL_PTR);
2959     hdmi_if_null_return(hdmi_dev->hal, HI_ERR_NULL_PTR);
2960     hdmi_if_null_return(attr, HI_ERR_NULL_PTR);
2961 
2962     app_attr = &hdmi_dev->attr.app_attr;
2963     hdmi_info("enable_hdmi: %u\n", attr->app_attr.enable_hdmi);
2964     hdmi_info("enable_video: %u\n", attr->app_attr.enable_video);
2965     hdmi_info("enable_audio: %u\n", attr->app_attr.enable_audio);
2966     hdmi_info("out_color_space: %u\n", attr->app_attr.out_color_space);
2967     hdmi_info("deep_color_mode: %u\n", attr->app_attr.deep_color_mode);
2968     hdmi_info("bxv_ycc_mode: %u\n", attr->app_attr.xvycc_mode);
2969     hdmi_info("enable_avi_info_frame: %u\n", attr->app_attr.enable_avi_infoframe);
2970     hdmi_info("enable_spd_info_frame: %u\n", attr->app_attr.enable_spd_infoframe);
2971     hdmi_info("enable_mpeg_info_frame: %u\n", attr->app_attr.enable_mpeg_infoframe);
2972     hdmi_info("enable_aud_info_frame: %u\n", attr->app_attr.enable_aud_infoframe);
2973     hdmi_info("debug_flag: %u\n", attr->app_attr.debug_flag);
2974     hdmi_info("hdcp_enable: %u\n", attr->app_attr.hdcp_enable);
2975     hdmi_info("hdcp_mode: %u\n", attr->app_attr.hdcp_mode);
2976     hdmi_info("enable_clr_space_adapt: %u\n", attr->app_attr.enable_clr_space_adapt);
2977     hdmi_info("enable_deep_clr_adapt: %u\n", attr->app_attr.enable_deep_clr_adapt);
2978     hdmi_info("auth_mode: %u\n", attr->app_attr.auth_mode);
2979     hdmi_info("out_csc_quantization: %u\n", attr->app_attr.out_csc_quantization);
2980 
2981     if (check_app_attr(&attr->app_attr) != HI_SUCCESS) {
2982         hdmi_err("check hdmi attr fail\n");
2983         return HI_ERR_HDMI_INVALID_PARA;
2984     }
2985     if (hdmi_color_and_bit_strategy(hdmi_dev, &attr->app_attr) != HI_SUCCESS) {
2986         hdmi_err(" hdmi_color_and_bit_strategy fail\n");
2987         return HI_ERR_HDMI_STRATEGY_FAILED;
2988     }
2989     errnumber = memcpy_s(app_attr, sizeof(*app_attr), &attr->app_attr, sizeof(hdmi_app_attr));
2990     hdmi_unequal_eok_return(errnumber, HI_ERR_HDMI_INVALID_PARA);
2991     if (drv_hdmi_ao_attr_set(hdmi_dev, &attr->ao_attr) != HI_SUCCESS) {
2992         hdmi_err("drv_hdmi_ao_attr_set fail\n");
2993         return HI_ERR_HDMI_SET_ATTR_FAILED;
2994     }
2995     if (drv_hdmi_vo_attr_set(hdmi_dev, &attr->vo_attr) != HI_SUCCESS) {
2996         hdmi_err("drv_hdmi_vo_attr_set fail\n");
2997         return HI_ERR_HDMI_SET_ATTR_FAILED;
2998     }
2999     hdmi_info(">>> out...\n");
3000 
3001     return HI_SUCCESS;
3002 }
3003 
3004 hi_s32 drv_hdmi_infoframe_get(const hdmi_device *hdmi_dev, hdmi_infoframe_id infoframe_id, hdmi_infoframe *info_frame)
3005 {
3006     errno_t ret;
3007     hdmi_info(">>> in...\n");
3008 
3009     hdmi_if_null_return(hdmi_dev, HI_ERR_NULL_PTR);
3010     hdmi_if_null_return(info_frame, HI_ERR_NULL_PTR);
3011 
3012     switch (infoframe_id) {
3013         case HDMI_INFOFRAME_TYPE_VENDOR:
3014             ret = memcpy_s(&info_frame->vendor_infoframe, sizeof(info_frame->vendor_infoframe),
3015                 &hdmi_dev->info_frame.vendor_infoframe, sizeof(hdmi_vendor_infoframe));
3016             hdmi_unequal_eok_return(ret, HI_ERR_HDMI_INVALID_PARA);
3017             break;
3018         case HDMI_INFOFRAME_TYPE_AVI:
3019             ret = memcpy_s(&info_frame->avi_infoframe, sizeof(info_frame->avi_infoframe),
3020                 &hdmi_dev->info_frame.avi_infoframe, sizeof(hdmi_avi_infoframe));
3021             hdmi_unequal_eok_return(ret, HI_ERR_HDMI_INVALID_PARA);
3022             break;
3023         case HDMI_INFOFRAME_TYPE_AUDIO:
3024             ret = memcpy_s(&info_frame->audio_infoframe, sizeof(info_frame->audio_infoframe),
3025                 &hdmi_dev->info_frame.audio_infoframe, sizeof(hdmi_audio_infoframe));
3026             hdmi_unequal_eok_return(ret, HI_ERR_HDMI_INVALID_PARA);
3027             break;
3028         default:
3029             return HI_ERR_HDMI_FEATURE_NO_SUPPORT;
3030     }
3031     hdmi_info("<<< out...\n");
3032 
3033     return HI_SUCCESS;
3034 }
3035 
3036 static hi_void infoframe_set_vendor(hdmi_device *hdmi_dev, hdmi_infoframe *info_frame)
3037 {
3038     errno_t ret;
3039     hdmi_user_vsif_content *src_vsif_content = HI_NULL;
3040     hdmi_user_vsif_content *dest_vsif_content = HI_NULL;
3041 
3042     src_vsif_content = &info_frame->vendor_infoframe.vsif_content.cea861_vsif;
3043     dest_vsif_content = &hdmi_dev->info_frame.vendor_infoframe.vsif_content.cea861_vsif;
3044     /*
3045      * save the user data to pstHdmiDev->puInfoFrame,
3046      * because it will get the data form it when user call get infoframe.
3047      */
3048     dest_vsif_content->len = src_vsif_content->len;
3049     ret = memcpy_s(dest_vsif_content->data, HDMI_VENDOR_USER_DATA_MAX_LEN,
3050         src_vsif_content->data, src_vsif_content->len);
3051     hdmi_unequal_eok_return_void(ret);
3052     /* first: save user data to pstHdmiDev->vendor_data */
3053     hdmi_dev->vendor_data.len = src_vsif_content->len;
3054     (hi_void)memset_s(hdmi_dev->vendor_data.data, HDMI_VENDOR_USER_DATA_MAX_LEN, 0, HDMI_VENDOR_USER_DATA_MAX_LEN);
3055     ret = memcpy_s(hdmi_dev->vendor_data.data, HDMI_VENDOR_USER_DATA_MAX_LEN,
3056         src_vsif_content->data, src_vsif_content->len);
3057     hdmi_unequal_eok_return_void(ret);
3058     /* second: copy other information to puInfoFrame, except user data */
3059     src_vsif_content->ieee             = dest_vsif_content->ieee;
3060     src_vsif_content->format           = dest_vsif_content->format;
3061     src_vsif_content->vic              = dest_vsif_content->vic;
3062     src_vsif_content->_3d_meta_present = dest_vsif_content->_3d_meta_present;
3063     src_vsif_content->_3d_structure    = dest_vsif_content->_3d_structure;
3064 
3065     return;
3066 }
3067 
3068 static hi_void infoframe_set_avi_print(hdmi_avi_infoframe *src_avi_info)
3069 {
3070     hdmi_info("type: %u\n", src_avi_info->type);
3071     hdmi_info("version: %u\n", src_avi_info->version);
3072     hdmi_info("length: %u\n", src_avi_info->length);
3073     hdmi_info("colorspace: %u\n", src_avi_info->colorspace);
3074     hdmi_info("active_info_valid: %u\n", src_avi_info->active_info_valid);
3075     hdmi_info("horizontal_bar_valid: %u\n", src_avi_info->horizontal_bar_valid);
3076     hdmi_info("vertical_bar_valid: %u\n", src_avi_info->vertical_bar_valid);
3077     hdmi_info("scan_mode: %u\n", src_avi_info->scan_mode);
3078     hdmi_info("colorimetry: %u\n", src_avi_info->colorimetry);
3079     hdmi_info("picture_aspect: %u\n", src_avi_info->picture_aspect);
3080     hdmi_info("active_aspect: %u\n", src_avi_info->active_aspect);
3081     hdmi_info("itc: %u\n", src_avi_info->itc);
3082     hdmi_info("extended_colorimetry: %u\n", src_avi_info->extended_colorimetry);
3083     hdmi_info("quantization_range: %u\n", src_avi_info->quantization_range);
3084     hdmi_info("nups: %u\n", src_avi_info->nups);
3085     hdmi_info("video_timing: %u\n", src_avi_info->video_timing);
3086     hdmi_info("disp_fmt: %u\n", src_avi_info->disp_fmt);
3087     hdmi_info("ycc_quantization_range: %u\n", src_avi_info->ycc_quantization_range);
3088     hdmi_info("content_type: %u\n", src_avi_info->content_type);
3089     hdmi_info("pixel_repeat: %u\n", src_avi_info->pixel_repeat);
3090     hdmi_info("top_bar: %u\n", src_avi_info->top_bar);
3091     hdmi_info("bottom_bar: %u\n", src_avi_info->bottom_bar);
3092     hdmi_info("left_bar: %u\n", src_avi_info->left_bar);
3093     hdmi_info("right_bar: %u\n", src_avi_info->right_bar);
3094 }
3095 
3096 static hi_void infoframe_set_avi(hdmi_device *hdmi_dev, hdmi_infoframe *info_frame)
3097 {
3098     errno_t ret;
3099     hdmi_vo_attr       *vo_attr = &hdmi_dev->attr.vo_attr;
3100     hdmi_avi_infoframe *src_avi_info = &info_frame->avi_infoframe;
3101     hdmi_avi_infoframe *dest_avi_info = &hdmi_dev->info_frame.avi_infoframe;
3102 
3103     infoframe_set_avi_print(src_avi_info);
3104 
3105     if ((src_avi_info->type != dest_avi_info->type) || (src_avi_info->video_timing != dest_avi_info->video_timing) ||
3106         (src_avi_info->colorspace != dest_avi_info->colorspace) ||
3107         (src_avi_info->disp_fmt != dest_avi_info->disp_fmt) ||
3108         (src_avi_info->quantization_range != dest_avi_info->quantization_range) ||
3109         (src_avi_info->ycc_quantization_range != dest_avi_info->ycc_quantization_range) ||
3110         (src_avi_info->pixel_repeat != dest_avi_info->pixel_repeat)) {
3111         hdmi_warn("The current infoframe does not match the original infoframe!\n");
3112     }
3113     ret = memcpy_s(dest_avi_info, sizeof(*dest_avi_info), src_avi_info, sizeof(hdmi_avi_infoframe));
3114     hdmi_unequal_eok_return_void(ret);
3115 
3116     if (hdmi_dev->attr.app_attr.auth_mode == HI_TRUE) {
3117         // set aspect and colorimetry by attr
3118         vo_attr->picture_aspect       = dest_avi_info->picture_aspect;
3119         vo_attr->active_aspect        = dest_avi_info->active_aspect;
3120         vo_attr->colorimetry          = dest_avi_info->colorimetry;
3121         vo_attr->extended_colorimetry = dest_avi_info->extended_colorimetry;
3122         vo_attr->rgb_quantization     = dest_avi_info->quantization_range;
3123         vo_attr->ycc_quantization     = dest_avi_info->ycc_quantization_range;
3124         (hi_void) drv_hdmi_vo_attr_set(hdmi_dev, vo_attr);
3125     }
3126 
3127     return;
3128 }
3129 
3130 hi_s32 drv_hdmi_infoframe_set(hdmi_device *hdmi_dev, hdmi_infoframe_id infoframe_id, hdmi_infoframe *info_frame)
3131 {
3132     errno_t ret;
3133     hdmi_info(">>> in..., infoframe_id: %u\n", infoframe_id);
3134 
3135     hdmi_if_null_return(hdmi_dev, HI_ERR_NULL_PTR);
3136     hdmi_if_null_return(info_frame, HI_ERR_NULL_PTR);
3137 
3138     switch (infoframe_id) {
3139         case HDMI_INFOFRAME_TYPE_VENDOR:
3140             infoframe_set_vendor(hdmi_dev, info_frame);
3141             break;
3142         case HDMI_INFOFRAME_TYPE_AVI:
3143             infoframe_set_avi(hdmi_dev, info_frame);
3144             break;
3145         case HDMI_INFOFRAME_TYPE_AUDIO: {
3146             hdmi_audio_infoframe *src_audio_info = &info_frame->audio_infoframe;
3147             hdmi_audio_infoframe *dest_audio_info = &hdmi_dev->info_frame.audio_infoframe;
3148             ret = memcpy_s(dest_audio_info, sizeof(hdmi_dev->info_frame.audio_infoframe),
3149                 src_audio_info, sizeof(hdmi_audio_infoframe));
3150             hdmi_unequal_eok_return(ret, HI_ERR_HDMI_INVALID_PARA);
3151 
3152             hdmi_info("type: %u\n", dest_audio_info->type);
3153             hdmi_info("version: %u\n", dest_audio_info->version);
3154             hdmi_info("length: %u\n", dest_audio_info->length);
3155             hdmi_info("channels: %u\n", dest_audio_info->channels);
3156             hdmi_info("coding_type: %u\n", dest_audio_info->coding_type);
3157             hdmi_info("sample_size: %u\n", dest_audio_info->sample_size);
3158             hdmi_info("sample_frequency: %u\n", dest_audio_info->sample_frequency);
3159             hdmi_info("coding_type_ext: %u\n", dest_audio_info->coding_type_ext);
3160             hdmi_info("channel_allocation: %u\n", dest_audio_info->channel_allocation);
3161             hdmi_info("lfe_playback_level: %u\n", dest_audio_info->lfe_playback_level);
3162             hdmi_info("level_shift_value: %u\n", dest_audio_info->level_shift_value);
3163             hdmi_info("downmix_inhibit: %u\n", dest_audio_info->downmix_inhibit);
3164             hdmi_info("level_shift_value: %u\n", dest_audio_info->level_shift_value);
3165             break;
3166         }
3167         default:
3168             return HI_ERR_HDMI_INVALID_PARA;
3169     }
3170     if ((infoframe_id != HDMI_INFOFRAME_TYPE_AVI) || (hdmi_dev->attr.app_attr.auth_mode == HI_FALSE)) {
3171         drv_hdmi_infoframe_send(&hdmi_dev->info_frame, infoframe_id, info_frame);
3172     }
3173     hdmi_info("<<< out...\n");
3174 
3175     return HI_SUCCESS;
3176 }
3177 
3178 static hi_s32 drv_hdmi_status_get(const hdmi_device *hdmi_dev, hdmi_status *status)
3179 {
3180     hdmi_hardware_status hw_status = {0};
3181 
3182     hdmi_info(">>> in...\n");
3183 
3184     hdmi_if_null_return(hdmi_dev, HI_ERR_NULL_PTR);
3185     hdmi_if_null_return(status, HI_ERR_NULL_PTR);
3186 
3187     hal_call_void(hal_hdmi_hardware_status_get, hdmi_dev->hal, &hw_status);
3188 
3189     /* some TV sometimes has no hot_plug but has rsen */
3190     status->connected = (hw_status.common_status.hotplug || hw_status.common_status.rsen);
3191     status->sink_power_on = hw_status.common_status.rsen;
3192     hdmi_info("<<< out...\n");
3193 
3194     return HI_SUCCESS;
3195 }
3196 
3197 hi_s32 drv_hdmi_play_status_get(const hdmi_device *hdmi_dev, hi_u32 *play_status)
3198 {
3199     hdmi_if_null_return(hdmi_dev, HI_ERR_NULL_PTR);
3200     hdmi_if_null_return(play_status, HI_ERR_NULL_PTR);
3201     *play_status = ((hi_u32)hdmi_dev->run_state & HDMI_RUN_STATE_START) ? 1 : 0;
3202     return HI_SUCCESS;
3203 }
3204 
3205 hi_s32 get_hdmi_default_action_set(hdmi_device *hdmi_dev, hdmi_default_action action)
3206 {
3207     hdmi_info(">>> in..., action: %u\n", action);
3208     hdmi_if_null_return(hdmi_dev, HI_ERR_NULL_PTR);
3209     hdmi_dev->attr.app_attr.hdmi_action = action;
3210     hdmi_info("<<< out...\n");
3211 
3212     return HI_SUCCESS;
3213 }
3214 
3215 hi_s32 get_hdmi_delay_get(const hdmi_device *hdmi_dev, hdmi_delay *delay)
3216 {
3217     errno_t ret;
3218     hdmi_info(">>> in...\n");
3219 
3220     hdmi_if_null_return(hdmi_dev, HI_ERR_NULL_PTR);
3221     hdmi_if_null_return(delay, HI_ERR_NULL_PTR);
3222 
3223     ret = memcpy_s(delay, sizeof(*delay), &hdmi_dev->delay, sizeof(hdmi_delay));
3224     hdmi_unequal_eok_return(ret, HI_ERR_HDMI_INVALID_PARA);
3225     hdmi_info("<<< out...\n");
3226 
3227     return HI_SUCCESS;
3228 }
3229 
3230 hi_s32 get_hdmi_delay_set(hdmi_device *hdmi_dev, hdmi_delay *delay)
3231 {
3232     errno_t ret;
3233     hdmi_info(">>> in...\n");
3234 
3235     hdmi_if_null_return(hdmi_dev, HI_ERR_NULL_PTR);
3236     hdmi_if_null_return(delay, HI_ERR_NULL_PTR);
3237 
3238     if ((delay->fmt_delay > MAX_DELAY_TIME_MS) || (delay->mute_delay > MAX_DELAY_TIME_MS)) {
3239         hdmi_warn("delay time fmt: %u mute: %u over range: %u \n",
3240             delay->fmt_delay, delay->mute_delay, MAX_DELAY_TIME_MS);
3241         return HI_FAILURE;
3242     }
3243     ret = memcpy_s(&hdmi_dev->delay, sizeof(hdmi_delay), delay, sizeof(*delay));
3244     hdmi_unequal_eok_return(ret, HI_ERR_HDMI_INVALID_PARA);
3245     hdmi_info("force_mute_delay: %u, mute_delay: %u\n", delay->force_mute_delay, delay->mute_delay);
3246     hdmi_info("force_fmt_delay:  %u, fmt_delay:  %u\n", delay->force_fmt_delay, delay->fmt_delay);
3247     hdmi_info("<<< out...\n");
3248 
3249     return HI_SUCCESS;
3250 }
3251 
3252 static hi_s32 drv_hdmi_mod_param_set(hdmi_device *hdmi_dev, const drv_hdmi_mod_param *mode_param)
3253 {
3254     hdmi_mode_param *param = HI_NULL;
3255 
3256     hdmi_if_null_return(hdmi_dev, HI_ERR_NULL_PTR);
3257     hdmi_if_null_return(mode_param, HI_ERR_NULL_PTR);
3258 
3259     param = &hdmi_dev->mode_param;
3260     hdmi_info("set trace length: %u->%u\n", param->trace_len, mode_param->trace_len);
3261     param->trace_len = mode_param->trace_len;
3262 
3263     return HI_SUCCESS;
3264 }
3265 
3266 static hi_s32 drv_hdmi_mod_param_get(hdmi_device *hdmi_dev, drv_hdmi_mod_param *mode_param)
3267 {
3268     hdmi_mode_param *param = HI_NULL;
3269 
3270     hdmi_if_null_return(hdmi_dev, HI_ERR_NULL_PTR);
3271     hdmi_if_null_return(mode_param, HI_ERR_NULL_PTR);
3272 
3273     param = &hdmi_dev->mode_param;
3274     mode_param->trace_len = param->trace_len;
3275 
3276     return HI_SUCCESS;
3277 }
3278 
3279 #if defined(CONFIG_HI_PLATFORM_H8)
3280 static hi_s32 drv_hdmi_hw_spec_get(hdmi_device *hdmi_dev, hdmi_hw_spec *hw_spec)
3281 {
3282     hi_s32 ret;
3283 
3284     hdmi_info(">>> in...\n");
3285     hdmi_if_null_return(hdmi_dev, HI_ERR_NULL_PTR);
3286     hdmi_if_null_return(hdmi_dev->hal, HI_ERR_NULL_PTR);
3287     hdmi_if_null_return(hw_spec, HI_ERR_NULL_PTR);
3288 
3289     hal_call_ret(ret, hal_hdmi_phy_hw_spec_get, hdmi_dev->hal, hw_spec);
3290     hdmi_info("<<< out...\n");
3291 
3292     return ret;
3293 }
3294 
3295 hi_s32 drv_hdmi_hw_spec_set(hdmi_device *hdmi_dev, const hdmi_hw_spec *hw_spec)
3296 {
3297     hi_u8 i;
3298     hi_u32 tmds_clk;
3299     hi_s32 ret;
3300 
3301     hdmi_info(">>> in...\n");
3302 
3303     hdmi_if_null_return(hdmi_dev, HI_ERR_NULL_PTR);
3304     hdmi_if_null_return(hdmi_dev->hal, HI_ERR_NULL_PTR);
3305     hdmi_if_null_return(hw_spec, HI_ERR_NULL_PTR);
3306 
3307     tmds_clk = hdmi_dev->attr.vo_attr.hdmi_adapt_pix_clk;
3308     hdmi_info("tmds_clk : %u\n", tmds_clk);
3309     for (i = 0; i < HW_PARAM_ARRAY_COUNT; i++) {
3310         hdmi_info("stage[%u]: i_de_main_clk:%u i_de_main_data:%u\
3311             i_main_clk:%u i_main_data:%u ft_cap_clk:%u ft_cap_data:%u\n", i,
3312             hw_spec->hw_param[i].i_de_main_clk, hw_spec->hw_param[i].i_de_main_data,
3313             hw_spec->hw_param[i].i_main_clk, hw_spec->hw_param[i].i_main_data,
3314             hw_spec->hw_param[i].ft_cap_clk, hw_spec->hw_param[i].ft_cap_data);
3315     }
3316     hal_call_ret(ret, hal_hdmi_phy_hw_spec_set, hdmi_dev->hal, tmds_clk, hw_spec);
3317     hdmi_info("<<< out...\n");
3318 
3319     return ret;
3320 }
3321 #endif
3322 
3323 static hi_s32 hdmi_file_open(void *private_data)
3324 {
3325     hi_unused(private_data);
3326     osal_atomic_inc_return(&g_hdmi_count);
3327 
3328     return HI_SUCCESS;
3329 }
3330 
3331 static hi_s32 hdmi_file_close(void *private_data)
3332 {
3333     hi_u32 hdmi_id = 0;
3334     hdmi_device *hdmi_dev = HI_NULL;
3335 
3336     hi_unused(private_data);
3337     if (osal_atomic_read(&g_hdmi_count)) {
3338         osal_atomic_dec_return(&g_hdmi_count);
3339         for (; hdmi_id < HDMI_DEVICE_ID_BUTT; hdmi_id++) {
3340             hdmi_dev = get_hdmi_device(hdmi_id);
3341             hdmi_if_null_return(hdmi_dev, HI_ERR_NULL_PTR);
3342             hdmi_mutex_lock(g_hdmi_mutex);
3343             drv_hdmi_close(hdmi_dev, HI_TRUE);
3344             hdmi_mutex_unlock(g_hdmi_mutex);
3345         }
3346     }
3347 
3348     return HI_SUCCESS;
3349 }
3350 
3351 static hi_s32 hdmi21_caps_check(hdmi_device *hdmi_dev, const hdmi_property *attr)
3352 {
3353 #ifndef HDMI_FRL_SUPPORT
3354     hi_bool is_4k = HI_FALSE;
3355 
3356     is_4k = (attr->disp_fmt == HDMI_VIDEO_FORMAT_3840X2160P_50) ||
3357             (attr->disp_fmt == HDMI_VIDEO_FORMAT_3840X2160P_60) ||
3358             (attr->disp_fmt == HDMI_VIDEO_FORMAT_4096X2160P_50) ||
3359             (attr->disp_fmt == HDMI_VIDEO_FORMAT_4096X2160P_60);
3360 
3361     if (is_4k == HI_TRUE &&
3362         (attr->out_color_space == HDMI_COLORSPACE_RGB || attr->out_color_space == HDMI_COLORSPACE_YCBCR444) &&
3363         (attr->deep_color_mode == HDMI_DEEP_COLOR_30BIT || attr->deep_color_mode == HDMI_DEEP_COLOR_36BIT)) {
3364         hdmi_err("param is invalid, fmt = %u, colorspace = %u, deepcolor = %u\n",
3365             attr->disp_fmt, attr->out_color_space, attr->deep_color_mode);
3366         return HI_ERR_HDMI_FEATURE_NO_SUPPORT;
3367     }
3368 #else
3369     hi_unused(attr);
3370 #endif
3371 
3372     hi_unused(hdmi_dev);
3373     return HI_SUCCESS;
3374 }
3375 
3376 static hi_void hdmi_property_vo_attr_adapt(hdmi_vo_attr *vo_attr, const hdmi_property *prop)
3377 {
3378     hi_bool aspect_is43 = HI_FALSE;
3379 
3380     vo_attr->disp_fmt     = prop->disp_fmt;
3381     vo_attr->video_timing = prop->video_timing;
3382 #if (!defined(CONFIG_HI_PLATFORM_H8))
3383     vo_attr->in_color_space = prop->in_color_space;
3384 #endif
3385     vo_attr->clk_fs = prop->pix_clk;
3386 
3387     aspect_is43 = ((vo_attr->video_timing == HDMI_VIDEO_TIMING_640X480P_60000) ||
3388                    (vo_attr->video_timing == HDMI_VIDEO_TIMING_720X480P_60000) ||
3389                    (vo_attr->video_timing == HDMI_VIDEO_TIMING_720X576P_50000) ||
3390                    (vo_attr->video_timing == HDMI_VIDEO_TIMING_1440X240P_60000) ||
3391                    (vo_attr->video_timing == HDMI_VIDEO_TIMING_1440X288P_50000) ||
3392                    (vo_attr->video_timing == HDMI_VIDEO_TIMING_1440X480I_60000) ||
3393                    (vo_attr->video_timing == HDMI_VIDEO_TIMING_1440X576I_50000) ||
3394                    (vo_attr->video_timing == HDMI_VIDEO_TIMING_1440X576P_50000) ||
3395                    (vo_attr->video_timing == HDMI_VIDEO_TIMING_1440X576I_60000));
3396     if (aspect_is43 == HI_TRUE) {
3397         vo_attr->picture_aspect = HDMI_PICTURE_ASPECT_4_3;
3398     } else if (vo_attr->video_timing <= HDMI_VIDEO_TIMING_4096X2160P_120000 &&
3399                vo_attr->video_timing >= HDMI_VIDEO_TIMING_4096X2160P_24000) {
3400         vo_attr->picture_aspect = HDMI_PICTURE_ASPECT_256_135;
3401     } else {
3402         vo_attr->picture_aspect = HDMI_PICTURE_ASPECT_16_9;
3403     }
3404 
3405     return;
3406 }
3407 
3408 static hi_void drv_hdmi_property_app_attr_init(hdmi_app_attr *app_attr, const hdmi_property *prop)
3409 {
3410     app_attr->enable_hdmi           = prop->enable_hdmi;
3411     app_attr->enable_video          = prop->enable_video;
3412     app_attr->enable_audio          = prop->enable_audio;
3413     app_attr->auth_mode             = prop->auth_mode;
3414     app_attr->hdmi_action           = prop->hdmi_action;
3415     app_attr->deep_color_mode       = prop->deep_color_mode;
3416     app_attr->enable_avi_infoframe  = prop->enable_avi_infoframe;
3417     app_attr->enable_aud_infoframe  = prop->enable_aud_infoframe;
3418     app_attr->enable_deep_clr_adapt = prop->enable_deep_clr_adapt;
3419 #if (!defined(CONFIG_HI_PLATFORM_H8))
3420     app_attr->enable_clr_space_adapt = prop->enable_vid_mode_adapt;
3421     app_attr->out_csc_quantization   = prop->out_csc_quantization;
3422     app_attr->out_color_space        = prop->out_color_space;
3423 #endif
3424 }
3425 
3426 static hi_s32 drv_hdmi_property_set(hdmi_device_id hdmi_id, const hdmi_property *prop)
3427 {
3428     errno_t errnumber;
3429     hi_s32 ret;
3430     hdmi_app_attr tmp = {0};
3431     hdmi_ao_attr  ao_attr = {0};
3432     hdmi_vo_attr  vo_attr = {0};
3433     hdmi_device *hdmi_dev = HI_NULL;
3434     hdmi_app_attr *app_attr = HI_NULL;
3435 
3436     hdmi_if_null_return(prop, HI_ERR_NULL_PTR);
3437     hdmi_dev = get_hdmi_device(hdmi_id);
3438     hdmi_if_null_return(hdmi_dev, HI_ERR_NULL_PTR);
3439     ret = hdmi21_caps_check(hdmi_dev, prop);
3440     hdmi_if_failure_return(ret, HI_ERR_HDMI_FEATURE_NO_SUPPORT);
3441 
3442     app_attr = &hdmi_dev->attr.app_attr;
3443     errnumber = memcpy_s(&tmp, sizeof(tmp), app_attr, sizeof(hdmi_app_attr));
3444     hdmi_unequal_eok_return(errnumber, HI_ERR_HDMI_INVALID_PARA);
3445     errnumber = memcpy_s(&vo_attr, sizeof(vo_attr), &hdmi_dev->attr.vo_attr, sizeof(hdmi_vo_attr));
3446     hdmi_unequal_eok_return(errnumber, HI_ERR_HDMI_INVALID_PARA);
3447     errnumber = memcpy_s(&ao_attr, sizeof(ao_attr), &hdmi_dev->attr.ao_attr, sizeof(hdmi_ao_attr));
3448     hdmi_unequal_eok_return(errnumber, HI_ERR_HDMI_INVALID_PARA);
3449 
3450     drv_hdmi_property_app_attr_init(app_attr, prop);
3451     hdmi_property_vo_attr_adapt(&vo_attr, prop);
3452     ret = drv_hdmi_vo_attr_set(hdmi_dev, &vo_attr);
3453     if (ret != HI_SUCCESS) {
3454         hdmi_err("set voattr error\n");
3455         goto err;
3456     }
3457 
3458     ao_attr.sample_fs    = prop->sample_rate;
3459     ao_attr.sample_depth = prop->bit_depth;
3460     ret = drv_hdmi_ao_attr_set(hdmi_dev, &ao_attr);
3461     if (ret != HI_SUCCESS) {
3462         hdmi_err("set aoattr error\n");
3463         goto err;
3464     }
3465 
3466     return HI_SUCCESS;
3467 
3468 err:
3469     /* property set failed, recover the app_attr */
3470     errnumber = memcpy_s(app_attr, sizeof(hdmi_dev->attr.app_attr), &tmp, sizeof(hdmi_app_attr));
3471     hdmi_unequal_eok_return(errnumber, HI_ERR_HDMI_INVALID_PARA);
3472 
3473     return ret;
3474 }
3475 
3476 static hi_s32 drv_hdmi_property_get(hdmi_device_id hdmi_id, hdmi_property *prop)
3477 {
3478     hdmi_attr *attr = HI_NULL;
3479     hdmi_device *hdmi_dev = HI_NULL;
3480 
3481     hdmi_dev = get_hdmi_device(hdmi_id);
3482     hdmi_if_null_return(hdmi_dev, HI_ERR_NULL_PTR);
3483 
3484     attr = &hdmi_dev->attr;
3485     prop->enable_hdmi           = attr->app_attr.enable_hdmi;
3486     prop->enable_video          = attr->app_attr.enable_video;
3487     prop->enable_audio          = attr->app_attr.enable_audio;
3488     prop->video_timing          = attr->vo_attr.video_timing;
3489     prop->disp_fmt              = attr->vo_attr.disp_fmt;
3490     prop->enable_avi_infoframe  = attr->app_attr.enable_avi_infoframe;
3491     prop->enable_aud_infoframe  = attr->app_attr.enable_aud_infoframe;
3492     prop->enable_vid_mode_adapt = attr->app_attr.enable_clr_space_adapt;
3493     prop->enable_deep_clr_adapt = attr->app_attr.enable_deep_clr_adapt;
3494     prop->auth_mode             = attr->app_attr.auth_mode;
3495     prop->in_color_space        = attr->vo_attr.in_color_space;
3496     prop->out_color_space       = attr->app_attr.out_color_space;
3497     prop->deep_color_mode       = attr->app_attr.deep_color_mode;
3498     prop->out_csc_quantization  = attr->app_attr.out_csc_quantization;
3499     prop->hdmi_action           = attr->app_attr.hdmi_action;
3500     prop->sample_rate           = attr->ao_attr.sample_fs;
3501     prop->pix_clk               = attr->vo_attr.clk_fs;
3502     prop->bit_depth             = attr->ao_attr.sample_depth;
3503 
3504     return HI_SUCCESS;
3505 }
3506 
3507 #ifdef CONFIG_COMPAT
3508 hi_s32 drv_hdmi_compat_cmd_process(unsigned int cmd, hi_void *arg, hi_bool user)
3509 {
3510     hi_void __user *argp = (hi_void __user *)arg;
3511     return drv_hdmi_cmd_process(cmd, argp, user);
3512 }
3513 #endif
3514 
3515 static hi_s32 hdmi_ioctrl_init(hi_void *arg, hi_bool user)
3516 {
3517     hi_unused(arg);
3518     hi_unused(user);
3519     return drv_hdmi_init();
3520 }
3521 
3522 static hi_s32 hdmi_ioctrl_deinit(hi_void *arg, hi_bool user)
3523 {
3524     hi_unused(arg);
3525     hi_unused(user);
3526     return drv_hdmi_deinit();
3527 }
3528 
3529 static hi_s32 hdmi_ioctrl_open(hi_void *arg, hi_bool user)
3530 {
3531     hi_s32 ret;
3532 
3533     hdmi_open *open = HI_NULL;
3534     hdmi_device *hdmi_dev = HI_NULL;
3535 
3536     hdmi_info("CMD_HDMI_OPEN user=%u\n", user);
3537 
3538     open = (hdmi_open *)arg;
3539     hdmi_if_null_return(open, HI_ERR_NULL_PTR);
3540     hdmi_dev = get_hdmi_device(open->hdmi_id);
3541     hdmi_if_null_return(hdmi_dev, HI_ERR_NULL_PTR);
3542 
3543     hdmi_mutex_lock(g_hdmi_mutex);
3544     get_hdmi_default_action_set(hdmi_dev, open->default_mode);
3545     ret = drv_hdmi_open(hdmi_dev, user);
3546     hdmi_mutex_unlock(g_hdmi_mutex);
3547 
3548     return ret;
3549 }
3550 
3551 static hi_s32 hdmi_ioctrl_close(hi_void *arg, hi_bool user)
3552 {
3553     hi_s32 ret;
3554     hdmi_device *hdmi_dev = HI_NULL;
3555 
3556     hdmi_info("CMD_HDMI_CLOSE user=%u\n", user);
3557 
3558     hdmi_if_null_return(arg, HI_ERR_NULL_PTR);
3559     hdmi_dev = get_hdmi_device(*(hdmi_device_id *)arg);
3560     hdmi_if_null_return(hdmi_dev, HI_ERR_NULL_PTR);
3561 
3562     hdmi_mutex_lock(g_hdmi_mutex);
3563     ret = drv_hdmi_close(hdmi_dev, user);
3564     hdmi_mutex_unlock(g_hdmi_mutex);
3565 
3566     return ret;
3567 }
3568 
3569 static hi_s32 hdmi_ioctrl_start(hi_void *arg, hi_bool user)
3570 {
3571     hi_s32 ret;
3572     hdmi_device *hdmi_dev = HI_NULL;
3573 
3574     hdmi_info("CMD_HDMI_START user=%u\n", user);
3575 
3576     hdmi_if_null_return(arg, HI_ERR_NULL_PTR);
3577     hdmi_dev = get_hdmi_device(*(hdmi_device_id *)arg);
3578     hdmi_if_null_return(hdmi_dev, HI_ERR_NULL_PTR);
3579 
3580     hdmi_mutex_lock(g_hdmi_mutex);
3581     ret = drv_hdmi_start(hdmi_dev);
3582     hdmi_mutex_unlock(g_hdmi_mutex);
3583 
3584     return ret;
3585 }
3586 
3587 static hi_s32 hdmi_ioctrl_stop(hi_void *arg, hi_bool user)
3588 {
3589     hi_s32 ret;
3590     hdmi_device *hdmi_dev = HI_NULL;
3591 
3592     hdmi_info("CMD_HDMI_STOP user=%u\n", user);
3593 
3594     hdmi_if_null_return(arg, HI_ERR_NULL_PTR);
3595     hdmi_dev = get_hdmi_device(*(hdmi_device_id *)arg);
3596     hdmi_if_null_return(hdmi_dev, HI_ERR_NULL_PTR);
3597 
3598     hdmi_mutex_lock(g_hdmi_mutex);
3599     ret = drv_hdmi_stop(hdmi_dev);
3600     hdmi_mutex_unlock(g_hdmi_mutex);
3601 
3602     return ret;
3603 }
3604 
3605 static hi_s32 hdmi_ioctrl_get_sink_capability(hi_void *arg, hi_bool user)
3606 {
3607     errno_t errnumber;
3608     hi_s32 ret;
3609     hdmi_tx_capability_data tx_cap = {0};
3610     hdmi_device *hdmi_dev = HI_NULL;
3611     hdmi_sink_capability *sink_cap = HI_NULL;
3612     drv_hdmi_sink_capability *drv_sink_cap = HI_NULL;
3613 
3614     hdmi_info("CMD_HDMI_GET_SINK_CAPABILITY user=%u\n", user);
3615 
3616     hdmi_if_null_return(arg, HI_FAILURE);
3617     drv_sink_cap = (drv_hdmi_sink_capability *)arg;
3618     hdmi_dev = get_hdmi_device(drv_sink_cap->hdmi_id);
3619     hdmi_if_null_return(hdmi_dev, HI_FAILURE);
3620 
3621     (hi_void)memset_s(&drv_sink_cap->cap, sizeof(drv_sink_cap->cap), 0, sizeof(hdmi_sink_capability));
3622     hdmi_mutex_lock(g_hdmi_mutex);
3623     if (hdmi_dev->hal == HI_NULL || hdmi_dev->hal->hal_hdmi_tx_capability_get == HI_NULL) {
3624         hdmi_err("null pointer!\n");
3625         ret = HI_ERR_NULL_PTR;
3626         hdmi_mutex_unlock(g_hdmi_mutex);
3627         return ret;
3628     }
3629     hdmi_dev->hal->hal_hdmi_tx_capability_get(hdmi_dev->hal, &tx_cap);
3630     if (drv_hdmi_edid_capability_get(&hdmi_dev->edid_info, &sink_cap) != HDMI_EDID_DATA_INVALID) {
3631         errnumber = memcpy_s(&drv_sink_cap->cap, sizeof(drv_sink_cap->cap), sink_cap, sizeof(hdmi_sink_capability));
3632         hdmi_unlock_unequal_eok_return(errnumber, g_hdmi_mutex, HI_ERR_HDMI_INVALID_PARA);
3633         ret = hdmi_capability_inter_section(&drv_sink_cap->cap, &tx_cap, hdmi_dev->attr.app_attr.auth_mode);
3634     } else {
3635         ret = HI_ERR_HDMI_READ_SINK_FAILED;
3636         hdmi_warn("no HPD, get sink capabity fail\n");
3637     }
3638     hdmi_mutex_unlock(g_hdmi_mutex);
3639 
3640     return ret;
3641 }
3642 
3643 static hi_s32 hdmi_ioctrl_poll_event(hi_void *arg, hi_bool user)
3644 {
3645     hi_s32 ret = HI_FAILURE;
3646     drv_hdmi_event *event = HI_NULL;
3647     hdmi_device *hdmi_dev = HI_NULL;
3648 
3649     hi_unused(user);
3650     hdmi_if_null_return(arg, ret);
3651     event = (drv_hdmi_event *)arg;
3652     hdmi_dev = get_hdmi_device(event->hdmi_id);
3653     if (hdmi_dev != HI_NULL) {
3654         ret = drv_hdmi_event_pool_read(event->hdmi_id, hdmi_current_id_get(hdmi_dev), &event->event);
3655     }
3656 
3657     return ret;
3658 }
3659 
3660 static hi_s32 hdmi_ioctrl_set_attr(hi_void *arg, hi_bool user)
3661 {
3662     hi_s32 ret;
3663     drv_hdmi_property *prop = HI_NULL;
3664     hdmi_device *hdmi_dev = HI_NULL;
3665 
3666     hdmi_info("CMD_HDMI_SET_ATTR user=%u\n", user);
3667 
3668     prop = (drv_hdmi_property *)arg;
3669     hdmi_if_null_return(prop, HI_ERR_NULL_PTR);
3670     hdmi_dev = get_hdmi_device(prop->hdmi_id);
3671     hdmi_if_null_return(hdmi_dev, HI_ERR_NULL_PTR);
3672 #ifdef HDMI_HDR_SUPPORT
3673     hdmi_attr_lock(hdmi_dev);
3674 #endif
3675     hdmi_mutex_lock(g_hdmi_mutex);
3676     ret = drv_hdmi_property_set(prop->hdmi_id, &prop->prop);
3677     hdmi_mutex_unlock(g_hdmi_mutex);
3678 #ifdef HDMI_HDR_SUPPORT
3679     hdmi_attr_un_lock(hdmi_dev);
3680 #endif
3681 
3682     return ret;
3683 }
3684 
3685 static hi_s32 hdmi_ioctrl_get_attr(hi_void *arg, hi_bool user)
3686 {
3687     hi_s32 ret;
3688     drv_hdmi_property *prop = HI_NULL;
3689 
3690     hdmi_info("CMD_HDMI_GET_ATTR user=%u\n", user);
3691 
3692     prop = (drv_hdmi_property *)arg;
3693     hdmi_if_null_return(prop, HI_ERR_NULL_PTR);
3694 
3695     hdmi_mutex_lock(g_hdmi_mutex);
3696     ret = drv_hdmi_property_get(prop->hdmi_id, &prop->prop);
3697     hdmi_mutex_unlock(g_hdmi_mutex);
3698 
3699     return ret;
3700 }
3701 
3702 static hi_s32 hdmi_ioctrl_get_vo_attr(hi_void *arg, hi_bool user)
3703 {
3704     hi_s32 ret;
3705     hdmi_device *hdmi_dev = HI_NULL;
3706     drv_hdmi_vo_attr *attr = HI_NULL;
3707 
3708     hdmi_info("CMD_HDMI_GET_VO_ATTR user=%u\n", user);
3709 
3710     attr = (drv_hdmi_vo_attr *)arg;
3711     hdmi_if_null_return(attr, HI_FAILURE);
3712     hdmi_dev = get_hdmi_device(attr->hdmi_id);
3713     hdmi_if_null_return(hdmi_dev, HI_FAILURE);
3714     (hi_void)memset_s(&attr->vo_attr, sizeof(attr->vo_attr), 0, sizeof(hdmi_vo_attr));
3715 
3716     hdmi_mutex_lock(g_hdmi_mutex);
3717     ret = drv_hdmi_vo_attr_get(hdmi_dev, &attr->vo_attr);
3718     hdmi_mutex_unlock(g_hdmi_mutex);
3719 
3720     return ret;
3721 }
3722 
3723 static hi_s32 hdmi_ioctrl_set_vo_attr(hi_void *arg, hi_bool user)
3724 {
3725     hi_s32 ret;
3726     hdmi_device *hdmi_dev = HI_NULL;
3727     drv_hdmi_vo_attr *attr = HI_NULL;
3728 
3729     hdmi_info("CMD_HDMI_SET_VO_ATTR user=%u\n", user);
3730 
3731     attr = (drv_hdmi_vo_attr *)arg;
3732     hdmi_if_null_return(attr, HI_FAILURE);
3733     hdmi_dev = get_hdmi_device(attr->hdmi_id);
3734     hdmi_if_null_return(hdmi_dev, HI_FAILURE);
3735 
3736     hdmi_mutex_lock(g_hdmi_mutex);
3737     ret = drv_hdmi_vo_attr_set(hdmi_dev, &attr->vo_attr);
3738     hdmi_mutex_unlock(g_hdmi_mutex);
3739 
3740     return ret;
3741 }
3742 
3743 static hi_s32 hdmi_ioctrl_get_infoframe(hi_void *arg, hi_bool user)
3744 {
3745     hi_s32 ret;
3746     hdmi_device *hdmi_dev = HI_NULL;
3747     drv_hdmi_infoframe *infoframe = HI_NULL;
3748 
3749     hdmi_info("CMD_HDMI_GET_INFOFRAME user=%u\n", user);
3750 
3751     hdmi_if_null_return(arg, HI_ERR_NULL_PTR);
3752     infoframe = (drv_hdmi_infoframe *)arg;
3753     hdmi_dev  = get_hdmi_device(infoframe->hdmi_id);
3754     hdmi_if_null_return(hdmi_dev, HI_ERR_NULL_PTR);
3755 
3756     hdmi_mutex_lock(g_hdmi_mutex);
3757     ret = drv_hdmi_infoframe_get(hdmi_dev, infoframe->infoframe_id, &(infoframe->infoframe));
3758     hdmi_mutex_unlock(g_hdmi_mutex);
3759 
3760     return ret;
3761 }
3762 
3763 static hi_s32 hdmi_ioctrl_set_infoframe(hi_void *arg, hi_bool user)
3764 {
3765     hi_s32 ret;
3766     hdmi_device *hdmi_dev = HI_NULL;
3767     drv_hdmi_infoframe *infoframe = HI_NULL;
3768 
3769     hdmi_info("CMD_HDMI_SET_INFOFRAME user=%u\n", user);
3770 
3771     hdmi_if_null_return(arg, HI_ERR_NULL_PTR);
3772     infoframe = (drv_hdmi_infoframe *)arg;
3773     hdmi_dev = get_hdmi_device(infoframe->hdmi_id);
3774     hdmi_if_null_return(hdmi_dev, HI_ERR_NULL_PTR);
3775 
3776     hdmi_mutex_lock(g_hdmi_mutex);
3777     ret = drv_hdmi_infoframe_set(hdmi_dev, infoframe->infoframe_id, &(infoframe->infoframe));
3778     hdmi_mutex_unlock(g_hdmi_mutex);
3779 
3780     return ret;
3781 }
3782 
3783 static hi_s32 hdmi_ioctrl_avmute(hi_void *arg, hi_bool user)
3784 {
3785     hdmi_device *hdmi_dev = HI_NULL;
3786     drv_hdmi_avmute *drv_avmute = HI_NULL;
3787     hi_bool audio_enable = HI_FALSE;
3788 
3789     hdmi_info("CMD_HDMI_SET_AVMUTE user=%u\n", user);
3790 
3791     hdmi_if_null_return(arg, HI_ERR_NULL_PTR);
3792     drv_avmute = (drv_hdmi_avmute *)arg;
3793     hdmi_dev = get_hdmi_device(drv_avmute->hdmi_id);
3794     hdmi_if_null_return(hdmi_dev, HI_ERR_NULL_PTR);
3795 
3796     audio_enable = (hdmi_dev->attr.app_attr.enable_hdmi) && (hdmi_dev->attr.app_attr.enable_audio);
3797 
3798     hdmi_mutex_lock(g_hdmi_mutex);
3799     drv_hdmi_avmute_set(hdmi_dev, drv_avmute->avmute);
3800     if (drv_avmute->avmute) {
3801         drv_hdmi_audio_path_enable(hdmi_dev, !(drv_avmute->avmute));
3802     } else {
3803         drv_hdmi_audio_path_enable(hdmi_dev, audio_enable);
3804     }
3805     hdmi_mutex_unlock(g_hdmi_mutex);
3806 
3807     return HI_SUCCESS;
3808 }
3809 
3810 static hi_s32 hdmi_ioctrl_update_edid(hi_void *arg, hi_bool user)
3811 {
3812     hi_s32 ret, edid_len;
3813     hdmi_device *hdmi_dev = HI_NULL;
3814     drv_hdmi_edid_raw_data *drv_edid_raw = HI_NULL;
3815 
3816     hdmi_info("CMD_HDMI_UPDATE_EDID user=%u\n", user);
3817 
3818     hdmi_if_null_return(arg, HI_ERR_NULL_PTR);
3819     drv_edid_raw = (drv_hdmi_edid_raw_data *)arg;
3820     hdmi_dev = get_hdmi_device(drv_edid_raw->hdmi_id);
3821     hdmi_if_null_return(hdmi_dev, HI_ERR_NULL_PTR);
3822 
3823     (hi_void)memset_s(&drv_edid_raw->edid_raw, sizeof(drv_edid_raw->edid_raw), 0, sizeof(hdmi_edid_raw_data));
3824     hdmi_mutex_lock(g_hdmi_mutex);
3825     ret = drv_hdmi_edid_update(&hdmi_dev->edid_info, HDMI_EDID_UPDATE_SINK);
3826     if (ret == HI_SUCCESS) {
3827         edid_len = drv_hdmi_edid_raw_get(&hdmi_dev->edid_info, drv_edid_raw->edid_raw.edid, HDMI_EDID_SIZE);
3828         if (edid_len != HI_ERR_HDMI_NUL_PTR && edid_len != HI_ERR_HDMI_INVALID_PARA && edid_len != HI_FAILURE) {
3829             drv_edid_raw->edid_raw.edid_len = (hi_u32)edid_len;
3830             drv_edid_raw->edid_raw.edid_valid = 1;
3831         }
3832     }
3833     hdmi_mutex_unlock(g_hdmi_mutex);
3834 
3835     return ret;
3836 }
3837 
3838 static hi_s32 hdmi_ioctrl_get_status(hi_void *arg, hi_bool user)
3839 {
3840     hi_s32 ret;
3841     hdmi_device *hdmi_dev = HI_NULL;
3842     drv_hdmi_status *hdmi_state = HI_NULL;
3843 
3844     hdmi_info("CMD_HDMI_GET_STATUS user=%u\n", user);
3845 
3846     hdmi_if_null_return(arg, HI_ERR_NULL_PTR);
3847     hdmi_state = (drv_hdmi_status *)arg;
3848     hdmi_dev = get_hdmi_device(hdmi_state->hdmi_id);
3849     hdmi_if_null_return(hdmi_dev, HI_ERR_NULL_PTR);
3850 
3851     (hi_void)memset_s(&hdmi_state->status, sizeof(hdmi_state->status), 0, sizeof(hdmi_status));
3852     hdmi_mutex_lock(g_hdmi_mutex);
3853     ret = drv_hdmi_status_get(hdmi_dev, &hdmi_state->status);
3854     hdmi_mutex_unlock(g_hdmi_mutex);
3855 
3856     return ret;
3857 }
3858 
3859 static hi_s32 hdmi_ioctrl_register_callback(hi_void *arg, hi_bool user)
3860 {
3861     hi_bool hpd = HI_FALSE;
3862     hi_bool intr_status = HI_FALSE;
3863     hdmi_device *hdmi_dev = HI_NULL;
3864 
3865     hdmi_info("CMD_HDMI_REGISTER_CALLBACK user=%u\n", user);
3866 
3867     hdmi_if_null_return(arg, HI_ERR_NULL_PTR);
3868     hdmi_dev = get_hdmi_device(*(hdmi_device_id *)arg);
3869     hdmi_if_null_return(hdmi_dev, HI_ERR_NULL_PTR);
3870 
3871     hdmi_mutex_lock(g_hdmi_mutex);
3872     if ((hdmi_dev->user_cnt != 0) || (hdmi_dev->kernel_cnt != 0)) {
3873         hdmi_dev->user_callback_cnt++;
3874         hdmi_mutex_unlock(g_hdmi_mutex);
3875         hdmi_mutex_lock(hdmi_dev->mutex_thread);
3876         hdmi_dev->k_callback = HI_NULL;
3877         /*
3878          * HPD needs to be reported when the following conditions are met:
3879          * 1. the driver has reported HPD before registering the callback.
3880          * 2. there is currently no pending hpd interrupt.
3881          * 3. hotplug pin level is high.
3882          */
3883         hal_call_void(hal_hdmi_hdp_intr_status_get, hdmi_dev->hal, &intr_status);
3884         if (hdmi_dev->hpd_notified == HI_TRUE && intr_status == HI_FALSE) {
3885             hal_call_void(hal_hdmi_hot_plug_status_get, hdmi_dev->hal, &hpd);
3886             if (hpd == HI_TRUE) {
3887                 drv_hdmi_event_pool_write(hdmi_dev->hdmi_dev_id, HDMI_EVENT_HOTPLUG);
3888             }
3889         }
3890         hdmi_mutex_unlock(hdmi_dev->mutex_thread);
3891         hdmi_mutex_lock(g_hdmi_mutex);
3892     }
3893     hdmi_mutex_unlock(g_hdmi_mutex);
3894 
3895     return HI_SUCCESS;
3896 }
3897 
3898 static hi_s32 hdmi_ioctrl_ungister_callback(hi_void *arg, hi_bool user)
3899 {
3900     hdmi_device *hdmi_dev = HI_NULL;
3901 
3902     hdmi_info("CMD_HDMI_UNREGISTER_CALLBACK user=%u\n", user);
3903 
3904     hdmi_if_null_return(arg, HI_ERR_NULL_PTR);
3905     hdmi_dev = get_hdmi_device(*(hdmi_device_id *)arg);
3906     hdmi_if_null_return(hdmi_dev, HI_ERR_NULL_PTR);
3907 
3908     hdmi_mutex_lock(g_hdmi_mutex);
3909     if (hdmi_dev->user_callback_cnt > 0) {
3910         hdmi_dev->user_callback_cnt--;
3911     }
3912     if (hdmi_dev->user_callback_cnt == 0) {
3913         hdmi_mutex_unlock(g_hdmi_mutex);
3914         hdmi_mutex_lock(hdmi_dev->mutex_thread);
3915         hdmi_dev->k_callback = hi_drv_hdmi_kernel_event_callback;
3916         hdmi_mutex_unlock(hdmi_dev->mutex_thread);
3917         hdmi_mutex_lock(g_hdmi_mutex);
3918     }
3919     hdmi_mutex_unlock(g_hdmi_mutex);
3920 
3921     return HI_SUCCESS;
3922 }
3923 
3924 #ifdef HDMI_HDR_SUPPORT
3925 static hi_s32 hdmi_ioctrl_set_hdr_attr(hi_void *arg, hi_bool user)
3926 {
3927     hi_s32 ret;
3928     drv_hdmi_hdr *hdr_attr = HI_NULL;
3929     hdmi_device *hdmi_dev = HI_NULL;
3930 
3931     hdmi_info("CMD_HDMI_SET_HDR_ATTR user=%u\n", user);
3932 
3933     hdmi_if_null_return(arg, HI_FAILURE);
3934     hdr_attr = (drv_hdmi_hdr *)arg;                 // from intf_k.c
3935     hdmi_dev = get_hdmi_device(hdr_attr->hdmi_id);  // find hdmi_device by hdmi_id
3936     hdmi_if_null_return(hdmi_dev, HI_FAILURE);
3937     ret = drv_hdmi_hdr_attr_set(hdmi_dev, hdr_attr);
3938 
3939     return ret;
3940 }
3941 #endif
3942 
3943 static hi_s32 hdmi_ioctrl_set_mod_param(hi_void *arg, hi_bool user)
3944 {
3945     hi_s32 ret;
3946     hdmi_device *hdmi_dev = HI_NULL;
3947     drv_hdmi_mod_param *mod_param = HI_NULL;
3948 
3949     hdmi_info("CMD_HDMI_SET_MOD_PARAM user=%u\n", user);
3950 
3951     hdmi_if_null_return(arg, HI_FAILURE);
3952     mod_param = (drv_hdmi_mod_param *)arg;
3953     hdmi_dev = get_hdmi_device(mod_param->hdmi_id);
3954     hdmi_if_null_return(hdmi_dev, HI_FAILURE);
3955 
3956     hdmi_mutex_lock(g_hdmi_mutex);
3957     ret = drv_hdmi_mod_param_set(hdmi_dev, mod_param);
3958     hdmi_mutex_unlock(g_hdmi_mutex);
3959 
3960     return ret;
3961 }
3962 
3963 static hi_s32 hdmi_ioctrl_get_mod_param(hi_void *arg, hi_bool user)
3964 {
3965     hi_s32 ret;
3966     hdmi_device *hdmi_dev = HI_NULL;
3967     drv_hdmi_mod_param *mod_param = HI_NULL;
3968 
3969     hdmi_info("CMD_HDMI_GET_MOD_PARAM user=%u\n", user);
3970 
3971     hdmi_if_null_return(arg, HI_FAILURE);
3972     mod_param = (drv_hdmi_mod_param *)arg;
3973     hdmi_dev = get_hdmi_device(mod_param->hdmi_id);
3974     hdmi_if_null_return(hdmi_dev, HI_FAILURE);
3975 
3976     hdmi_mutex_lock(g_hdmi_mutex);
3977     ret = drv_hdmi_mod_param_get(hdmi_dev, mod_param);
3978     hdmi_mutex_unlock(g_hdmi_mutex);
3979 
3980     return ret;
3981 }
3982 
3983 #if defined(CONFIG_HI_PLATFORM_H8)
3984 static hi_s32 hdmi_ioctrl_get_hw_spec(hi_void *arg, hi_bool user)
3985 {
3986     hi_s32 ret;
3987     hdmi_device *hdmi_dev = HI_NULL;
3988     drv_hdmi_hw_spec *spec = HI_NULL;
3989 
3990     hdmi_info("CMD_HDMI_GET_HW_SPEC user=%u\n", user);
3991 
3992     hdmi_if_null_return(arg, HI_ERR_NULL_PTR);
3993     spec = (drv_hdmi_hw_spec *)arg;
3994     hdmi_dev = get_hdmi_device(spec->hdmi_id);
3995     hdmi_if_null_return(hdmi_dev, HI_ERR_NULL_PTR);
3996 
3997     (hi_void)memset_s(&spec->hw_spec, sizeof(hdmi_hw_spec), 0, sizeof(hdmi_hw_spec));
3998     hdmi_mutex_lock(g_hdmi_mutex);
3999     ret = drv_hdmi_hw_spec_get(hdmi_dev, &spec->hw_spec);
4000     hdmi_mutex_unlock(g_hdmi_mutex);
4001 
4002     return ret;
4003 }
4004 
4005 static hi_s32 hdmi_ioctrl_set_hw_spec(hi_void *arg, hi_bool user)
4006 {
4007     hi_s32 ret;
4008     hdmi_device *hdmi_dev = HI_NULL;
4009     drv_hdmi_hw_spec *spec = HI_NULL;
4010 
4011     hdmi_info("CMD_HDMI_SET_HW_SPEC user=%u\n", user);
4012 
4013     hdmi_if_null_return(arg, HI_ERR_NULL_PTR);
4014     spec = (drv_hdmi_hw_spec *)arg;
4015     hdmi_dev = get_hdmi_device(spec->hdmi_id);
4016     hdmi_if_null_return(hdmi_dev, HI_ERR_NULL_PTR);
4017 
4018     hdmi_mutex_lock(g_hdmi_mutex);
4019     ret = drv_hdmi_hw_spec_set(hdmi_dev, &spec->hw_spec);
4020     hdmi_mutex_unlock(g_hdmi_mutex);
4021 
4022     return ret;
4023 }
4024 #endif
4025 
4026 static const hdmi_ioctrl_func g_hdmi_cmd_func_tab[] = {
4027     { CMD_HDMI_INIT, hdmi_ioctrl_init },
4028     { CMD_HDMI_DEINIT, hdmi_ioctrl_deinit },
4029     { CMD_HDMI_OPEN, hdmi_ioctrl_open },
4030     { CMD_HDMI_CLOSE, hdmi_ioctrl_close },
4031     { CMD_HDMI_START, hdmi_ioctrl_start },
4032     { CMD_HDMI_STOP, hdmi_ioctrl_stop },
4033     { CMD_HDMI_GET_SINK_CAPABILITY, hdmi_ioctrl_get_sink_capability },
4034     { CMD_HDMI_POLL_EVENT, hdmi_ioctrl_poll_event },
4035     { CMD_HDMI_SET_ATTR, hdmi_ioctrl_set_attr },
4036     { CMD_HDMI_GET_ATTR, hdmi_ioctrl_get_attr },
4037     { CMD_HDMI_GET_VO_ATTR, hdmi_ioctrl_get_vo_attr },
4038     { CMD_HDMI_SET_VO_ATTR, hdmi_ioctrl_set_vo_attr },
4039     { CMD_HDMI_GET_INFOFRAME, hdmi_ioctrl_get_infoframe },
4040     { CMD_HDMI_SET_INFOFRAME, hdmi_ioctrl_set_infoframe },
4041     { CMD_HDMI_SET_AVMUTE, hdmi_ioctrl_avmute },
4042     { CMD_HDMI_UPDATE_EDID, hdmi_ioctrl_update_edid },
4043     { CMD_HDMI_GET_STATUS, hdmi_ioctrl_get_status },
4044     { CMD_HDMI_REGISTER_CALLBACK, hdmi_ioctrl_register_callback },
4045     { CMD_HDMI_UNREGISTER_CALLBACK, hdmi_ioctrl_ungister_callback },
4046 #ifdef HDMI_HDR_SUPPORT
4047     { CMD_HDMI_SET_HDR_ATTR, hdmi_ioctrl_set_hdr_attr },
4048 #endif
4049     { CMD_HDMI_SET_MOD_PARAM, hdmi_ioctrl_set_mod_param },
4050     { CMD_HDMI_GET_MOD_PARAM, hdmi_ioctrl_get_mod_param },
4051 #if defined(CONFIG_HI_PLATFORM_H8)
4052     { CMD_HDMI_GET_HW_SPEC, hdmi_ioctrl_get_hw_spec },
4053     { CMD_HDMI_SET_HW_SPEC, hdmi_ioctrl_set_hw_spec },
4054 #endif
4055 };
4056 
4057 hi_s32 drv_hdmi_cmd_process(unsigned int cmd, hi_void *arg, hi_bool user)
4058 {
4059     hi_s32 ret = HI_FAILURE;
4060     hi_u32 index;
4061 
4062     for (index = 0; index < hdmi_array_size(g_hdmi_cmd_func_tab); index++) {
4063         if ((g_hdmi_cmd_func_tab[index].cmd == cmd) && (g_hdmi_cmd_func_tab[index].hdmi_ioctrl_func != HI_NULL)) {
4064             ret = g_hdmi_cmd_func_tab[index].hdmi_ioctrl_func(arg, user);
4065             break;
4066         }
4067     }
4068 
4069     if (index == hdmi_array_size(g_hdmi_cmd_func_tab)) {
4070         hdmi_err("unknown cmd:0x%x\n", cmd);
4071         return HI_ERR_HDMI_UNKNOWN_COMMAND;
4072     }
4073     if (ret != HI_SUCCESS) {
4074         hdmi_warn("ret != HI_SUCCESS!\n");
4075     }
4076 
4077     return ret;
4078 }
4079 
4080 #ifndef CONFIG_COMPAT
4081 static long hdmi_ioctl(unsigned int cmd, unsigned long arg, void *private_data)
4082 {
4083     hi_unused(private_data);
4084     return drv_hdmi_cmd_process(cmd, (hi_void *)(uintptr_t)arg, HI_TRUE);
4085 }
4086 #else
4087 static long hdmi_compact_ioctl(unsigned int cmd, unsigned long arg, void *private_data)
4088 {
4089     hi_unused(private_data);
4090     return drv_hdmi_compat_cmd_process(cmd, (hi_void *)(uintptr_t)arg, HI_TRUE);
4091 }
4092 #endif
4093 
4094 hi_s32 hdmi_init(hi_void *args)
4095 {
4096     hi_unused(args);
4097     osal_atomic_inc_return(&g_hdmi_count);
4098     return 0;
4099 }
4100 
4101 hi_void hdmi_exit(hi_void)
4102 {
4103     /* deinit HDMI by user. */
4104     if (osal_atomic_dec_return(&g_hdmi_count)) {
4105         hdmi_info("exit...");
4106     }
4107     return;
4108 }
4109 
4110 static hi_void hdmi_notify(mod_notice_id notice)
4111 {
4112     hi_unused(notice);
4113     return;
4114 }
4115 
4116 static hi_void hdmi_query_state(mod_state *state)
4117 {
4118     *state = MOD_STATE_FREE;
4119     return;
4120 }
4121 
4122 static hi_u32 hdmi_get_ver_magic(hi_void)
4123 {
4124     return VERSION_MAGIC;
4125 }
4126 
4127 static hdmi_export_func g_hdmi_export_funcs = {
4128     .pfn_stop = hi_drv_hdmi_stop,
4129 #if (defined(CONFIG_HI_PLATFORM_H8))
4130     .pfn_csc_param_set = hi_drv_hdmi_csc_param_set,
4131     .pfn_video_param_set = hi_drv_hdmi_video_param_set,
4132 #endif
4133 #ifdef HDMI_HDR_SUPPORT
4134     .pfn_set_hdr_attr = hi_drv_hdmi_set_hdr_attr,
4135 #endif
4136 };
4137 
4138 static umap_module g_module = {
4139     .export_funcs    = &g_hdmi_export_funcs,
4140     .mod_id          = HI_ID_HDMI,
4141     .mod_name        = "hdmi",
4142     .pfn_init        = hdmi_init,
4143     .pfn_exit        = hdmi_exit,
4144     .pfn_query_state = hdmi_query_state,
4145     .pfn_notify      = hdmi_notify,
4146     .pfn_ver_checker = hdmi_get_ver_magic,
4147     .data            = HI_NULL,
4148 };
4149 
4150 static long hdmi_file_ioctl(unsigned int cmd, unsigned long arg, void *private_data)
4151 {
4152 #ifndef CONFIG_COMPAT
4153     return (long)hdmi_ioctl(cmd, arg, private_data);
4154 #else
4155     return (long)hdmi_compact_ioctl(cmd, arg, private_data);
4156 #endif
4157 }
4158 
4159 #ifdef CONFIG_HI_PROC_SHOW_SUPPORT
4160 hdmi_proc_item g_hdmi_proc_item = {
4161 #ifdef CONFIG_HI_PLATFORM_H8
4162     .fn_read = drv_hdmi_proc_show,
4163 #else
4164     .fn_read = drv_hdmi_read_proc,
4165 #endif
4166 #ifdef HDMI_DEBUG_SUPPORT
4167     .fn_write = drv_hdmi_debug_source_write,
4168 #else
4169     .fn_write = HI_NULL,
4170 #endif
4171 };
4172 
4173 hdmi_proc_item g_vo_proc_item = {
4174 #ifdef CONFIG_HI_PLATFORM_H8
4175     .fn_read = drv_hdmi_vo_proc_show,
4176 #else
4177     .fn_read = drv_hdmi_vo_read_proc,
4178 #endif
4179     .fn_write = HI_NULL,
4180 };
4181 
4182 hdmi_proc_item g_ao_proc_item = {
4183 #ifdef CONFIG_HI_PLATFORM_H8
4184     .fn_read = drv_hdmi_ao_proc_show,
4185 #else
4186     .fn_read = drv_hdmi_ao_read_proc,
4187 #endif
4188     .fn_write = HI_NULL,
4189 };
4190 
4191 hdmi_proc_item g_sink_proc_item = {
4192 #ifdef CONFIG_HI_PLATFORM_H8
4193     .fn_read = drv_hdmi_sink_proc_show,
4194 #else
4195     .fn_read = drv_hdmi_sink_read_proc,
4196 #endif
4197     .fn_write = HI_NULL,
4198 };
4199 
4200 static hi_void drv_hdmi_proc_add_module(hi_char *entry_name, hdmi_proc_item *proc_item, hi_void *data)
4201 {
4202     osal_proc_entry_t *proc = NULL;
4203 
4204     hi_unused(data);
4205     proc = osal_create_proc_entry(entry_name, NULL);
4206     hdmi_if_null_return_void(proc);
4207     proc->read = (hi_void *)proc_item->fn_read;
4208     proc->write = (hi_void *)proc_item->fn_write;
4209 
4210     return;
4211 }
4212 
4213 static hi_void drv_hdmi_proc_remove_module(hi_char *entry_name)
4214 {
4215     osal_remove_proc_entry(entry_name, NULL);
4216     return;
4217 }
4218 
4219 hi_void drv_hdmi_proc_register(hi_u32 hdmi_id)
4220 {
4221     errno_t ret;
4222     hi_char proc_name[16];
4223 
4224     (hi_void)memset_s(proc_name, sizeof(proc_name), 0, sizeof(proc_name));
4225     ret = snprintf_s(proc_name, sizeof(proc_name), sizeof(proc_name) - 1, "%s%u", "hdmi", hdmi_id);
4226     if (ret < 0) {
4227         hdmi_err("snprintf_s err.\n");
4228         return;
4229     }
4230     drv_hdmi_proc_add_module(proc_name, &g_hdmi_proc_item, HI_NULL);
4231     (hi_void)memset_s(proc_name, sizeof(proc_name), 0, sizeof(proc_name));
4232     ret = snprintf_s(proc_name, sizeof(proc_name), sizeof(proc_name) - 1, "%s%u%s", "hdmi", hdmi_id, "_vo");
4233     if (ret < 0) {
4234         hdmi_err("snprintf_s err.\n");
4235         return;
4236     }
4237     drv_hdmi_proc_add_module(proc_name, &g_vo_proc_item, HI_NULL);
4238     (hi_void)memset_s(proc_name, sizeof(proc_name), 0, sizeof(proc_name));
4239     ret = snprintf_s(proc_name, sizeof(proc_name), sizeof(proc_name) - 1, "%s%u%s", "hdmi", hdmi_id, "_ao");
4240     if (ret < 0) {
4241         hdmi_err("snprintf_s err.\n");
4242         return;
4243     }
4244     drv_hdmi_proc_add_module(proc_name, &g_ao_proc_item, HI_NULL);
4245     (hi_void)memset_s(proc_name, sizeof(proc_name), 0, sizeof(proc_name));
4246     ret = snprintf_s(proc_name, sizeof(proc_name), sizeof(proc_name) - 1, "%s%u%s", "hdmi", hdmi_id, "_sink");
4247     if (ret < 0) {
4248         hdmi_err("snprintf_s err.\n");
4249         return;
4250     }
4251     drv_hdmi_proc_add_module(proc_name, &g_sink_proc_item, HI_NULL);
4252 
4253     return;
4254 }
4255 
4256 hi_void drv_hdmi_proc_un_register(hi_u32 hdmi_id)
4257 {
4258     hi_s32 ret;
4259     hi_char proc_name[16];
4260 
4261     (hi_void)memset_s(proc_name, sizeof(proc_name), 0, sizeof(proc_name));
4262     ret = snprintf_s(proc_name, sizeof(proc_name), sizeof(proc_name) - 1, "%s%u", "hdmi", hdmi_id);
4263     if (ret < 0) {
4264         hdmi_err("snprintf_s err.\n");
4265         return;
4266     }
4267     drv_hdmi_proc_remove_module(proc_name);
4268     (hi_void)memset_s(proc_name, sizeof(proc_name), 0, sizeof(proc_name));
4269     ret = snprintf_s(proc_name, sizeof(proc_name), sizeof(proc_name) - 1, "%s%u%s", "hdmi", hdmi_id, "_vo");
4270     if (ret < 0) {
4271         hdmi_err("snprintf_s err.\n");
4272         return;
4273     }
4274     drv_hdmi_proc_remove_module(proc_name);
4275     (hi_void)memset_s(proc_name, sizeof(proc_name), 0, sizeof(proc_name));
4276     ret = snprintf_s(proc_name, sizeof(proc_name), sizeof(proc_name) - 1, "%s%u%s", "hdmi", hdmi_id, "_ao");
4277     if (ret < 0) {
4278         hdmi_err("snprintf_s err.\n");
4279         return;
4280     }
4281     drv_hdmi_proc_remove_module(proc_name);
4282     (hi_void)memset_s(proc_name, sizeof(proc_name), 0, sizeof(proc_name));
4283     ret = snprintf_s(proc_name, sizeof(proc_name), sizeof(proc_name) - 1, "%s%u%s", "hdmi", hdmi_id, "_sink");
4284     if (ret < 0) {
4285         hdmi_err("snprintf_s err.\n");
4286         return;
4287     }
4288     drv_hdmi_proc_remove_module(proc_name);
4289 
4290     return;
4291 }
4292 #endif
4293 
4294 static struct osal_fileops g_hdmi_file_ops = {
4295     .open           = hdmi_file_open,
4296     .unlocked_ioctl = hdmi_file_ioctl,
4297     .release        = hdmi_file_close,
4298 #ifdef CONFIG_COMPAT
4299     .compat_ioctl   = hdmi_file_ioctl,
4300 #endif
4301 };
4302 
4303 static struct osal_pmops g_hdmi_drv_ops = {0};
4304 
4305 static hi_s32 hdmi_dev_register(hi_void)
4306 {
4307     errno_t ret;
4308     hi_char ch_devfs_name[20] = {0};
4309 
4310     if (cmpi_register_module(&g_module)) {
4311         hdmi_warn("cmpi_register_module hdmi fail \n");
4312         return HI_FAILURE;
4313     }
4314 
4315     /* register hdmi device */
4316     ret = snprintf_s(ch_devfs_name, sizeof(ch_devfs_name), sizeof(ch_devfs_name) - 1, "%s", UMAP_DEVNAME_HDMI_BASE);
4317     if (ret < 0) {
4318         hdmi_err("snprintf_s err\n");
4319         return HI_FAILURE;
4320     }
4321     g_hdmi_device = osal_createdev(ch_devfs_name);
4322     hdmi_if_null_return(g_hdmi_device, HI_FAILURE);
4323     g_hdmi_device->fops       = &g_hdmi_file_ops;
4324     g_hdmi_device->osal_pmops = &g_hdmi_drv_ops;
4325     g_hdmi_device->minor      = UMAP_HDMI_MINOR_BASE;
4326     if (osal_registerdevice(g_hdmi_device) < 0) {
4327         hdmi_warn("g_hdmi_device register failed\n");
4328         return HI_FAILURE;
4329     }
4330 
4331     return HI_SUCCESS;
4332 }
4333 
4334 #ifdef CONFIG_HI_PROC_SHOW_SUPPORT
4335 static hi_void hdmi_proc_register(hi_void)
4336 {
4337     hi_s32 hdmi_id;
4338     hdmi_device *hdmi_dev = HI_NULL;
4339 
4340         /* register hdmi proc */
4341     for (hdmi_id = 0; hdmi_id < HDMI_DEVICE_ID_BUTT; hdmi_id++) {
4342         hdmi_dev = get_hdmi_device(hdmi_id);
4343         if (hdmi_dev != HI_NULL) {
4344             drv_hdmi_proc_register(hdmi_id);
4345         }
4346     }
4347 
4348     return;
4349 }
4350 #endif
4351 
4352 hi_s32 hdmi_drv_mod_init(hi_void)
4353 {
4354     hi_s32 ret;
4355     hdmi_device *hdmi_dev = HI_NULL;
4356 
4357     hdmi_dev = get_hdmi_device(HDMI_DEVICE_ID0);
4358     if (hdmi_dev != HI_NULL) {
4359         /* init csc param. */
4360         hdmi_dev->csc_param.colorimetry = HI_HDMI_COLORIMETRY_ITU709;
4361         hdmi_dev->csc_param.pixel_encoding = HI_HDMI_COLORSPACE_YCBCR444;
4362         hdmi_dev->csc_param.quantization = HI_HDMI_QUANT_RANGE_LIMITED;
4363 
4364         osal_sema_init(&hdmi_dev->mutex_proc, 1);
4365         osal_sema_init(&hdmi_dev->mutex_thread, 1);
4366 #ifdef HDMI_HDR_SUPPORT
4367         osal_spin_lock_init(&hdmi_dev->hdr_mutex.attr_spin);
4368 #endif
4369     }
4370 
4371     osal_sema_init(&g_hdmi_mutex, 1);
4372     osal_atomic_init(&g_hdmi_count);
4373     osal_atomic_set(&g_hdmi_count, 0);
4374 
4375     ret = hdmi_dev_register();
4376     if (ret == HI_FAILURE) {
4377         goto exit_dev;
4378     }
4379 
4380 #ifdef CONFIG_HI_PROC_SHOW_SUPPORT
4381     hdmi_proc_register();
4382 #endif
4383 
4384 #ifdef CONFIG_DRM_HISI_HISMART
4385     drm_hal_hdmitx_dev_register();
4386 #endif
4387 
4388 #if (defined(CONFIG_HI_PLATFORM_H8))
4389     HI_PRINT("load hdmi.ko ....OK!\n");
4390 #else
4391     HI_PRINT("load hdmi.ko for %s...OK!\n", CHIP_NAME);
4392 #endif
4393 
4394 #if defined(HDMI_LITEOS_SUPPORT)
4395 #ifdef HDMI_PRODUCT_HI3516CV500
4396     g_hdmi_reg = (hi_char *)osal_ioremap_nocache(BASE_ADDR_TX_DPHY, HDMI_TX_REG_LEN);
4397 #else
4398     g_hdmi_reg = (hi_char *)osal_ioremap_nocache(HDMI_TX_BASE_ADDR, HDMI_TX_REG_LEN);
4399 #endif
4400     if (g_hdmi_reg == HI_NULL) {
4401         hdmi_err("ioremap_nocache failed!\n");
4402         return HI_FAILURE;
4403     }
4404 #endif
4405 
4406     return HI_SUCCESS;
4407 
4408 exit_dev:
4409     osal_destroydev(g_hdmi_device);
4410     cmpi_unregister_module(HI_ID_HDMI);
4411 
4412     return HI_FAILURE;
4413 }
4414 
4415 hi_void hdmi_drv_mod_exit(hi_void)
4416 {
4417     hi_u32 hdmi_id;
4418     hdmi_device *hdmi_dev = HI_NULL;
4419 
4420 #ifdef CONFIG_DRM_HISI_HISMART
4421     drm_hal_hdmitx_dev_unregister();
4422 #endif
4423 
4424     for (hdmi_id = 0; hdmi_id < HDMI_DEVICE_ID_BUTT; hdmi_id++) {
4425         hdmi_dev = get_hdmi_device(hdmi_id);
4426         if (hdmi_dev != HI_NULL) {
4427             if ((hi_u32)hdmi_dev->run_state & HDMI_RUN_STATE_OPEN) {
4428                 hdmi_dev->user_cnt = 0;
4429                 hdmi_dev->kernel_cnt = 0;
4430                 hdmi_release(hdmi_dev);
4431             }
4432             osal_sema_destroy(&hdmi_dev->mutex_proc);
4433 #ifdef HDMI_HDR_SUPPORT
4434             osal_spin_lock_destroy(&hdmi_dev->hdr_mutex.attr_spin);
4435 #endif
4436             osal_sema_destroy(&hdmi_dev->mutex_thread);
4437         }
4438 #ifdef CONFIG_HI_PROC_SHOW_SUPPORT
4439         drv_hdmi_proc_un_register(hdmi_id);
4440 #endif
4441     }
4442     drv_hdmi_hardware_reset();
4443     cmpi_unregister_module(HI_ID_HDMI);
4444     osal_deregisterdevice(g_hdmi_device);
4445     osal_destroydev(g_hdmi_device);
4446     osal_atomic_destroy(&g_hdmi_count);
4447     osal_sema_destroy(&g_hdmi_mutex);
4448 
4449 #if defined(HDMI_LITEOS_SUPPORT)
4450     if (g_hdmi_reg != HI_NULL) {
4451         osal_iounmap((void *)g_hdmi_reg, HDMI_TX_REG_LEN);
4452         g_hdmi_reg = HI_NULL;
4453     }
4454 #endif
4455 }
4456 
4457