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