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 #include "drv_hdmi_intf_k.h"
19 #include "drv_hdmi_intf.h"
20 #include "hdmi_hal.h"
21 #include "drv_hdmi_edid.h"
22 #include "drv_hdmi_event.h"
23 #include "hdmi_product_define.h"
24 #include "drv_hdmi_ioctl.h"
25
hdmi_ext_ioctl(unsigned int cmd,void * argp)26 static hi_s32 hdmi_ext_ioctl(unsigned int cmd, void *argp)
27 {
28 hi_s32 ret;
29 ret = drv_hdmi_cmd_process(cmd, argp, HI_FALSE);
30 return ret;
31 }
32
hdmi_hot_plug_process(hdmi_device_id hdmi_id)33 static hi_void hdmi_hot_plug_process(hdmi_device_id hdmi_id)
34 {
35 hi_s32 ret;
36 drv_hdmi_status status = {0};
37 drv_hdmi_property property = {0};
38 hdmi_device *hdmi_dev = HI_NULL;
39 hdmi_sink_capability *sink_cap = HI_NULL;
40
41 hdmi_info("\n---HDMI kernel event(no user_call_back): HOTPLUG. --- \n");
42
43 hdmi_dev = get_hdmi_device(hdmi_id);
44 hdmi_if_null_return_void(hdmi_dev);
45
46 get_hdmi_default_action_set(hdmi_dev, HDMI_DEFAULT_ACTION_HDMI);
47 ret = drv_hdmi_edid_capability_get(&hdmi_dev->edid_info, &sink_cap);
48 if (ret == HDMI_EDID_DATA_INVALID) {
49 hdmi_warn("get sink capability err!\n");
50 }
51
52 status.hdmi_id = hdmi_id;
53 ret = hdmi_ext_ioctl(CMD_HDMI_GET_STATUS, &status);
54 if (ret != HI_SUCCESS) {
55 hdmi_err("get HDMI status err!\n");
56 return;
57 }
58 if (status.status.connected == HI_FALSE) {
59 hdmi_err("no connect!\n");
60 return;
61 }
62 hdmi_info("connected !\n");
63 property.hdmi_id = hdmi_id;
64 ret = hdmi_ext_ioctl(CMD_HDMI_GET_ATTR, &property);
65 if (ret != HI_SUCCESS) {
66 hdmi_err("get hdmi attr err!\n");
67 return;
68 }
69 hdmi_info("CMD_HDMI_GET_ATTR ok! \n");
70 ret = hdmi_ext_ioctl(CMD_HDMI_SET_ATTR, &property);
71 if (ret != HI_SUCCESS) {
72 hdmi_err("set attr err!:0x%x\n", ret);
73 }
74 hdmi_info("CMD_HDMI_SET_ATTR ok! \n");
75 ret = hdmi_ext_ioctl(CMD_HDMI_START, &hdmi_id);
76 if (ret != HI_SUCCESS) {
77 hdmi_err("hdmi start err!:0x%x\n", ret);
78 return;
79 }
80 hdmi_info("CMD_HDMI_START ok! \n");
81
82 return;
83 }
84
hdmi_hot_unplug_process(hdmi_device_id hdmi_id)85 static hi_void hdmi_hot_unplug_process(hdmi_device_id hdmi_id)
86 {
87 hi_s32 ret;
88
89 ret = hdmi_ext_ioctl(CMD_HDMI_STOP, &hdmi_id);
90 if (ret != HI_SUCCESS) {
91 hdmi_err("hdmi stop err!:0x%x\n", ret);
92 return;
93 }
94 hdmi_info("CMD_HDMI_STOP ok! \n");
95
96 return;
97 }
98
hi_drv_hdmi_kernel_event_callback(hi_void * data,hdmi_event event)99 hi_s32 hi_drv_hdmi_kernel_event_callback(hi_void *data, hdmi_event event)
100 {
101 hdmi_device_id hdmi_id;
102 hi_u32 need_hpd_process;
103 hdmi_device *hdmi_dev = HI_NULL;
104
105 hdmi_if_null_return(data, HI_FAILURE);
106
107 hdmi_id = *(hdmi_device_id *)data;
108 hdmi_dev = get_hdmi_device(hdmi_id);
109 hdmi_if_null_return(hdmi_dev, HI_FAILURE);
110
111 need_hpd_process = ((hi_u32)hdmi_dev->run_state & HDMI_RUN_STATE_START) ||
112 ((hi_u32)hdmi_dev->run_state & HDMI_RUN_STATE_STOP);
113 if (need_hpd_process) {
114 if (event == HDMI_EVENT_HOTPLUG) {
115 hdmi_hot_plug_process(hdmi_id);
116 } else if (event == HDMI_EVENT_HOTUNPLUG) {
117 hdmi_hot_unplug_process(hdmi_id);
118 }
119 }
120
121 return HI_SUCCESS;
122 }
123
124 #if (defined(CONFIG_HI_PLATFORM_H8))
csc_param_check(const hdmi_csc_param * csc_param)125 static hi_s32 csc_param_check(const hdmi_csc_param *csc_param)
126 {
127 if (csc_param->colorimetry != HI_HDMI_COLORIMETRY_ITU601 &&
128 csc_param->colorimetry != HI_HDMI_COLORIMETRY_ITU709 &&
129 csc_param->colorimetry != HI_HDMI_COLORIMETRY_2020_CONST_LUMINOUS &&
130 csc_param->colorimetry != HI_HDMI_COLORIMETRY_2020_NON_CONST_LUMINOUS) {
131 hdmi_err("colorimetry err!\n");
132 return HI_FAILURE;
133 }
134
135 if (csc_param->quantization != HI_HDMI_QUANT_RANGE_LIMITED &&
136 csc_param->quantization != HI_HDMI_QUANT_RANGE_FULL) {
137 hdmi_err("quantization err!\n");
138 return HI_FAILURE;
139 }
140
141 return HI_SUCCESS;
142 }
143
video_param_check(const hdmi_video_param * video_param)144 static hi_s32 video_param_check(const hdmi_video_param *video_param)
145 {
146 if (video_param->pixel_encoding != HI_HDMI_COLORSPACE_RGB &&
147 video_param->pixel_encoding != HI_HDMI_COLORSPACE_YCBCR444) {
148 hdmi_err("pixel_encoding err!\n");
149 return HI_FAILURE;
150 }
151
152 return HI_SUCCESS;
153 }
154
hi_drv_hdmi_csc_param_set(hdmi_dev_id hdmi,const hdmi_csc_param * csc_param)155 hi_s32 hi_drv_hdmi_csc_param_set(hdmi_dev_id hdmi, const hdmi_csc_param *csc_param)
156 {
157 hi_s32 ret;
158 hdmi_device *hdmi_dev = HI_NULL;
159 drv_hdmi_vo_attr video_attr = {0};
160
161 hdmi_info("in...\n");
162
163 if (get_hdmi_device(hdmi) == HI_NULL) {
164 hdmi_err("device id is wrong\n");
165 return HI_FAILURE;
166 }
167
168 hdmi_dev = get_hdmi_device(hdmi);
169 hdmi_if_null_return(csc_param, HI_FAILURE);
170
171 /* param check */
172 ret = csc_param_check(csc_param);
173 if (ret != HI_SUCCESS) {
174 hdmi_err("csc_param_check fail... \n");
175 return ret;
176 }
177
178 hdmi_dev->csc_param.colorimetry = csc_param->colorimetry;
179 hdmi_dev->csc_param.quantization = csc_param->quantization;
180 /* HDMI not open */
181 if (hdmi_dev->kernel_cnt == 0 && hdmi_dev->user_cnt == 0) {
182 hdmi_warn("device not open! save param to dev. colorimetry=%u, quantization=%u\n",
183 csc_param->colorimetry, csc_param->quantization);
184 return HI_SUCCESS;
185 } else {
186 hdmi_dev->attr.app_attr.out_csc_quantization = csc_param->quantization;
187 ret = hdmi_ext_ioctl(CMD_HDMI_GET_VO_ATTR, &video_attr);
188 if (ret != HI_SUCCESS) {
189 hdmi_err("get vo attr fail... \n");
190 return ret;
191 }
192 video_attr.hdmi_id = hdmi;
193 video_attr.vo_attr.colorimetry = csc_param->colorimetry;
194 ret = hdmi_ext_ioctl(CMD_HDMI_SET_VO_ATTR, &video_attr);
195 if (ret != HI_SUCCESS) {
196 hdmi_err("set attr fail... \n");
197 return ret;
198 }
199 }
200 hdmi_info("out...\n");
201
202 return ret;
203 }
204
hi_drv_hdmi_video_param_set(hdmi_dev_id hdmi,const hdmi_video_param * video_param)205 hi_s32 hi_drv_hdmi_video_param_set(hdmi_dev_id hdmi, const hdmi_video_param *video_param)
206 {
207 hi_s32 ret;
208 hdmi_device *hdmi_dev = HI_NULL;
209 drv_hdmi_vo_attr vid_attr = {0};
210
211 hdmi_info("in...\n");
212
213 if (get_hdmi_device(hdmi) == HI_NULL) {
214 hdmi_err("device id is wrong\n");
215 return HI_FAILURE;
216 }
217
218 hdmi_dev = get_hdmi_device(hdmi);
219 hdmi_if_null_return(hdmi_dev, HI_FAILURE);
220 hdmi_if_null_return(video_param, HI_FAILURE);
221
222 /* param check */
223 ret = video_param_check(video_param);
224 if (ret != HI_SUCCESS) {
225 hdmi_err("video_param_check fail... \n");
226 return ret;
227 }
228
229 hdmi_dev->csc_param.pixel_encoding = video_param->pixel_encoding;
230
231 /* HDMI not open */
232 if (hdmi_dev->kernel_cnt == 0 && hdmi_dev->user_cnt == 0) {
233 hdmi_warn("device not open! save param to dev. pixel_encoding = %u\n", video_param->pixel_encoding);
234 return HI_SUCCESS;
235 } else {
236 hdmi_dev->attr.app_attr.out_color_space = video_param->pixel_encoding;
237 hdmi_dev->attr.vo_attr.in_color_space = video_param->pixel_encoding;
238 ret = hdmi_ext_ioctl(CMD_HDMI_GET_VO_ATTR, &vid_attr);
239 if (ret != HI_SUCCESS) {
240 hdmi_err("get vo attr fail... \n");
241 return ret;
242 }
243 vid_attr.hdmi_id = hdmi;
244 ret = hdmi_ext_ioctl(CMD_HDMI_SET_VO_ATTR, &vid_attr);
245 if (ret != HI_SUCCESS) {
246 hdmi_err("set attr fail... \n");
247 return ret;
248 }
249 }
250 hdmi_info("out...\n");
251
252 return ret;
253 }
254 #endif
255
hi_drv_hdmi_stop(hdmi_dev_id hdmi)256 hi_s32 hi_drv_hdmi_stop(hdmi_dev_id hdmi)
257 {
258 hi_s32 ret;
259
260 hdmi_info("in...\n");
261 ret = drv_hdmi_cmd_process(CMD_HDMI_STOP, (hi_void *)(&hdmi), HI_FALSE);
262 if (ret != HI_SUCCESS) {
263 hdmi_err("stop hdmi err!:0x%x\n", ret);
264 return ret;
265 }
266 hdmi_info("out...\n");
267
268 return ret;
269 }
270
271 #ifdef HDMI_HDR_SUPPORT
disp_to_hdmi_hdr_attr(const hdmi_device * hdmi_dev,drv_hdmi_hdr_attr * drv_hdr_attr,const hdmi_hdr_attr * hdr_attr)272 static hi_void disp_to_hdmi_hdr_attr(const hdmi_device *hdmi_dev, drv_hdmi_hdr_attr *drv_hdr_attr,
273 const hdmi_hdr_attr *hdr_attr)
274 {
275 errno_t ret;
276 hdmi_if_null_return_void(hdmi_dev);
277 hdmi_if_null_return_void(drv_hdr_attr);
278
279 drv_hdr_attr->hdr_mode = hdr_attr->hdr_mode;
280 drv_hdr_attr->user_hdr_mode = hdmi_dev->attr.hdr_attr.user_hdr_mode;
281 drv_hdr_attr->colorimetry = hdr_attr->colorimetry;
282 drv_hdr_attr->eotf_type = hdr_attr->eotf_type;
283 drv_hdr_attr->metadata_id = hdr_attr->metadata_id;
284 ret = memcpy_s(&(drv_hdr_attr->un_descriptor), sizeof(drv_hdr_attr->un_descriptor),
285 &(hdr_attr->descriptor), sizeof(hdmi_meta_descriptor));
286 hdmi_unequal_eok_return_void(ret);
287
288 return;
289 }
290
hi_drv_hdmi_set_hdr_attr(hdmi_dev_id hdmi,const hdmi_hdr_attr * hdr_attr)291 hi_s32 hi_drv_hdmi_set_hdr_attr(hdmi_dev_id hdmi, const hdmi_hdr_attr *hdr_attr)
292 {
293 hi_s32 ret;
294 drv_hdmi_hdr drv_hdr = {0};
295 hdmi_device *hdmi_dev = HI_NULL;
296 drv_hdmi_hdr_attr *drv_hdr_attr = HI_NULL;
297
298 hdmi_dev = get_hdmi_device(hdmi);
299 if (hdmi_dev == HI_NULL) {
300 hdmi_warn("device id is wrong\n");
301 return HI_FAILURE;
302 }
303 if (hdmi_dev->kernel_cnt == 0 && hdmi_dev->user_cnt == 0) {
304 hdmi_warn("device not open\n");
305 return HI_FAILURE;
306 }
307
308 hdmi_info("in...\n");
309 hdmi_if_null_return(hdr_attr, HI_FAILURE);
310
311 if (hdr_attr->hdr_mode == HI_HDMI_HDR_MODE_BUTT) {
312 return HI_FAILURE;
313 }
314 drv_hdr_attr = &drv_hdr.hdr_attr;
315 drv_hdr.hdmi_id = hdmi;
316 disp_to_hdmi_hdr_attr(hdmi_dev, drv_hdr_attr, hdr_attr);
317 ret = hdmi_ext_ioctl(CMD_HDMI_SET_HDR_ATTR, &drv_hdr);
318 if (ret != HI_SUCCESS) {
319 hdmi_info("set HDR attr fail... \n");
320 return ret;
321 }
322 hdmi_info("out...\n");
323
324 return ret;
325 }
326 #endif
327
328