• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2007-2019 Allwinnertech Co., Ltd.
3  * Author: zhengwanyu <zhengwanyu@allwinnertech.com>
4  *
5  * This software is licensed under the terms of the GNU General Public
6  * License version 2, as published by the Free Software Foundation, and
7  * may be copied, distributed, and modified under those terms.
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  */
15 #include "sunxi_hdmi20.h"
16 
17 static struct drv_model_info *hdmi20_drv;
18 static struct sunxi_hdmi *hwhdmi20;
19 static struct device_access reg_access;
20 struct system_functions low_functions;
21 u32 hdmi_printf;
22 
23 #define DDC_PIN_STATE_ACTIVE "ddc_active"
24 #define DDC_PIN_STATE_SLEEP "ddc_sleep"
25 #define CEC_PIN_STATE_ACTIVE "cec_active"
26 #define CEC_PIN_STATE_SLEEP "cec_sleep"
27 
28 #define ESM_REG_BASE_OFFSET 0x8000
29 #define HDCP22_FIRMWARE_SIZE	(1024 * 256)
30 #define HDCP22_DATA_SIZE	(1024 * 128)
31 
sunxi_hdmi20_get_hdmi(void)32 static struct sunxi_hdmi *sunxi_hdmi20_get_hdmi(void)
33 {
34 	if (hwhdmi20)
35 		return hwhdmi20;
36 	return NULL;
37 }
38 
sunxi_hdmi_get_funcs(void)39 struct sunxi_hdmi_funcs *sunxi_hdmi_get_funcs(void)
40 {
41 	struct sunxi_hdmi *hdmi = sunxi_hdmi20_get_hdmi();
42 
43 	return (struct sunxi_hdmi_funcs *)hdmi->funcs;
44 }
45 
register_func_to_drm(struct hdmi_dev_func func)46 void register_func_to_drm(struct hdmi_dev_func func)
47 {
48 	struct sunxi_hdmi *hdmi = sunxi_hdmi20_get_hdmi();
49 
50 	memcpy(&hdmi->dev_funcs, &func,
51 			sizeof(struct hdmi_dev_func));
52 }
53 
hdmi20_write(uintptr_t addr,u32 data)54 void hdmi20_write(uintptr_t addr, u32 data)
55 {
56 	asm volatile("dsb st");
57 	*((volatile u8 *)(hwhdmi20->reg_base + (addr >> 2))) = data;
58 }
59 
hdmi20_read(uintptr_t addr)60 u32 hdmi20_read(uintptr_t addr)
61 {
62 	return *((volatile u8 *)(hwhdmi20->reg_base + (addr >> 2)));
63 }
64 
65 static int
sunxi_hdmi20_video_dts_parse(struct platform_device * pdev,struct sunxi_hdmi * hdmi)66 sunxi_hdmi20_video_dts_parse(struct platform_device *pdev,
67 		struct sunxi_hdmi *hdmi)
68 {
69 	struct sunxi_hdmi_work_mode *params = &hdmi->init_params;
70 
71 	if (of_property_read_u32(pdev->dev.of_node,
72 			"dvi_hdmi", &params->hdmi_mode)) {
73 		HDMI_ERR("can NOT get dvi_hdmi\n");
74 		return -1;
75 	}
76 
77 	if (of_property_read_u32(pdev->dev.of_node,
78 			"color_format", &params->color_fmt)) {
79 		HDMI_ERR("can NOT get color_format\n");
80 		return -1;
81 	}
82 
83 	if (of_property_read_u32(pdev->dev.of_node,
84 			"color_depth", &params->color_depth)) {
85 		HDMI_ERR("can NOT get color_depth\n");
86 		return -1;
87 	}
88 
89 	if (of_property_read_u32(pdev->dev.of_node,
90 			"color_space", &params->color_space)) {
91 		HDMI_ERR("can NOT get color_space\n");
92 		return -1;
93 	}
94 
95 	if (of_property_read_u32(pdev->dev.of_node,
96 			"color_range", &params->color_range)) {
97 		HDMI_ERR("can NOT get color_range\n");
98 		return -1;
99 	}
100 
101 	if (of_property_read_u32(pdev->dev.of_node,
102 			"eotf", &params->eotf)) {
103 		HDMI_ERR("can NOT get color_eotf\n");
104 		return -1;
105 	}
106 
107 	if (of_property_read_u32(pdev->dev.of_node,
108 			"aspect_ratio", &params->aspect_ratio)) {
109 		HDMI_ERR("can NOT get aspect_ratio\n");
110 		return -1;
111 	}
112 
113 	return 0;
114 }
115 
116 static int
sunxi_hdmi20_hdcp_dts_parse(struct platform_device * pdev,struct sunxi_hdmi * hdmi)117 sunxi_hdmi20_hdcp_dts_parse(struct platform_device *pdev,
118 	struct sunxi_hdmi *hdmi)
119 {
120 	struct device_node *esm_np;
121 	u32 dts_esm_buff_phy_addr = 0, dts_esm_size_phy_addr = 0;
122 	void *dts_esm_buff_vir_addr = NULL, *dts_esm_size_vir_addr = NULL;
123 	u8 *esm_firm_vir_addr = NULL, *esm_data_vir_addr = NULL;
124 
125 	hdcpParams_t *hdcp = &hdmi->hdcp;
126 
127 /*Parse if we use hdcp functions in hdmi driver*/
128 	if (of_property_read_u32_array(pdev->dev.of_node,
129 			"hdmi_hdcp_enable", (u32 *)&hdcp->use_hdcp, 1)) {
130 		HDMI_INFO("WARN:can NOT get hdmi_hdcp_enable\n");
131 		return 0;
132 	}
133 
134 	if (hdcp->use_hdcp) {
135 		DRM_INFO("NOT use hdcp\n");
136 		return 0;
137 	}
138 
139 	if (of_property_read_u32_array(pdev->dev.of_node,
140 			"hdmi_hdcp22_enable", (u32 *)&hdcp->use_hdcp22, 1)) {
141 		HDMI_INFO("WARN:can NOT get hdmi_hdcp22_enable\n");
142 		return 0;
143 	}
144 
145 /*parse hdcp2.2*/
146 	if (!hdcp->use_hdcp22) {
147 		HDMI_INFO("NOT use hdcp2.2\n");
148 		return 0;
149 	}
150 
151 /*allocate dma memory for esm as firmware storage ram and ram for running programs*/
152 	esm_firm_vir_addr = dma_alloc_coherent(&pdev->dev,
153 		HDCP22_FIRMWARE_SIZE, &hdcp->esm_firm_phy_addr,
154 		GFP_KERNEL | __GFP_ZERO);
155 	if (!esm_firm_vir_addr) {
156 		HDMI_ERR("dma_alloc_coherent for esm firmware failed\n");
157 		goto failed;
158 	}
159 
160 	hdcp->esm_firm_vir_addr = (unsigned long)esm_firm_vir_addr;
161 	hdcp->esm_firm_size = HDCP22_FIRMWARE_SIZE;
162 
163 	esm_data_vir_addr = dma_alloc_coherent(&pdev->dev,
164 		HDCP22_FIRMWARE_SIZE, &hdcp->esm_data_phy_addr,
165 		GFP_KERNEL | __GFP_ZERO);
166 	if (!esm_firm_vir_addr) {
167 		HDMI_ERR("dma_alloc_coherent for esm firmware failed\n");
168 		goto failed;
169 	}
170 	hdcp->esm_data_vir_addr = (unsigned long)esm_data_vir_addr;
171 	hdcp->esm_data_size = HDCP22_DATA_SIZE;
172 
173 /*parse esm*/
174 	esm_np = of_find_node_by_name(NULL, "esm");
175 	if (!esm_np) {
176 		HDMI_ERR("can NOT get esm device node\n");
177 		goto failed;
178 	}
179 
180 /*obtain esm firmware size*/
181 	/*get physical address of esm firmware size*/
182 	if (of_property_read_u32_array(esm_np,
183 				"esm_img_size_addr",
184 				&dts_esm_size_phy_addr,
185 				1) && !dts_esm_size_phy_addr) {
186 		HDMI_ERR("read esm_img_size_addr form esm node failed\n");
187 		goto failed;
188 	}
189 	/*get esm firmware size*/
190 	dts_esm_size_vir_addr = __va(dts_esm_size_phy_addr);
191 	memcpy((void *)(&hdcp->esm_firm_size), dts_esm_size_vir_addr, 4);
192 
193 /*obtain esm firmware*/
194 	/*get physical address of esm firmware*/
195 	if (of_property_read_u32_array(esm_np,
196 				"esm_img_buff_addr",
197 				&dts_esm_buff_phy_addr,
198 				1) && !dts_esm_buff_phy_addr) {
199 		HDMI_ERR("read esm_img_buff_addr form esm node failed\n");
200 		goto failed;
201 	}
202 	/*get esm firmware*/
203 	dts_esm_buff_vir_addr = __va(dts_esm_buff_phy_addr);
204 	if (hdcp->esm_firm_size <= HDCP22_FIRMWARE_SIZE) {
205 		memcpy(esm_firm_vir_addr, dts_esm_buff_vir_addr,
206 						hdcp->esm_firm_size);
207 		return 0;
208 	}
209 	HDMI_ERR("get esm firmware failed\n");
210 
211 failed:
212 	if (esm_firm_vir_addr)
213 		dma_free_coherent(&pdev->dev, HDCP22_FIRMWARE_SIZE,
214 		esm_firm_vir_addr, hdcp->esm_firm_phy_addr);
215 	if (esm_data_vir_addr)
216 		dma_free_coherent(&pdev->dev, HDCP22_DATA_SIZE,
217 		esm_data_vir_addr, hdcp->esm_data_phy_addr);
218 	return -1;
219 }
220 
221 
222 
223 static int
sunxi_hdmi20_cec_dts_parse(struct platform_device * pdev,struct sunxi_hdmi * hdmi)224 sunxi_hdmi20_cec_dts_parse(struct platform_device *pdev,
225 	struct sunxi_hdmi *hdmi)
226 {
227 	struct cec_params *cec = &hdmi->cec;
228 
229 	/*get cec config*/
230 	if (of_property_read_u32(pdev->dev.of_node,
231 						   "hdmi_cec_support",
232 						   &cec->support)) {
233 		HDMI_INFO("WARN:can NOT get hdmi_cec_support\n");
234 		return 0;
235 	}
236 
237 	if (!cec->support) {
238 		DRM_INFO("WARN:NOT support cec\n");
239 		return 0;
240 	}
241 
242 	if (of_property_read_u32(pdev->dev.of_node,
243 				"hdmi_cec_super_standby",
244 				&cec->support_super_standby)) {
245 		HDMI_INFO("WARN:can NOT get hdmi_cec_super_standby\n");
246 		return 0;
247 	}
248 
249 	return 0;
250 }
251 
sunxi_hdmi20_hdcp_init(void)252 static int sunxi_hdmi20_hdcp_init(void)
253 {
254 	struct sunxi_hdmi *hdmi = sunxi_hdmi20_get_hdmi();
255 	hdcpParams_t *hdcp = &hdmi->hdcp;
256 
257 	if (!hdcp->use_hdcp)
258 		return 0;
259 
260 	if (!hdcp->use_hdcp22)
261 		return 0;
262 
263 	hdcp->hdcp_on = 0;
264 	hdcp->mEnable11Feature = -1;
265 	hdcp->mRiCheck = -1;
266 	hdcp->mI2cFastMode = -1;
267 	hdcp->mEnhancedLinkVerification = -1;
268 	hdcp->maxDevices = 0;
269 	hdcp->mKsvListBuffer = NULL;
270 	hdcp->mAksv = NULL;
271 	hdcp->mKeys = NULL;
272 	hdcp->mSwEncKey = NULL;
273 
274 	hdcp->esm_hpi_base = (unsigned long)hdmi->reg_base
275 		+ ESM_REG_BASE_OFFSET;
276 	return 0;
277 }
278 
sunxi_hdmi20_audio_init(void)279 static int sunxi_hdmi20_audio_init(void)
280 {
281 	struct sunxi_hdmi *hdmi = sunxi_hdmi20_get_hdmi();
282 	audioParams_t *audio = &hdmi->audio;
283 
284 	audio->mInterfaceType = I2S;
285 	audio->mCodingType = PCM;
286 	audio->mSamplingFrequency = 44100;
287 	audio->mChannelAllocation = 0;
288 	audio->mChannelNum = 2;
289 	audio->mSampleSize = 16;
290 	audio->mClockFsFactor = 64;
291 	audio->mPacketType = PACKET_NOT_DEFINED;
292 	audio->mDmaBeatIncrement = DMA_NOT_DEFINED;
293 
294 	return 0;
295 }
296 
297 static bool hdmi20_clk_enable;
sunxi_hdmi20_clk_enable(struct sunxi_hdmi * hdmi)298 int sunxi_hdmi20_clk_enable(struct sunxi_hdmi *hdmi)
299 {
300 	int ret;
301 	unsigned long tcon_tv_rate;
302 	struct clk *tcon_tv_clk;
303 
304 	tcon_tv_clk = clk_get(NULL, "tcon_tv");
305 	tcon_tv_rate = clk_get_rate(tcon_tv_clk);
306 	clk_set_rate(hdmi->mclk, tcon_tv_rate);
307 
308 	if (hdmi20_clk_enable)
309 		return 0;
310 	hdmi20_clk_enable = true;
311 
312 	ret = clk_prepare_enable(hdmi->mclk);
313 	if (ret < 0) {
314 		HDMI_ERR("fail to enable hdmi mclk\n");
315 		return -1;
316 	}
317 
318 	ret = clk_prepare_enable(hdmi->ddc_clk);
319 	if (ret < 0) {
320 		HDMI_ERR("fail to enable hdmi ddc clk\n");
321 		return -1;
322 	}
323 
324 	if (hdmi->hdcp.use_hdcp) {
325 		ret = clk_prepare_enable(hdmi->hdcp_clk);
326 		if (ret < 0) {
327 			HDMI_ERR("fail to enable hdmi hdcp clk\n");
328 			return -1;
329 		}
330 	}
331 
332 	if (hdmi->cec.support) {
333 		ret = clk_prepare_enable(hdmi->cec_clk);
334 		if (ret < 0) {
335 			HDMI_ERR("fail to enable hdmi cec clk\n");
336 			return -1;
337 		}
338 	}
339 
340 	return 0;
341 }
342 
sunxi_hdmi20_clk_disable(struct sunxi_hdmi * hdmi)343 static int sunxi_hdmi20_clk_disable(struct sunxi_hdmi *hdmi)
344 {
345 	if (!hdmi20_clk_enable)
346 		return 0;
347 	hdmi20_clk_enable = false;
348 
349 	if (__clk_get_enable_count(hdmi->mclk))
350 		clk_disable_unprepare(hdmi->mclk);
351 
352 	if (__clk_get_enable_count(hdmi->ddc_clk))
353 		clk_disable_unprepare(hdmi->ddc_clk);
354 
355 	if (__clk_get_enable_count(hdmi->hdcp_clk))
356 		clk_disable_unprepare(hdmi->hdcp_clk);
357 
358 	if (__clk_get_enable_count(hdmi->cec_clk))
359 		clk_disable_unprepare(hdmi->cec_clk);
360 
361 	return 0;
362 }
363 
sunxi_hdmi20_get_dtd(dtd_t * dtd,struct disp_video_timings * timing)364 static void sunxi_hdmi20_get_dtd(dtd_t *dtd,
365 				struct disp_video_timings *timing)
366 {
367 	dtd->mPixelRepetitionInput = timing->pixel_repeat;
368 	dtd->mInterlaced = timing->b_interlace;
369 
370 	dtd->mCode = timing->vic;
371 	dtd->mPixelClock = timing->pixel_clk * (timing->pixel_repeat + 1)
372 		* (timing->b_interlace + 1) / 1000;
373 
374 	dtd->mHActive = timing->x_res * (timing->pixel_repeat + 1);
375 	dtd->mHBlanking = (timing->hor_total_time- timing->x_res) * (timing->pixel_repeat + 1);
376 	dtd->mHSyncOffset = timing->hor_front_porch * (timing->pixel_repeat + 1);
377 	dtd->mHSyncPulseWidth = timing->hor_sync_time * (timing->pixel_repeat + 1);
378 
379 	dtd->mVActive = timing->y_res / (timing->b_interlace + 1);
380 	dtd->mVBlanking = timing->ver_total_time- timing->y_res;
381 	dtd->mVSyncOffset = timing->ver_front_porch;
382 	dtd->mVSyncPulseWidth = timing->ver_sync_time;
383 
384 	dtd->mHSyncPolarity = timing->hor_sync_polarity;
385 	dtd->mVSyncPolarity = timing->ver_sync_polarity;
386 
387 	DRM_INFO("dtd: vsync:%d hsync:%d       timing: vysnc:%d hsync:%d\n",
388 		dtd->mVSyncPolarity, dtd->mHSyncPolarity, timing->ver_sync_polarity, timing->hor_sync_polarity);
389 }
390 
sunxi_hdmi20_fill_params(struct sunxi_hdmi * hdmi,struct disp_video_timings * timing)391 static int sunxi_hdmi20_fill_params(struct sunxi_hdmi *hdmi,
392 		struct disp_video_timings *timing)
393 {
394 	videoParams_t *video = &hdmi->video;
395 	productParams_t *product = &hdmi->product;
396 	dtd_t *dtd = &video->mDtd;
397 	sink_edid_t *sink = &hdmi->sink_caps;
398 
399 /*get dertailed timings from vic*/
400 	sunxi_hdmi20_get_dtd(dtd, timing);
401 
402 	video->mCea_code = 0;
403 	video->mHdmi_code = 0;
404 
405 	/*hdmi vic or cea vic for 4k*/
406 	if ((timing->x_res == 3840 && timing->y_res == 2160)
407 		|| (timing->x_res == 4096 && timing->y_res == 2160)) {
408 		if ((timing->vic <= 4) && (timing->vic >= 1)) {
409 			video->mCea_code = 0;
410 			video->mHdmi_code = timing->vic;
411 		} else {
412 			video->mCea_code = timing->vic;
413 			video->mHdmi_code = 0;
414 		}
415 	} else {
416 		video->mCea_code = timing->vic;
417 		video->mHdmi_code = 0;
418 	}
419 
420 	/*if hdmi sink support hdmi2.0*/
421 	video->mHdmi20 = sink->edid_m20Sink;
422 	video->scdc_ability = sink->edid_mHdmiForumvsdb.mSCDC_Present;
423 
424 	if (video->mHdmi_code) {
425 		product->mVendorPayload[0] = 0x20;
426 		product->mVendorPayload[1] = video->mHdmi_code;
427 		product->mVendorPayload[2] = 0;
428 		product->mVendorPayload[3] = 0;
429 		product->mVendorPayloadLength = 4;
430 	} else if (video->mCea_code) {
431 		product->mVendorPayload[0] = 0;
432 		product->mVendorPayload[1] = 0;
433 		product->mVendorPayload[2] = 0;
434 		product->mVendorPayload[3] = 0;
435 		product->mVendorPayloadLength = 4;
436 	}
437 
438 /*set vendor speciffic info frame: IEEE codes and payload*/
439 	/*hdmi20 video format: 4k50/4k60*/
440 	if (video->mCea_code == 96 || video->mCea_code == 97
441 		|| video->mCea_code == 101 || video->mCea_code == 102) {
442 		product->mOUI = 0xc45dd8;
443 
444 		product->mVendorPayload[0] = 0x01;
445 		product->mVendorPayload[1] = 0;
446 		product->mVendorPayload[2] = 0;
447 		product->mVendorPayload[3] = 0;
448 		product->mVendorPayloadLength = 4;
449 	} else
450 		product->mOUI = 0x000c03;
451 
452 /*set info frame for 3d*/
453 	if (timing->b_interlace) {
454 		video->mHdmiVideoFormat = 0x02;
455 		video->m3dStructure = 0;
456 	} else if (video->mHdmi_code) {
457 		video->mHdmiVideoFormat = 0x01;
458 		video->m3dStructure = 0;
459 	} else {
460 		video->mHdmiVideoFormat = 0x0;
461 		video->m3dStructure = 0;
462 	}
463 
464 	return 0;
465 }
466 
sunxi_hdmi20_get_connect_status(void)467 static int sunxi_hdmi20_get_connect_status(void)
468 {
469 	int status, time_out = 5;
470 	struct sunxi_hdmi *hdmi = sunxi_hdmi20_get_hdmi();
471 	struct hdmi_dev_func *dev_funcs = &hdmi->dev_funcs;
472 
473 	/* read hdmi connected status with anti-shake check */
474 	/* the connected status should remain unchanged for 20*5 ms */
475 	status = dev_funcs->dev_hpd_status();
476 	while (time_out) {
477 		msleep(20);
478 		if (status == dev_funcs->dev_hpd_status())
479 			--time_out;
480 		else {
481 			time_out = 5;
482 			status = dev_funcs->dev_hpd_status();
483 		}
484 	}
485 
486 	return status;
487 }
488 
489 static void
sunxi_hdmi20_get_working_mode(struct sunxi_hdmi_work_mode * work_mode)490 sunxi_hdmi20_get_working_mode(struct sunxi_hdmi_work_mode *work_mode)
491 {
492 	struct sunxi_hdmi *hdmi = sunxi_hdmi20_get_hdmi();
493 	videoParams_t *video = &hdmi->video;
494 
495 	if (video->mHdmi == MODE_UNDEFINED
496 		|| video->mHdmi == DVI)
497 			work_mode->hdmi_mode = DISP_DVI;
498 	else if (video->mHdmi == HDMI)
499 			work_mode->hdmi_mode = DISP_HDMI;
500 
501 	if (video->mEncodingIn == ENC_UNDEFINED
502 		|| video->mEncodingIn == RGB)
503 		work_mode->color_fmt = DISP_CSC_TYPE_RGB;
504 	else if (video->mEncodingIn == YCC444)
505 		work_mode->color_fmt = DISP_CSC_TYPE_YUV444;
506 	else if (video->mEncodingIn == YCC422)
507 		work_mode->color_fmt = DISP_CSC_TYPE_YUV422;
508 	else if (video->mEncodingIn == YCC420)
509 		work_mode->color_fmt = DISP_CSC_TYPE_YUV420;
510 
511 
512 	if (video->mColorResolution == COLOR_DEPTH_INVALID
513 		|| video->mColorResolution == COLOR_DEPTH_8)
514 		work_mode->color_depth = DISP_DATA_8BITS;
515 	else if (video->mColorResolution == COLOR_DEPTH_10)
516 		work_mode->color_depth = DISP_DATA_10BITS;
517 	else if (video->mColorResolution == COLOR_DEPTH_12)
518 		work_mode->color_depth = DISP_DATA_12BITS;
519 	else if (video->mColorResolution == COLOR_DEPTH_16)
520 		work_mode->color_depth = DISP_DATA_16BITS;
521 
522 	if (video->mColorimetry == ITU601)
523 		work_mode->color_space = DISP_BT601;
524 	else if (video->mColorimetry == ITU709)
525 		work_mode->color_space = DISP_BT709;
526 	else if (video->mColorimetry == EXTENDED_COLORIMETRY
527 		&& video->mExtColorimetry == BT2020_Y_CB_CR)
528 		work_mode->color_space = DISP_BT2020NC;
529 
530 	if (video->pb->eotf == SDR_LUMINANCE_RANGE)
531 		work_mode->eotf = DISP_EOTF_GAMMA22;
532 	else if (video->pb->eotf == HDR_LUMINANCE_RANGE)
533 		work_mode->eotf = DISP_EOTF_SMPTE2084;
534 	else if (video->pb->eotf == HLG)
535 		work_mode->eotf = DISP_EOTF_ARIB_STD_B67;
536 
537 	if (video->mRgbQuantizationRange == 0)
538 		work_mode->color_range = DISP_COLOR_RANGE_DEFAULT;
539 	else if (video->mRgbQuantizationRange == 2)
540 		work_mode->color_range = DISP_COLOR_RANGE_0_255;
541 	else if (video->mRgbQuantizationRange == 1)
542 		work_mode->color_range = DISP_COLOR_RANGE_16_235;
543 
544 	work_mode->aspect_ratio = video->mActiveFormatAspectRatio;
545 }
546 
547 static int
sunxi_hdmi20_set_working_mode(struct sunxi_hdmi_work_mode * work_mode)548 sunxi_hdmi20_set_working_mode(struct sunxi_hdmi_work_mode *work_mode)
549 {
550 	struct sunxi_hdmi *hdmi = sunxi_hdmi20_get_hdmi();
551 	videoParams_t *video = &hdmi->video;
552 
553 	video->mHdmi = (work_mode->hdmi_mode == DISP_HDMI) ?
554 			HDMI : DVI;
555 
556 	if (work_mode->color_fmt == DISP_CSC_TYPE_RGB) {
557 		video->mEncodingIn = RGB;
558 		video->mEncodingOut = RGB;
559 	} else if (work_mode->color_fmt == DISP_CSC_TYPE_YUV444) {
560 		video->mEncodingIn = YCC444;
561 		video->mEncodingOut = YCC444;
562 	} else if (work_mode->color_fmt == DISP_CSC_TYPE_YUV422) {
563 		video->mEncodingIn = YCC422;
564 		video->mEncodingOut = YCC422;
565 	} else if (work_mode->color_fmt == DISP_CSC_TYPE_YUV420) {
566 		video->mEncodingIn = YCC420;
567 		video->mEncodingOut = YCC420;
568 	}
569 
570 	if (work_mode->color_depth == DISP_DATA_8BITS)
571 		video->mColorResolution = COLOR_DEPTH_8;
572 	else if (work_mode->color_depth == DISP_DATA_10BITS)
573 		video->mColorResolution = COLOR_DEPTH_10;
574 	else if (work_mode->color_depth == DISP_DATA_12BITS)
575 		video->mColorResolution = COLOR_DEPTH_12;
576 	else if (work_mode->color_depth == DISP_DATA_16BITS)
577 		video->mColorResolution = COLOR_DEPTH_16;
578 
579 	if (work_mode->color_space == DISP_BT601)
580 		video->mColorimetry = ITU601;
581 	else if (work_mode->color_space == DISP_BT709)
582 		video->mColorimetry = ITU709;
583 	else if (work_mode->color_space == DISP_BT2020NC) {
584 		video->mColorimetry = EXTENDED_COLORIMETRY;
585 		video->mExtColorimetry = BT2020_Y_CB_CR;
586 	} else {
587 		video->mColorimetry = ITU709;
588 	}
589 
590 	if (work_mode->eotf == DISP_EOTF_GAMMA22)
591 		video->pb->eotf = SDR_LUMINANCE_RANGE;
592 	else if (work_mode->eotf == DISP_EOTF_SMPTE2084)
593 		video->pb->eotf = HDR_LUMINANCE_RANGE;
594 	else if (work_mode->eotf == DISP_EOTF_ARIB_STD_B67)
595 		video->pb->eotf = HLG;
596 	else
597 		video->pb->eotf = SDR_LUMINANCE_RANGE;
598 
599 	video->mRgbQuantizationRange = work_mode->color_range;
600 	video->mActiveFormatAspectRatio = work_mode->aspect_ratio;
601 
602 	return 0;
603 }
604 
sunxi_hdmi20_get_edid_block(void * data,unsigned char * buf,unsigned int block,size_t len)605 static int sunxi_hdmi20_get_edid_block(void *data, unsigned char *buf,
606 		unsigned int block, size_t len)
607 {
608 	struct sunxi_hdmi *hdmi = sunxi_hdmi20_get_hdmi();
609 
610 	return hdmi->dev_funcs.get_edid_block(buf, block, len);
611 }
612 
sunxi_hdmi20_get_sink_caps(void)613 static sink_edid_t *sunxi_hdmi20_get_sink_caps(void)
614 {
615 	struct sunxi_hdmi *hdmi = sunxi_hdmi20_get_hdmi();
616 
617 	return &hdmi->sink_caps;
618 }
619 
sunxi_hdmi20_get_init_params(void)620 static struct sunxi_hdmi_work_mode *sunxi_hdmi20_get_init_params(void)
621 {
622 	struct sunxi_hdmi *hdmi = sunxi_hdmi20_get_hdmi();
623 
624 	return &hdmi->init_params;
625 }
626 
hdmi20_dump_video_para(videoParams_t * para)627 static void hdmi20_dump_video_para(videoParams_t *para)
628 {
629 	DRM_INFO("hdmi mode:%d  cea_code:%d hdmi_code:%d\n",
630 		para->mHdmi, para->mCea_code, para->mHdmi_code);
631 	DRM_INFO("format in:%d out:%d\n", para->mEncodingOut, para->mEncodingIn);
632 	DRM_INFO("depth:%d\n", para->mColorResolution);
633 	DRM_INFO("pixel_repeat:%d\n", para->mPixelRepetitionFactor);
634 	DRM_INFO("mColorimetry:%d\n", para->mColorimetry);
635 	DRM_INFO("mHdmiVideoFormat:%d\n", para->mHdmiVideoFormat);
636 	DRM_INFO("m3dStructure:%d\n", para->m3dStructure);
637 	DRM_INFO("mHdmiVic:%d mHdmi20:%d scdc_ability:%d\n",
638 		para->mHdmiVic, para->mHdmi20, para->scdc_ability);
639 	DRM_INFO("mActiveFormatAspectRatio:%d\n", para->mActiveFormatAspectRatio);
640 	DRM_INFO("mRgbQuantizationRange:%d\n", para->mRgbQuantizationRange);
641 }
642 
643 static int
sunxi_hdmi20_enable(struct disp_video_timings * timing)644 sunxi_hdmi20_enable(struct disp_video_timings *timing)
645 {
646 	int ret;
647 	struct sunxi_hdmi *hdmi = sunxi_hdmi20_get_hdmi();
648 	struct hdmi_dev_func *dev_funcs = &hdmi->dev_funcs;
649 
650 	ret = sunxi_hdmi20_fill_params(hdmi, timing);
651 	if (ret < 0) {
652 		HDMI_ERR("sunxi_hdmi20_fill_params failed\n");
653 		return ret;
654 	}
655 
656 	hdmi20_dump_video_para(&hdmi->video);
657 	ret = dev_funcs->main_config(&hdmi->video, &hdmi->audio,
658 			&hdmi->product, &hdmi->hdcp, 301);
659 	if (ret < 0) {
660 		HDMI_ERR("hdmi main_config failed!\n");
661 		return ret;
662 	}
663 
664 	return 0;
665 }
666 
667 static int
sunxi_hdmi20_sw_enable(struct disp_video_timings * timing)668 sunxi_hdmi20_sw_enable(struct disp_video_timings *timing)
669 {
670 	return 0;
671 }
672 
sunxi_hdmi20_disable(void)673 static void sunxi_hdmi20_disable(void)
674 {
675 	struct sunxi_hdmi *hdmi = sunxi_hdmi20_get_hdmi();
676 	struct hdmi_dev_func *dev_funcs = &hdmi->dev_funcs;
677 
678 	dev_funcs->avmute_enable(1);
679 	dev_funcs->device_close();
680 
681 	sunxi_hdmi20_clk_disable(hdmi);
682 	msleep(5);
683 	sunxi_hdmi20_clk_enable(hdmi);
684 	dev_funcs->hpd_enable(1);
685 }
686 
687 static const struct sunxi_hdmi_funcs hdmi20_funcs = {
688 	.get_init_params = sunxi_hdmi20_get_init_params,
689 	.get_connect_status = sunxi_hdmi20_get_connect_status,
690 
691 	.set_working_mode = sunxi_hdmi20_set_working_mode,
692 	.get_working_mode = sunxi_hdmi20_get_working_mode,
693 
694 	.get_edid_block = sunxi_hdmi20_get_edid_block,
695 	.get_sink_caps = sunxi_hdmi20_get_sink_caps,
696 
697 	.enable = sunxi_hdmi20_enable,
698 	.sw_enable = sunxi_hdmi20_sw_enable,
699 	.disable = sunxi_hdmi20_disable,
700 };
701 
sunxi_hdmi20_power_init(struct platform_device * pdev,struct sunxi_hdmi * hdmi)702 static int sunxi_hdmi20_power_init(struct platform_device *pdev,
703 					 struct sunxi_hdmi *hdmi)
704 {
705 	int ret = 0, i;
706 	char power_name[20];
707 
708 	if (of_property_read_u32(pdev->dev.of_node,
709 				"hdmi_power_cnt",
710 				&hdmi->power_count)) {
711 		pr_err("ERROR: can not get hdmi_power_cnt\n");
712 		return -1;
713 	}
714 
715 	for (i = 0; i < hdmi->power_count; i++) {
716 		const char *hdmi_power;
717 
718 		sprintf(power_name, "hdmi_power%d", i);
719 		if (of_property_read_string(pdev->dev.of_node,
720 					 power_name, &hdmi_power)) {
721 			pr_err("Error: get %s failed\n", power_name);
722 			ret = -1;
723 		} else {
724 			DRM_INFO("Get hdmi_power%d:%s\n", i, hdmi_power);
725 			memcpy((void *)hdmi->power[i], hdmi_power,
726 					strlen(hdmi_power) + 1);
727 			sunxi_drm_sys_power_enable(NULL, hdmi->power[i]); /* fix me */
728 		}
729 	}
730 
731 	return 0;
732 }
733 
sunxi_hdmi20_clk_init(struct platform_device * pdev,struct sunxi_hdmi * hdmi)734 static int sunxi_hdmi20_clk_init(struct platform_device *pdev,
735 					 struct sunxi_hdmi *hdmi)
736 {
737 	int ret;
738 	int index = 0;
739 
740 	/* get hdmi main clk */
741 	hdmi->mclk = of_clk_get(pdev->dev.of_node, index);
742 	if (IS_ERR(hdmi->mclk)) {
743 		 HDMI_ERR("fail to get clk for hdmi\n");
744 		 return -1;
745 	}
746 
747 	hdmi->mclk_parent = clk_get_parent(hdmi->mclk);
748 	if (IS_ERR(hdmi->mclk_parent)) {
749 		 HDMI_ERR("fail to get clk parent for hdmi\n");
750 		 return -1;
751 	}
752 
753 	if (__clk_get_enable_count(hdmi->mclk) == 0) {
754 		 ret = clk_prepare_enable(hdmi->mclk);
755 		 if (ret < 0) {
756 			 HDMI_ERR("fail to enable hdmi mclk\n");
757 			 return -1;
758 		 }
759 	}
760 
761 	index++;
762 	/* get ddc clk for hdmi ddc function like edid reading
763 	* and hdcp authentication
764 	*/
765 	hdmi->ddc_clk = of_clk_get(pdev->dev.of_node, index);
766 	if (IS_ERR(hdmi->ddc_clk)) {
767 		 HDMI_ERR("fail to get clk for hdmi ddc\n");
768 		 return -1;
769 	}
770 
771 	if (__clk_get_enable_count(hdmi->ddc_clk) == 0) {
772 		 ret = clk_prepare_enable(hdmi->ddc_clk);
773 		 if (ret < 0) {
774 			 HDMI_ERR("fail to enable hdmi ddc clk\n");
775 			 return -1;
776 		 }
777 	}
778 
779 	index++;
780 	/*get hdcp clk for hdmi hdcp2.2 function*/
781 	hdmi->hdcp_clk = of_clk_get(pdev->dev.of_node, index);
782 	if (IS_ERR_OR_NULL(hdmi->hdcp_clk)) {
783 		 HDMI_ERR("fail to get hdmi_cec_clk\n");
784 		 //return -1;
785 	}
786 
787 	if (hdmi->hdcp.use_hdcp
788 		&& __clk_get_enable_count(hdmi->hdcp_clk) == 0) {
789 		 ret = clk_prepare_enable(hdmi->hdcp_clk);
790 		 if (ret < 0) {
791 			 HDMI_ERR("fail to enable hdmi hdcp clk\n");
792 			 //return -1;
793 		 }
794 	}
795 
796 	index++;
797 	/*get cec clk for hdmi cec function*/
798 	hdmi->cec_clk = of_clk_get(pdev->dev.of_node, index);
799 	if (IS_ERR_OR_NULL(hdmi->cec_clk)) {
800 		 HDMI_ERR("fail to get hdmi_cec_clk\n");
801 		 //return -1;
802 	}
803 
804 	if (hdmi->cec.support
805 		&& __clk_get_enable_count(hdmi->cec_clk) == 0) {
806 		 ret = clk_prepare_enable(hdmi->cec_clk);
807 		 if (ret < 0) {
808 			 HDMI_ERR("fail to enable hdmi cec clk\n");
809 			 //return -1;
810 		 }
811 	}
812 
813 	return 0;
814 }
815 
sunxi_hdmi20_clk_exit(struct sunxi_hdmi * hdmi)816 static int sunxi_hdmi20_clk_exit(struct sunxi_hdmi *hdmi)
817 {
818 	return sunxi_hdmi20_clk_disable(hdmi);
819 }
820 
sunxi_hdmi20_pin_active(void)821 static int sunxi_hdmi20_pin_active(void)
822 {
823 	/*set hdmi pin like ddc pin to active state*/
824 	sunxi_drm_sys_pin_set_state("hdmi", DDC_PIN_STATE_ACTIVE);
825 	/*set hdmi pin like ddc pin to active state*/
826 	sunxi_drm_sys_pin_set_state("hdmi", CEC_PIN_STATE_ACTIVE);
827 
828 	return 0;
829 }
830 
sunxi_hdmi20_pin_sleep(void)831 int sunxi_hdmi20_pin_sleep(void)
832 {
833 	/*set hdmi pin like ddc pin to sleep state*/
834 	sunxi_drm_sys_pin_set_state("hdmi", DDC_PIN_STATE_SLEEP);
835 	/*set hdmi pin like ddc pin to sleep state*/
836 	sunxi_drm_sys_pin_set_state("hdmi", CEC_PIN_STATE_SLEEP);
837 
838 	return 0;
839 }
840 
hdmi_debug_show(struct device * dev,struct device_attribute * attr,char * buf)841 static ssize_t hdmi_debug_show(struct device *dev,
842 				struct device_attribute *attr,
843 				char *buf)
844 {
845 	ssize_t n = 0;
846 
847 	n += sprintf(buf + n, "Current debug=%d\n\n", hdmi_printf);
848 
849 	n += sprintf(buf + n, "hdmi log debug level:\n");
850 	n += sprintf(buf + n, "debug = 1, print video log\n");
851 	n += sprintf(buf + n, "debug = 2, print edid log\n");
852 	n += sprintf(buf + n, "debug = 3, print audio log\n");
853 	n += sprintf(buf + n, "debug = 4, print video+edid+audio log\n");
854 	n += sprintf(buf + n, "debug = 5, print cec log\n");
855 	n += sprintf(buf + n, "debug = 6, print hdcp log\n");
856 	n += sprintf(buf + n, "debug = 7, print all of the logs above\n");
857 	n += sprintf(buf + n, "debug = 8, print all of the logs above and trace log\n");
858 
859 	return n;
860 }
861 
hdmi_debug_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)862 static ssize_t hdmi_debug_store(struct device *dev,
863 				struct device_attribute *attr,
864 				const char *buf, size_t count)
865 {
866 	if (count < 1)
867 		return -EINVAL;
868 
869 	if (strncmp(buf, "9", 1) == 0)
870 		hdmi_printf = 9;
871 	else if (strncmp(buf, "8", 1) == 0)
872 		hdmi_printf = 8;
873 	else if (strncmp(buf, "7", 1) == 0)
874 		hdmi_printf = 7;
875 	else if (strncmp(buf, "6", 1) == 0)
876 		hdmi_printf = 6;
877 	else if (strncmp(buf, "5", 1) == 0)
878 			hdmi_printf = 5;
879 	else if (strncmp(buf, "4", 1) == 0)
880 		hdmi_printf = 4;
881 	else if (strncmp(buf, "3", 1) == 0)
882 		hdmi_printf = 3;
883 	else if (strncmp(buf, "2", 1) == 0)
884 		hdmi_printf = 2;
885 	else if (strncmp(buf, "1", 1) == 0)
886 		hdmi_printf = 1;
887 	else if (strncmp(buf, "0", 1) == 0)
888 		hdmi_printf = 0;
889 	else
890 		pr_err("Error Input!\n");
891 
892 	pr_info("debug=%d\n", hdmi_printf);
893 
894 	return count;
895 }
896 
897 static DEVICE_ATTR(debug, 0664, hdmi_debug_show, hdmi_debug_store);
898 
899 static unsigned int reg_read_start, reg_read_end, reg_read_cmd;
sunxi_hdmi20_read_show(struct device * dev,struct device_attribute * attr,char * buf)900 static ssize_t sunxi_hdmi20_read_show(struct device *dev,
901 		struct device_attribute *attr, char *buf)
902 {
903 	ssize_t n = 0;
904 	unsigned int reg;
905 
906 	if (!reg_read_cmd) {
907 		n += sprintf(buf + n, "read hdmi register, Usage:\n");
908 		n += sprintf(buf + n, "echo [reg_offset_start] [reg_offset_end] > read\n");
909 		n += sprintf(buf + n, "OR:echo [reg_offset_start],[reg_offset_end] > read\n");
910 		return n;
911 	}
912 
913 	for (reg = reg_read_start; reg <= reg_read_end; reg++) {
914 		if (reg % 16 == 0) {
915 			n += sprintf(buf + n, "\n");
916 			n += sprintf(buf + n, "0x%x: ", reg);
917 		}
918 
919 		n += sprintf(buf + n, "0x%02x ", hdmi20_read(reg << 2));
920 	}
921 
922 	n += sprintf(buf + n, "\n");
923 
924 	reg_read_cmd = 0;
925 
926 	return n;
927 }
928 
sunxi_hdmi20_read_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)929 static ssize_t sunxi_hdmi20_read_store(struct device *dev,
930 				struct device_attribute *attr,
931 				const char *buf, size_t count)
932 {
933 	char *end;
934 
935 	reg_read_start = (unsigned int)simple_strtoull(buf, &end, 0);
936 
937 	if ((*end != ' ') && (*end != ',')) {
938 		HDMI_ERR("error separator:%c\n", *end);
939 		return count;
940 	}
941 
942 	reg_read_end = (unsigned int)simple_strtoull(end + 1, &end, 0);
943 
944 	reg_read_cmd = 1;
945 
946 	return count;
947 }
948 
949 static DEVICE_ATTR(read, 0660,
950 		sunxi_hdmi20_read_show, sunxi_hdmi20_read_store);
951 
952 
sunxi_hdmi20_write_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)953 static ssize_t sunxi_hdmi20_write_store(struct device *dev,
954 				struct device_attribute *attr,
955 				const char *buf, size_t count)
956 {
957 	char *end;
958 	unsigned int reg_addr;
959 	unsigned char value;
960 
961 	reg_addr = (unsigned int)simple_strtoull(buf, &end, 0);
962 
963 	if ((*end != ' ') && (*end != ',')) {
964 		HDMI_ERR("error separator:%c\n", *end);
965 		return count;
966 	}
967 
968 	value = (unsigned char)simple_strtoull(end + 1, &end, 0);
969 
970 	hdmi20_write(reg_addr << 2, value);
971 
972 	return count;
973 }
974 
975 static DEVICE_ATTR(write, 0660, NULL, sunxi_hdmi20_write_store);
976 
sunxi_hdmi20_source_para_show(struct device * dev,struct device_attribute * attr,char * buf)977 static ssize_t sunxi_hdmi20_source_para_show(struct device *dev,
978 		struct device_attribute *attr, char *buf)
979 {
980 	ssize_t n = 0;
981 	/*struct sunxi_hdmi *hdmi = sunxi_hdmi20_get_hdmi();
982 	videoParams_t *video = &hdmi->video;
983 	audioParams_t *audio = &hdmi->audio;
984 	productParams_t *product = &hdmi->product;
985 	hdcpParams_t *hdcp = &hdmi->hdcp;
986 	struct cec_params *cec = &hdmi->cec;*/
987 
988 	return n;
989 }
990 
991 static DEVICE_ATTR(source_para, 0660,
992 		sunxi_hdmi20_source_para_show, NULL);
993 
994 
sunxi_hdmi20_hdcp_enable_show(struct device * dev,struct device_attribute * attr,char * buf)995 static ssize_t sunxi_hdmi20_hdcp_enable_show(struct device *dev,
996 		struct device_attribute *attr, char *buf)
997 {
998 	ssize_t n = 0;
999 	//struct sunxi_hdmi *hdmi = sunxi_hdmi20_get_hdmi();
1000 
1001 	//n += sprintf(buf + n, "%d", hdmi->video.is_hcts);
1002 
1003 	return n;
1004 }
1005 
sunxi_hdmi20_hdcp_enable_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)1006 static ssize_t sunxi_hdmi20_hdcp_enable_store(struct device *dev,
1007 				struct device_attribute *attr,
1008 				const char *buf, size_t count)
1009 {
1010 	//struct sunxi_hdmi *hdmi = sunxi_hdmi20_get_hdmi();
1011 
1012 	if (count < 1)
1013 		return -EINVAL;
1014 
1015 	if (strncasecmp(buf, "on", 2) == 0 || strncasecmp(buf, "1", 1) == 0)
1016 		;
1017 	else if (strncasecmp(buf, "off", 3) == 0 ||
1018 			strncasecmp(buf, "0", 1) == 0)
1019 		;
1020 	else
1021 		return -EINVAL;
1022 
1023 	return count;
1024 }
1025 
1026 static DEVICE_ATTR(hdcp_enable, 0660,
1027 		sunxi_hdmi20_hdcp_enable_show, sunxi_hdmi20_hdcp_enable_store);
1028 
1029 static struct attribute *hdmi20_attributes[] = {
1030 	&dev_attr_hdcp_enable.attr,
1031 	&dev_attr_source_para.attr,
1032 	&dev_attr_read.attr,
1033 	&dev_attr_write.attr,
1034 	&dev_attr_debug.attr,
1035 	NULL
1036 };
1037 
1038 
hdmi20_delay_us(int us)1039 static void hdmi20_delay_us(int us)
1040 {
1041 	 udelay(us);
1042 }
1043 
sunxi_hdmi20_core_init(struct sunxi_hdmi * hdmi)1044 static int sunxi_hdmi20_core_init(struct sunxi_hdmi *hdmi)
1045 {
1046 	low_functions.sleep = hdmi20_delay_us;
1047 	reg_access.read = hdmi20_read;
1048 	reg_access.write = hdmi20_write;
1049 
1050 	register_system_functions(&low_functions);
1051 	register_bsp_functions(&reg_access);
1052 
1053 	/*set initial video timing*/
1054 //	sunxi_hdmi20_get_video_mode_info(&hdmi->video_info,
1055 //				 DISP_TV_MOD_720P_50HZ);
1056 
1057 	hdmitx_api_init(&hdmi->hdmi_dev,
1058 		&hdmi->video, &hdmi->audio, &hdmi->hdcp);
1059 
1060 	hdmi->dev_funcs.hpd_enable(1);
1061 
1062 	hdmi->video.pb = kzalloc(sizeof(fc_drm_pb_t), GFP_KERNEL);
1063 	if (!hdmi->video.pb) {
1064 		HDMI_ERR("kzalloc for fc_drm_pb_t failed\n");
1065 		return -1;
1066 	}
1067 
1068 	hdmi->funcs = &hdmi20_funcs;
1069 	return 0;
1070 }
1071 
sunxi_hdmi20_probe(struct platform_device * pdev)1072 static int sunxi_hdmi20_probe(struct platform_device *pdev)
1073 {
1074 	int ret = -1;
1075 	struct sunxi_hdmi *hdmi = NULL;
1076 
1077 	hdmi = kmalloc(sizeof(struct sunxi_hdmi), GFP_KERNEL | __GFP_ZERO);
1078 	if (!hdmi) {
1079 		HDMI_ERR("Malloc sunxi_hdmi fail!\n");
1080 		goto OUT;
1081 	}
1082 
1083 	hwhdmi20 = hdmi;
1084 
1085 	hdmi->pdev = pdev;
1086 
1087 	/* iomap */
1088 	hdmi->reg_base = of_iomap(pdev->dev.of_node, 0);
1089 	if (hdmi->reg_base == 0) {
1090 		HDMI_ERR("unable to map hdmi registers\n");
1091 		ret = -EINVAL;
1092 		goto FREE_HDMI;
1093 	}
1094 
1095 	ret = sunxi_hdmi20_video_dts_parse(pdev, hdmi);
1096 	if (ret < 0) {
1097 		HDMI_ERR("parse video dts failed\n");
1098 		ret = -EINVAL;
1099 		goto FREE_HDMI;
1100 	}
1101 
1102 	ret = sunxi_hdmi20_hdcp_dts_parse(pdev, hdmi);
1103 	if (ret < 0) {
1104 		HDMI_ERR("parse hdcp dts failed\n");
1105 		ret = -EINVAL;
1106 		goto FREE_HDMI;
1107 	}
1108 
1109 	ret = sunxi_hdmi20_cec_dts_parse(pdev, hdmi);
1110 	if (ret < 0) {
1111 		HDMI_ERR("parse cec dts failed\n");
1112 		ret = -EINVAL;
1113 		goto FREE_HDMI;
1114 	}
1115 
1116 	sunxi_hdmi20_power_init(pdev, hdmi);
1117 
1118 	ret = sunxi_hdmi20_clk_init(pdev, hdmi);
1119 	if (ret < 0) {
1120 		HDMI_ERR("sunxi_hdmi_clk_init failed\n");
1121 		goto err_iomap;
1122 	}
1123 
1124 	sunxi_hdmi20_pin_active();
1125 
1126 	sunxi_hdmi20_hdcp_init();
1127 	sunxi_hdmi20_audio_init();
1128 
1129 	ret = sunxi_hdmi20_core_init(hdmi);
1130 	if (ret < 0) {
1131 		HDMI_ERR("sunxi_hdmi20_core_init failed\n");
1132 		goto err_iomap;
1133 	}
1134 
1135 	return 0;
1136 
1137 err_iomap:
1138 	if (hdmi->reg_base)
1139 		iounmap((char __iomem *)hdmi->reg_base);
1140 FREE_HDMI:
1141 	kfree(hdmi);
1142 OUT:
1143 	return ret;
1144 }
1145 
sunxi_hdmi20_remove(struct platform_device * pdev)1146 static int sunxi_hdmi20_remove(struct platform_device *pdev)
1147 {
1148 	 int i;
1149 	 struct sunxi_hdmi *hdmi = hwhdmi20;
1150 
1151 	 if (!hdmi) {
1152 		 HDMI_ERR("Null pointer!\n");
1153 		 return -1;
1154 	 }
1155 
1156 	 sunxi_hdmi20_clk_exit(hdmi);
1157 	 for (i = 0; i < hdmi->power_count; i++)
1158 		 sunxi_drm_sys_power_disable(NULL, hdmi->power[i]); /* fix me */
1159 	 iounmap((char __iomem *)hdmi->reg_base);
1160 	 kfree(hdmi);
1161 	 return 0;
1162 }
1163 
1164 static const struct of_device_id sunxi_hdmi20_match[] = {
1165 	 { .compatible = "allwinner,sunxi-hdmi", },
1166 
1167 	 {},
1168 };
1169 
1170 struct platform_driver sunxi_hdmi20_platform_driver = {
1171 	 .probe = sunxi_hdmi20_probe,
1172 	 .remove = sunxi_hdmi20_remove,
1173 	 .driver = {
1174 			.name = "hdmi",
1175 			.owner = THIS_MODULE,
1176 			.of_match_table = sunxi_hdmi20_match,
1177 	 },
1178 };
1179 
1180 static struct attribute_group hdmi20_attribute_group = {
1181 	 .name = "attr",
1182 	 .attrs = hdmi20_attributes,
1183 };
1184 
sunxi_hdmi20_module_init(void)1185 int __init sunxi_hdmi20_module_init(void)
1186 {
1187 	int ret = -1;
1188 
1189 	HDMI_INFO(" start\n");
1190 	hdmi20_drv = kmalloc(sizeof(struct drv_model_info),
1191 				 GFP_KERNEL | __GFP_ZERO);
1192 	if (!hdmi20_drv) {
1193 		 HDMI_ERR("Null drv_model_info pointer\n");
1194 		 goto OUT;
1195 	}
1196 	ret = alloc_chrdev_region(&hdmi20_drv->devid, 0, 1, "hdmi");
1197 	if (ret < 0) {
1198 		 HDMI_ERR("alloc_chrdev_region failed\n");
1199 		 goto FREE_DRV;
1200 	}
1201 
1202 	hdmi20_drv->cdev = cdev_alloc();
1203 	if (!hdmi20_drv->cdev) {
1204 		 HDMI_ERR("cdev_alloc failed\n");
1205 		 goto FREE_DRV;
1206 	}
1207 
1208 	cdev_init(hdmi20_drv->cdev, NULL);
1209 	hdmi20_drv->cdev->owner = THIS_MODULE;
1210 	ret = cdev_add(hdmi20_drv->cdev, hdmi20_drv->devid, 1);
1211 	if (ret) {
1212 		 HDMI_ERR("cdev_add major number:%d failed\n",
1213 				MAJOR(hdmi20_drv->devid));
1214 		 goto FREE_DRV;
1215 	}
1216 
1217 	hdmi20_drv->sysclass = class_create(THIS_MODULE, "hdmi");
1218 	if (IS_ERR(hdmi20_drv->sysclass)) {
1219 		HDMI_ERR("create class error\n");
1220 		goto FREE_DRV;
1221 	}
1222 
1223 	hdmi20_drv->dev = device_create(hdmi20_drv->sysclass, NULL,
1224 			 hdmi20_drv->devid, NULL, "hdmi");
1225 	if (!hdmi20_drv->dev) {
1226 		 HDMI_ERR("device_create failed\n");
1227 		 goto FREE_DRV;
1228 	}
1229 
1230 	ret = platform_driver_register(&sunxi_hdmi20_platform_driver);
1231 	if (ret) {
1232 		 HDMI_ERR("platform_driver_register failed\n");
1233 		 goto FREE_DEVICE;
1234 	}
1235 
1236 	ret = sysfs_create_group(&hdmi20_drv->dev->kobj, &hdmi20_attribute_group);
1237 	if (ret < 0) {
1238 		 HDMI_ERR("sysfs_create_file fail!\n");
1239 		 goto UNREGISTER;
1240 	}
1241 
1242 	HDMI_INFO(" end\n");
1243 	return ret;
1244 
1245 UNREGISTER:
1246 	 platform_driver_unregister(&sunxi_hdmi20_platform_driver);
1247 FREE_DEVICE:
1248 	 device_destroy(hdmi20_drv->sysclass, hdmi20_drv->devid);
1249 FREE_DRV:
1250 	 kfree(hdmi20_drv);
1251 OUT:
1252 	 HDMI_ERR(" failed\n");
1253 	 return -EINVAL;
1254 }
1255 
sunxi_hdmi20_module_exit(void)1256 void __exit sunxi_hdmi20_module_exit(void)
1257 {
1258 	 HDMI_INFO("\n");
1259 	 if (hdmi20_drv) {
1260 		 platform_driver_unregister(&sunxi_hdmi20_platform_driver);
1261 
1262 		 device_destroy(hdmi20_drv->sysclass, hdmi20_drv->devid);
1263 		 class_destroy(hdmi20_drv->sysclass);
1264 
1265 		 cdev_del(hdmi20_drv->cdev);
1266 		 kfree(hdmi20_drv);
1267 	 }
1268 }
1269 
1270