• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * drivers/gpu/drm/sunxi/sunxi_device/sunxi_tv/sunxi_tv.c
3  *
4  * Copyright (c) 2007-2019 Allwinnertech Co., Ltd.
5  * Author: zhengxiaobin <zhengxiaobin@allwinnertech.com>
6  * Author: zhengwanyu <zhengwanyu@allwinnertech.com>
7  *
8  * sunxi tvout driver include cvbs out, YPbPr and VGA out
9  *
10  * This software is licensed under the terms of the GNU General Public
11  * License version 2, as published by the Free Software Foundation, and
12  * may be copied, distributed, and modified under those terms.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  */
20 
21 #include <linux/dma-mapping.h>
22 #include <drm/drmP.h>
23 #include <linux/clk.h>
24 #include "sunxi_common.h"
25 #include "sunxi_tcon.h"
26 #include "sunxi_tv.h"
27 
28 static struct drv_model_info *p_tv_drv;
29 static struct sunxi_tv *hwtv[MAX_TV_COUNT];
30 static unsigned int tv_count;
31 
32 /*video timing definition start*/
33 static struct disp_video_timings cvbs_timing[] = {
34 	{
35 		.vic = 0,
36 		.tv_mode = DISP_TV_MOD_NTSC,
37 		.pixel_clk = 216000000,
38 		.pixel_repeat = 0,
39 		.x_res = 720,
40 		.y_res = 480,
41 		.hor_total_time = 858,
42 		.hor_back_porch = 60,
43 		.hor_front_porch = 16,
44 		.hor_sync_time = 62,
45 		.ver_total_time = 525,
46 		.ver_back_porch = 30,
47 		.ver_front_porch = 9,
48 		.ver_sync_time = 6,
49 		.hor_sync_polarity = 0,/* 0: negative, 1: positive */
50 		.ver_sync_polarity = 0,/* 0: negative, 1: positive */
51 		.b_interlace = 0,
52 		.vactive_space = 0,
53 		.trd_mode = 0,
54 
55 	},
56 	{
57 		.vic = 0,
58 		.tv_mode = DISP_TV_MOD_PAL,
59 		.pixel_clk = 216000000,
60 		.pixel_repeat = 0,
61 		.x_res = 720,
62 		.y_res = 576,
63 		.hor_total_time = 864,
64 		.hor_back_porch = 68,
65 		.hor_front_porch = 12,
66 		.hor_sync_time = 64,
67 		.ver_total_time = 625,
68 		.ver_back_porch = 39,
69 		.ver_front_porch = 5,
70 		.ver_sync_time = 5,
71 		.hor_sync_polarity = 0,/* 0: negative, 1: positive */
72 		.ver_sync_polarity = 0,/* 0: negative, 1: positive */
73 		.b_interlace = 0,
74 		.vactive_space = 0,
75 		.trd_mode = 0,
76 	},
77 };
78 
79 static struct disp_video_timings vga_timing[] = {
80 	{
81 		.vic = 0,
82 		.tv_mode = DISP_VGA_MOD_1600_900P_60,
83 		.pixel_clk = 108000000,
84 		.pixel_repeat = 0,
85 		.x_res = 1600,
86 		.y_res = 900,
87 		.hor_total_time = 1800,
88 		.hor_back_porch = 96,
89 		.hor_front_porch = 24,
90 		.hor_sync_time = 80,
91 		.ver_total_time = 1000,
92 		.ver_back_porch = 96,
93 		.ver_front_porch = 1,
94 		.ver_sync_time = 3,
95 		.hor_sync_polarity = 1,/* 0: negative, 1: positive */
96 		.ver_sync_polarity = 1,/* 0: negative, 1: positive */
97 		.b_interlace = 0,
98 		.vactive_space = 0,
99 		.trd_mode = 0,
100 	},
101 	{
102 		.vic = 0,
103 		.tv_mode = DISP_VGA_MOD_1440_900P_60,
104 		.pixel_clk = 89000000,
105 		.pixel_repeat = 0,
106 		.x_res = 1440,
107 		.y_res = 900,
108 		.hor_total_time = 1600,
109 		.hor_back_porch = 80,
110 		.hor_front_porch = 48,
111 		.hor_sync_time = 32,
112 		.ver_total_time = 926,
113 		.ver_back_porch = 17,
114 		.ver_front_porch = 3,
115 		.ver_sync_time = 6,
116 		.hor_sync_polarity = 1,/* 0: negative, 1: positive */
117 		.ver_sync_polarity = 0,/* 0: negative, 1: positive */
118 		.b_interlace = 0,
119 		.vactive_space = 0,
120 		.trd_mode = 0,
121 	},
122 	{
123 		.vic = 0,
124 		.tv_mode = DISP_VGA_MOD_1366_768P_60,
125 		.pixel_clk = 85800000,
126 		.pixel_repeat = 0,
127 		.x_res = 1366,
128 		.y_res = 768,
129 		.hor_total_time = 1792,
130 		.hor_back_porch = 213,
131 		.hor_front_porch = 70,
132 		.hor_sync_time = 143,
133 		.ver_total_time = 798,
134 		.ver_back_porch = 24,
135 		.ver_front_porch = 3,
136 		.ver_sync_time = 3,
137 		.hor_sync_polarity = 1,/* 0: negative, 1: positive */
138 		.ver_sync_polarity = 1,/* 0: negative, 1: positive */
139 		.b_interlace = 0,
140 		.vactive_space = 0,
141 		.trd_mode = 0,
142 	},
143 	{
144 		.vic = 0,
145 		.tv_mode = DISP_VGA_MOD_1280_800P_60,
146 		.pixel_clk = 83500000,
147 		.pixel_repeat = 0,
148 		.x_res = 1280,
149 		.y_res = 800,
150 		.hor_total_time = 1680,
151 		.hor_back_porch = 200,
152 		.hor_front_porch = 72,
153 		.hor_sync_time = 128,
154 		.ver_total_time = 831,
155 		.ver_back_porch = 22,
156 		.ver_front_porch = 3,
157 		.ver_sync_time = 6,
158 		.hor_sync_polarity = 0,/* 0: negative, 1: positive */
159 		.ver_sync_polarity = 1,/* 0: negative, 1: positive */
160 		.b_interlace = 0,
161 		.vactive_space = 0,
162 		.trd_mode = 0,
163 	},
164 	{
165 		.vic = 0,
166 		.tv_mode = DISP_VGA_MOD_1024_768P_60,
167 		.pixel_clk = 65000000,
168 		.pixel_repeat = 0,
169 		.x_res = 1024,
170 		.y_res = 768,
171 		.hor_total_time = 1344,
172 		.hor_back_porch = 160,
173 		.hor_front_porch = 24,
174 		.hor_sync_time = 136,
175 		.ver_total_time = 806,
176 		.ver_back_porch = 29,
177 		.ver_front_porch = 3,
178 		.ver_sync_time = 6,
179 		.hor_sync_polarity = 0,/* 0: negative, 1: positive */
180 		.ver_sync_polarity = 0,/* 0: negative, 1: positive */
181 		.b_interlace = 0,
182 		.vactive_space = 0,
183 		.trd_mode = 0,
184 	},
185 	{
186 		.vic = 0,
187 		.tv_mode = DISP_VGA_MOD_800_600P_60,
188 		.pixel_clk = 40000000,
189 		.pixel_repeat = 0,
190 		.x_res = 800,
191 		.y_res = 600,
192 		.hor_total_time = 1056,
193 		.hor_back_porch = 88,
194 		.hor_front_porch = 40,
195 		.hor_sync_time = 128,
196 		.ver_total_time = 628,
197 		.ver_back_porch = 23,
198 		.ver_front_porch = 1,
199 		.ver_sync_time = 4,
200 		.hor_sync_polarity = 1,/* 0: negative, 1: positive */
201 		.ver_sync_polarity = 1,/* 0: negative, 1: positive */
202 		.b_interlace = 0,
203 		.vactive_space = 0,
204 		.trd_mode = 0,
205 	},
206 	{
207 		.vic = 0,
208 		.tv_mode = DISP_VGA_MOD_1280_720P_60,
209 		.pixel_clk = 74250000,
210 		.pixel_repeat = 0,
211 		.x_res = 1280,
212 		.y_res = 720,
213 		.hor_total_time = 1650,
214 		.hor_back_porch = 220,
215 		.hor_front_porch = 110,
216 		.hor_sync_time = 40,
217 		.ver_total_time = 750,
218 		.ver_back_porch = 20,
219 		.ver_front_porch = 5,
220 		.ver_sync_time = 5,
221 		.hor_sync_polarity = 1,/* 0: negative, 1: positive */
222 		.ver_sync_polarity = 1,/* 0: negative, 1: positive */
223 		.b_interlace = 0,
224 		.vactive_space = 0,
225 		.trd_mode = 0,
226 	},
227 	{
228 		.vic = 0,
229 		.tv_mode = DISP_VGA_MOD_1920_1080P_60,
230 		.pixel_clk = 148500000,
231 		.pixel_repeat = 0,
232 		.x_res = 1920,
233 		.y_res = 1080,
234 		.hor_total_time = 2200,
235 		.hor_back_porch = 148,
236 		.hor_front_porch = 88,
237 		.hor_sync_time = 44,
238 		.ver_total_time = 1125,
239 		.ver_back_porch = 36,
240 		.ver_front_porch = 4,
241 		.ver_sync_time = 5,
242 		.hor_sync_polarity = 1,/* 0: negative, 1: positive */
243 		.ver_sync_polarity = 1,/* 0: negative, 1: positive */
244 		.b_interlace = 0,
245 		.vactive_space = 0,
246 		.trd_mode = 0,
247 	},
248 };
249 
250 static struct disp_video_timings ypbpr_timing[] = {
251 	{
252 		.vic = 0,
253 		.tv_mode = DISP_TV_MOD_NTSC,
254 		.pixel_clk = 216000000,
255 		.pixel_repeat = 0,
256 		.x_res = 720,
257 		.y_res = 480,
258 		.hor_total_time = 858,
259 		.hor_back_porch = 60,
260 		.hor_front_porch = 16,
261 		.hor_sync_time = 62,
262 		.ver_total_time = 525,
263 		.ver_back_porch = 30,
264 		.ver_front_porch = 9,
265 		.ver_sync_time = 6,
266 		.hor_sync_polarity = 0,/* 0: negative, 1: positive */
267 		.ver_sync_polarity = 0,/* 0: negative, 1: positive */
268 		.b_interlace = 0,
269 		.vactive_space = 0,
270 		.trd_mode = 0,
271 
272 	},
273 	{
274 		.vic = 0,
275 		.tv_mode = DISP_TV_MOD_PAL,
276 		.pixel_clk = 216000000,
277 		.pixel_repeat = 0,
278 		.x_res = 720,
279 		.y_res = 576,
280 		.hor_total_time = 864,
281 		.hor_back_porch = 68,
282 		.hor_front_porch = 12,
283 		.hor_sync_time = 64,
284 		.ver_total_time = 625,
285 		.ver_back_porch = 39,
286 		.ver_front_porch = 5,
287 		.ver_sync_time = 5,
288 		.hor_sync_polarity = 0,/* 0: negative, 1: positive */
289 		.ver_sync_polarity = 0,/* 0: negative, 1: positive */
290 		.b_interlace = 0,
291 		.vactive_space = 0,
292 		.trd_mode = 0,
293 	},
294 	{
295 		.vic = 0,
296 		.tv_mode = DISP_TV_MOD_480I,
297 		.pixel_clk = 216000000,
298 		.pixel_repeat = 0,
299 		.x_res = 720,
300 		.y_res = 480,
301 		.hor_total_time = 858,
302 		.hor_back_porch = 57,
303 		.hor_front_porch = 62,
304 		.hor_sync_time = 19,
305 		.ver_total_time = 525,
306 		.ver_back_porch = 4,
307 		.ver_front_porch = 1,
308 		.ver_sync_time = 3,
309 		.hor_sync_polarity = 0,/* 0: negative, 1: positive */
310 		.ver_sync_polarity = 0,/* 0: negative, 1: positive */
311 		.b_interlace = 1,
312 		.vactive_space = 0,
313 		.trd_mode = 0,
314 	},
315 	{
316 		.vic = 0,
317 		.tv_mode = DISP_TV_MOD_576I,
318 		.pixel_clk = 216000000,
319 		.pixel_repeat = 0,
320 		.x_res = 720,
321 		.y_res = 576,
322 		.hor_total_time = 864,
323 		.hor_back_porch = 69,
324 		.hor_front_porch = 63,
325 		.hor_sync_time = 12,
326 		.ver_total_time = 625,
327 		.ver_back_porch = 2,
328 		.ver_front_porch = 44,
329 		.ver_sync_time = 3,
330 		.hor_sync_polarity = 0,/* 0: negative, 1: positive */
331 		.ver_sync_polarity = 0,/* 0: negative, 1: positive */
332 		.b_interlace = 1,
333 		.vactive_space = 0,
334 		.trd_mode = 0,
335 	},
336 	{
337 		.vic = 0,
338 		.tv_mode = DISP_TV_MOD_480P,
339 		.pixel_clk = 54000000,
340 		.pixel_repeat = 0,
341 		.x_res = 720,
342 		.y_res = 480,
343 		.hor_total_time = 858,
344 		.hor_back_porch = 60,
345 		.hor_front_porch = 62,
346 		.hor_sync_time = 16,
347 		.ver_total_time = 525,
348 		.ver_back_porch = 9,
349 		.ver_front_porch = 30,
350 		.ver_sync_time = 6,
351 		.hor_sync_polarity = 1,/* 0: negative, 1: positive */
352 		.ver_sync_polarity = 1,/* 0: negative, 1: positive */
353 		.b_interlace = 0,
354 		.vactive_space = 0,
355 		.trd_mode = 0,
356 	},
357 	{
358 		.vic = 0,
359 		.tv_mode = DISP_TV_MOD_576P,
360 		.pixel_clk = 54000000,
361 		.pixel_repeat = 0,
362 		.x_res = 720,
363 		.y_res = 576,
364 		.hor_total_time = 864,
365 		.hor_back_porch = 68,
366 		.hor_front_porch = 64,
367 		.hor_sync_time = 12,
368 		.ver_total_time = 625,
369 		.ver_back_porch = 5,
370 		.ver_front_porch = 39,
371 		.ver_sync_time = 5,
372 		.hor_sync_polarity = 1,/* 0: negative, 1: positive */
373 		.ver_sync_polarity = 1,/* 0: negative, 1: positive */
374 		.b_interlace = 0,
375 		.vactive_space = 0,
376 		.trd_mode = 0,
377 	},
378 	{
379 		.vic = 0,
380 		.tv_mode = DISP_TV_MOD_720P_60HZ,
381 		.pixel_clk = 74250000,
382 		.pixel_repeat = 0,
383 		.x_res = 1280,
384 		.y_res = 720,
385 		.hor_total_time = 1650,
386 		.hor_back_porch = 220,
387 		.hor_front_porch = 40,
388 		.hor_sync_time = 110,
389 		.ver_total_time = 750,
390 		.ver_back_porch = 5,
391 		.ver_front_porch = 20,
392 		.ver_sync_time = 5,
393 		.hor_sync_polarity = 1,/* 0: negative, 1: positive */
394 		.ver_sync_polarity = 1,/* 0: negative, 1: positive */
395 		.b_interlace = 0,
396 		.vactive_space = 0,
397 		.trd_mode = 0,
398 	},
399 	{
400 		.vic = 0,
401 		.tv_mode = DISP_TV_MOD_720P_50HZ,
402 		.pixel_clk = 74250000,
403 		.pixel_repeat = 0,
404 		.x_res = 1280,
405 		.y_res = 720,
406 		.hor_total_time = 1980,
407 		.hor_back_porch = 220,
408 		.hor_front_porch = 40,
409 		.hor_sync_time = 440,
410 		.ver_total_time = 750,
411 		.ver_back_porch = 5,
412 		.ver_front_porch = 20,
413 		.ver_sync_time = 5,
414 		.hor_sync_polarity = 1,/* 0: negative, 1: positive */
415 		.ver_sync_polarity = 1,/* 0: negative, 1: positive */
416 		.b_interlace = 0,
417 		.vactive_space = 0,
418 		.trd_mode = 0,
419 	},
420 	{
421 		.vic = 0,
422 		.tv_mode = DISP_TV_MOD_1080I_60HZ,
423 		.pixel_clk = 74250000,
424 		.pixel_repeat = 0,
425 		.x_res = 1920,
426 		.y_res = 1080,
427 		.hor_total_time = 2200,
428 		.hor_back_porch = 148,
429 		.hor_front_porch = 44,
430 		.hor_sync_time = 88,
431 		.ver_total_time = 1125,
432 		.ver_back_porch = 2,
433 		.ver_front_porch = 38,
434 		.ver_sync_time = 5,
435 		.hor_sync_polarity = 1,/* 0: negative, 1: positive */
436 		.ver_sync_polarity = 1,/* 0: negative, 1: positive */
437 		.b_interlace = 1,
438 		.vactive_space = 0,
439 		.trd_mode = 0,
440 	},
441 	{
442 		.vic = 0,
443 		.tv_mode = DISP_TV_MOD_1080I_50HZ,
444 		.pixel_clk = 74250000,
445 		.pixel_repeat = 0,
446 		.x_res = 1920,
447 		.y_res = 1080,
448 		.hor_total_time = 2640,
449 		.hor_back_porch = 148,
450 		.hor_front_porch = 44,
451 		.hor_sync_time = 528,
452 		.ver_total_time = 1125,
453 		.ver_back_porch = 2,
454 		.ver_front_porch = 38,
455 		.ver_sync_time = 5,
456 		.hor_sync_polarity = 1,/* 0: negative, 1: positive */
457 		.ver_sync_polarity = 1,/* 0: negative, 1: positive */
458 		.b_interlace = 1,
459 		.vactive_space = 0,
460 		.trd_mode = 0,
461 	},
462 	{
463 		.vic = 0,
464 		.tv_mode = DISP_TV_MOD_1080P_60HZ,
465 		.pixel_clk = 148500000,
466 		.pixel_repeat = 0,
467 		.x_res = 1920,
468 		.y_res = 1080,
469 		.hor_total_time = 2200,
470 		.hor_back_porch = 148,
471 		.hor_front_porch = 44,
472 		.hor_sync_time = 88,
473 		.ver_total_time = 1125,
474 		.ver_back_porch = 4,
475 		.ver_front_porch = 36,
476 		.ver_sync_time = 5,
477 		.hor_sync_polarity = 1,/* 0: negative, 1: positive */
478 		.ver_sync_polarity = 1,/* 0: negative, 1: positive */
479 		.b_interlace = 0,
480 		.vactive_space = 0,
481 		.trd_mode = 0,
482 	},
483 	{
484 		.vic = 0,
485 		.tv_mode = DISP_TV_MOD_1080P_50HZ,
486 		.pixel_clk = 148500000,
487 		.pixel_repeat = 0,
488 		.x_res = 1920,
489 		.y_res = 1080,
490 		.hor_total_time = 2640,
491 		.hor_back_porch = 148,
492 		.hor_front_porch = 44,
493 		.hor_sync_time = 528,
494 		.ver_total_time = 1125,
495 		.ver_back_porch = 4,
496 		.ver_front_porch = 36,
497 		.ver_sync_time = 5,
498 		.hor_sync_polarity = 1,/* 0: negative, 1: positive */
499 		.ver_sync_polarity = 1,/* 0: negative, 1: positive */
500 		.b_interlace = 0,
501 		.vactive_space = 0,
502 		.trd_mode = 0,
503 	},
504 };
505 /*video timing definition end*/
506 
sunxi_tv_get_tv(int tv_id)507 static struct sunxi_tv *sunxi_tv_get_tv(int tv_id)
508 {
509 	if (tv_id > MAX_TV_COUNT) {
510 		TV_ERR("tv_id:%d is too big!\n", tv_id);
511 		return NULL;
512 	}
513 
514 	return hwtv[tv_id];
515 }
516 
517 /**
518  * @name       :sunxi_tv_get_tv_count
519  * @brief      :get the number of sunxi
520  * @return     :the number of sunxi tv
521  */
sunxi_tv_get_tv_count(void)522 int sunxi_tv_get_tv_count(void)
523 {
524 	return tv_count;
525 }
526 
__pin_config(int sel,char * name)527 static int __pin_config(int sel, char *name)
528 {
529 	int ret = 0;
530 	char type_name[10] = {0};
531 	struct device_node *node;
532 	struct platform_device *pdev;
533 	struct pinctrl *pctl;
534 	struct pinctrl_state *state;
535 
536 	snprintf(type_name, sizeof(type_name), "tv%d", sel);
537 
538 	node = of_find_compatible_node(NULL, type_name, "allwinner,sunxi-tv");
539 	if (!node) {
540 		TV_ERR("of_find_tv_node %s fail\n", type_name);
541 		ret = -EINVAL;
542 		goto exit;
543 	}
544 
545 	pdev = of_find_device_by_node(node);
546 	if (!node) {
547 		TV_ERR("of_find_device_by_node for %s fail\n", type_name);
548 		ret = -EINVAL;
549 		goto exit;
550 	}
551 
552 	pctl = pinctrl_get(&pdev->dev);
553 	if (IS_ERR(pctl)) {
554 		TV_ERR("pinctrl_get for %s fail\n", type_name);
555 		ret = PTR_ERR(pctl);
556 		goto exit;
557 	}
558 
559 	state = pinctrl_lookup_state(pctl, name);
560 	if (IS_ERR(state)) {
561 		TV_ERR("pinctrl_lookup_state for %s fail\n", type_name);
562 		ret = PTR_ERR(state);
563 		goto exit;
564 	}
565 
566 	ret = pinctrl_select_state(pctl, state);
567 	if (ret < 0) {
568 		TV_ERR("pinctrl_select_state(%s)fail\n", type_name);
569 		goto exit;
570 	}
571 
572 exit:
573 	return ret;
574 }
575 
tv_get_timing_list_num(struct sunxi_tv * p_tv)576 s32 tv_get_timing_list_num(struct sunxi_tv *p_tv)
577 {
578 	if (!p_tv) {
579 		TV_ERR("Null pointer!\n");
580 		return 0;
581 	}
582 	if (p_tv->tv_type == DISP_TV_CVBS) {
583 		return sizeof(cvbs_timing) / sizeof(struct disp_video_timings);
584 	} else if (p_tv->tv_type == DISP_VGA) {
585 		return sizeof(vga_timing) / sizeof(struct disp_video_timings);
586 	} else {
587 		return sizeof(ypbpr_timing) / sizeof(struct disp_video_timings);
588 	}
589 }
590 
tve_clk_enable(struct sunxi_tv * p_tv)591 static int tve_clk_enable(struct sunxi_tv *p_tv)
592 {
593 	int ret = -1;
594 
595 	if (!p_tv) {
596 		TV_ERR("Null pointer!\n");
597 		goto OUT;
598 	}
599 
600 	ret = clk_prepare_enable(p_tv->mclk);
601 	if (ret != 0) {
602 		TV_ERR("fail to enable tve%d's clk!\n", p_tv->id);
603 		return ret;
604 	}
605 
606 OUT:
607 	return ret;
608 }
609 
610 /*static int tve_clk_disable(struct sunxi_tv *p_tv)
611 {
612 	if (!p_tv) {
613 		TV_ERR("Null pointer!\n");
614 		return -1;
615 	}
616 	clk_disable(p_tv->mclk);
617 	return 0;
618 }*/
619 
tve_get_pixclk(struct sunxi_tv * p_tv,unsigned long * p_rate)620 static s32 tve_get_pixclk(struct sunxi_tv *p_tv, unsigned long *p_rate)
621 {
622 	int i = 0, list_num = 0, ret = -1;
623 	bool find = false;
624 	struct disp_video_timings *info = NULL;
625 
626 	if (!p_rate || !p_tv)
627 		goto OUT;
628 
629 	list_num = tv_get_timing_list_num(p_tv);
630 	info = p_tv->video_info;
631 	if (!info) {
632 		TV_ERR("Null pointer!\n");
633 		goto OUT;
634 	}
635 
636 	for (i = 0; i < list_num; i++) {
637 		if (info->tv_mode == p_tv->tv_mode) {
638 			find = true;
639 			break;
640 		}
641 		info++;
642 	}
643 	if (!find) {
644 		TV_ERR("tv have no mode(%d)!\n", p_tv->tv_mode);
645 		goto OUT;
646 	} else {
647 		*p_rate = info->pixel_clk;
648 		ret = 0;
649 	}
650 OUT:
651 	return ret;
652 }
653 
tve_clk_config(struct sunxi_tv * p_tv)654 static void tve_clk_config(struct sunxi_tv *p_tv)
655 {
656 	int ret = 0;
657 	unsigned long rate = 0, prate = 0;
658 	unsigned long round = 0, parent_round_rate = 0;
659 	signed long rate_diff = 0, prate_diff = 0, accuracy = 1000000;
660 	unsigned int div = 1;
661 
662 	if (!p_tv) {
663 		TV_ERR("Null pointer!\n");
664 		return;
665 	}
666 
667 	ret = tve_get_pixclk(p_tv, &rate);
668 	if (ret)
669 		TV_ERR("%s:tve_get_pixclk fail!\n", __func__);
670 
671 	round = clk_round_rate(p_tv->mclk, rate);
672 	rate_diff = (long)(round - rate);
673 	if ((rate_diff > accuracy) || (rate_diff < -accuracy)) {
674 		for (accuracy = 1000000; accuracy <= 5000000;
675 		     accuracy += 1000000) {
676 			for (div = 1; (rate * div) <= 984000000; div++) {
677 				prate = rate * div;
678 				parent_round_rate =
679 				    clk_round_rate(p_tv->mclk_parent, prate);
680 				prate_diff = (long)(parent_round_rate - prate);
681 				if ((prate_diff < accuracy) &&
682 				    (prate_diff > -accuracy)) {
683 					ret = clk_set_rate(p_tv->mclk_parent,
684 							   prate);
685 					ret += clk_set_rate(
686 					    p_tv->mclk, rate);
687 					if (ret)
688 						TV_ERR("fail to set rate(%ld) "
689 							"fo tve%d's clock!\n",
690 							rate, p_tv->id);
691 					else
692 						break;
693 				}
694 			}
695 			if (rate * div > 984000000) {
696 				TV_ERR("fail to set tve clk at %ld accuracy\n",
697 					accuracy);
698 				continue;
699 			}
700 			break;
701 		}
702 	} else {
703 		prate = clk_get_rate(p_tv->mclk_parent);
704 		ret = clk_set_rate(p_tv->mclk, rate);
705 		if (ret)
706 			TV_ERR("fail to set rate(%ld) fo tve%d's clock!\n",
707 				rate, p_tv->id);
708 	}
709 
710 	TV_DBG("parent prate=%lu(%lu), rate=%lu(%lu), tv_mode=%d\n",
711 		clk_get_rate(p_tv->mclk_parent), prate,
712 		clk_get_rate(p_tv->mclk), rate, p_tv->tv_mode);
713 }
714 
715 /*static enum disp_tv_mode sunxi_tv_get_mode(int tv_id)
716 {
717 	struct sunxi_tv *p_tv = sunxi_tv_get_tv(tv_id);
718 
719 	if (!p_tv) {
720 		TV_ERR("Null pointer!\n");
721 		return DISP_TV_MODE_NUM;
722 	}
723 
724 	return p_tv->tv_mode;
725 }*/
726 
sunxi_tv_get_video_timing(int tv_id,unsigned int tv_mode)727 struct disp_video_timings *sunxi_tv_get_video_timing(
728 			int tv_id, unsigned int tv_mode)
729 {
730 	int i, num;
731 	struct disp_video_timings *timing;
732 	struct sunxi_tv *p_tv = sunxi_tv_get_tv(tv_id);
733 
734 	if (!p_tv) {
735 		TV_ERR("Null pointer!\n");
736 		return NULL;
737 	}
738 
739 	num = tv_get_timing_list_num(p_tv);
740 	timing = p_tv->video_info;
741 
742 	for (i = 0; i < num; i++)
743 		if (timing[i].tv_mode == tv_mode)
744 			break;
745 
746 	if (i >= num) {
747 		TV_ERR("cat NOT get timing from tv_mode:%u\n", tv_mode);
748 		return NULL;
749 	}
750 
751 	return &timing[i];
752 
753 }
754 
755 
sunxi_tv_set_mode(int tv_id,enum disp_tv_mode tv_mode)756 int sunxi_tv_set_mode(int tv_id, enum disp_tv_mode tv_mode)
757 {
758 	struct sunxi_tv *p_tv = sunxi_tv_get_tv(tv_id);
759 
760 	if (!p_tv) {
761 		TV_ERR("Null pointer!\n");
762 		return -1;
763 	}
764 
765 	mutex_lock(&p_tv->mlock);
766 	p_tv->tv_mode = tv_mode;
767 	mutex_unlock(&p_tv->mlock);
768 	return 0;
769 }
770 
sunxi_tv_enable(int tv_id)771 int sunxi_tv_enable(int tv_id)
772 {
773 	struct sunxi_tv *p_tv = sunxi_tv_get_tv(tv_id);
774 
775 	if (!p_tv) {
776 		TV_ERR("Null pointer!\n");
777 		return -1;
778 	}
779 
780 	if (!p_tv->enable) {
781 		if (p_tv->tv_type == DISP_VGA)
782 			__pin_config(p_tv->id, "active");
783 
784 		tve_clk_config(p_tv);
785 		tve_low_set_tv_mode(p_tv->id, p_tv->tv_mode, p_tv->cali);
786 		tve_low_dac_enable(p_tv->id);
787 		tve_low_open(p_tv->id);
788 		mutex_lock(&p_tv->mlock);
789 		p_tv->enable = 1;
790 		mutex_unlock(&p_tv->mlock);
791 	}
792 	return 0;
793 }
794 
sunxi_tv_disable(int tv_id)795 int sunxi_tv_disable(int tv_id)
796 {
797 	struct sunxi_tv *p_tv = sunxi_tv_get_tv(tv_id);
798 
799 	if (!p_tv) {
800 		TV_ERR("Null pointer!\n");
801 		return -1;
802 	}
803 
804 	TV_DBG("tv %d\n", p_tv->id);
805 
806 	mutex_lock(&p_tv->mlock);
807 	if (p_tv->enable) {
808 		tve_low_close(p_tv->id);
809 		tve_low_dac_autocheck_enable(p_tv->id);
810 		p_tv->enable = 0;
811 	}
812 	mutex_unlock(&p_tv->mlock);
813 	if (p_tv->tv_type == DISP_VGA)
814 		__pin_config(p_tv->id, "sleep");
815 
816 	return 0;
817 }
818 
sunxi_tv_get_working_mode(int tv_id,struct sunxi_tv_work_mode * work_mode)819 int  sunxi_tv_get_working_mode(int tv_id,
820 		struct sunxi_tv_work_mode *work_mode)
821 {
822 	struct sunxi_tv *p_tv = sunxi_tv_get_tv(tv_id);
823 
824 	if (!p_tv) {
825 		TV_ERR("Null pointer!\n");
826 		return 1;
827 	}
828 
829 	/* vga interface is rgb mode. */
830 	if (p_tv->tv_type == DISP_VGA)
831 		work_mode->color_fmt = COLOR_FMT_RGB444;
832 	else
833 		work_mode->color_fmt = COLOR_FMT_YUV444;
834 
835 	return 0;
836 }
837 
sunxi_tv_get_interface_type(int tv_id)838 enum disp_tv_output sunxi_tv_get_interface_type(int tv_id)
839 {
840 	struct sunxi_tv *p_tv = sunxi_tv_get_tv(tv_id);
841 
842 	if (!p_tv) {
843 		TV_ERR("Null pointer!\n");
844 		return DISP_TV_NONE;
845 	}
846 
847 	return p_tv->tv_type;
848 }
849 
sunxi_tv_get_connect_status(int tv_id)850 int sunxi_tv_get_connect_status(int tv_id)
851 {
852 	struct sunxi_tv *p_tv = sunxi_tv_get_tv(tv_id);
853 
854 	if (!p_tv) {
855 		TV_ERR("Null pointer!\n");
856 		return DISP_TV_NONE;
857 	}
858 
859 	if (p_tv->tv_type == DISP_VGA ||
860 	    p_tv->tv_type == DISP_TV_YPBPR)
861 		return 1;
862 
863 	return tve_low_get_dac_status(p_tv->id);
864 }
865 
sunxi_tv_mode_support(int tv_id,enum disp_tv_mode tv_mode)866 int sunxi_tv_mode_support(int tv_id, enum disp_tv_mode tv_mode)
867 {
868 	struct sunxi_tv *p_tv = sunxi_tv_get_tv(tv_id);
869 	unsigned int i, list_num;
870 	struct disp_video_timings *info;
871 
872 	if (!p_tv) {
873 		TV_ERR("Null pointer!\n");
874 		return 0;
875 	}
876 
877 	list_num = tv_get_timing_list_num(p_tv);
878 	if (!list_num) {
879 		TV_ERR("list number is zero!\n");
880 		return 0;
881 	}
882 
883 	if (p_tv->tv_type == DISP_TV_CVBS)
884 		info = cvbs_timing;
885 	else if (p_tv->tv_type == DISP_VGA)
886 		info = vga_timing;
887 	else
888 		info = ypbpr_timing;
889 
890 	for (i = 0; i < list_num; i++) {
891 		if (info->tv_mode == tv_mode)
892 			return 1;
893 		info++;
894 	}
895 	return 0;
896 }
897 
sunxi_tv_get_video_mode_info(int tv_id,struct disp_video_timings ** video_info,enum disp_tv_mode tv_mode)898 int sunxi_tv_get_video_mode_info(int tv_id,
899 			       struct disp_video_timings **video_info,
900 			       enum disp_tv_mode tv_mode)
901 {
902 	struct disp_video_timings *info;
903 	int ret = -1;
904 	int i, list_num;
905 	struct sunxi_tv *p_tv = sunxi_tv_get_tv(tv_id);
906 	if (!p_tv || !video_info) {
907 		TV_ERR("Null pointer!\n");
908 		return 0;
909 	}
910 
911 	TV_DBG("tv %d\n", p_tv->id);
912 	info = p_tv->video_info;
913 
914 	list_num = tv_get_timing_list_num(p_tv);
915 	for (i = 0; i < list_num; i++) {
916 		mutex_lock(&p_tv->mlock);
917 		if (info->tv_mode == tv_mode) {
918 			*video_info = info;
919 			ret = 0;
920 			mutex_unlock(&p_tv->mlock);
921 			break;
922 		}
923 		mutex_unlock(&p_tv->mlock);
924 		info++;
925 	}
926 	return ret;
927 }
928 
sunxi_tv_get_video_timing_info(int tv_id,unsigned int * num,struct disp_video_timings ** video_info)929 int sunxi_tv_get_video_timing_info(int tv_id, unsigned int *num,
930 			       struct disp_video_timings **video_info)
931 {
932 	struct sunxi_tv *p_tv = sunxi_tv_get_tv(tv_id);
933 
934 	if (!p_tv || !num || !video_info) {
935 		TV_ERR("Null pointer!\n");
936 		return -1;
937 	}
938 
939 	*num = tv_get_timing_list_num(p_tv);
940 	*video_info = p_tv->video_info;
941 	if (!*num || !*video_info) {
942 		TV_ERR("Fail to get num or video_info!\n");
943 		return -1;
944 	}
945 	return 0;
946 }
947 
948 #ifdef CONFIG_AW_AXP
tv_power_enable(const char * name)949 static int tv_power_enable(const char *name)
950 {
951 	struct regulator *regu = NULL;
952 	int ret = -1;
953 
954 	if (!name) {
955 		goto exit;
956 	}
957 
958 	regu = regulator_get(NULL, name);
959 	if (IS_ERR(regu)) {
960 		TV_ERR("%s: some error happen, fail to get regulator %s\n",
961 			__func__, name);
962 		goto exit;
963 	}
964 
965 	/* enalbe regulator */
966 	ret = regulator_enable(regu);
967 	if (0 != ret) {
968 		TV_ERR("%s: some error happen, fail to enable regulator %s!\n",
969 			__func__, name);
970 		goto exit1;
971 	}
972 
973 
974 exit1:
975 	/* put regulater, when module exit */
976 	regulator_put(regu);
977 exit:
978 	return ret;
979 }
980 
tv_power_disable(const char * name)981 static int tv_power_disable(const char *name)
982 {
983 	struct regulator *regu = NULL;
984 	int ret = 0;
985 
986 	if (!name) {
987 		goto exit;
988 	}
989 
990 	regu = regulator_get(NULL, name);
991 	if (IS_ERR(regu)) {
992 		TV_ERR("%s: some error happen, fail to get regulator %s\n",
993 			__func__, name);
994 		goto exit;
995 	}
996 
997 	/*disalbe regulator*/
998 	ret = regulator_disable(regu);
999 	if (0 != ret) {
1000 		TV_ERR("%s: some error happen, fail to disable regulator %s!\n",
1001 			__func__, name);
1002 		goto exit1;
1003 	}
1004 exit1:
1005 	/*put regulater, when module exit*/
1006 	regulator_put(regu);
1007 exit:
1008 	return ret;
1009 }
1010 #else
tv_power_enable(char * name)1011 static int tv_power_enable(char *name)
1012 {
1013 	return 0;
1014 }
tv_power_disable(char * name)1015 static int tv_power_disable(char *name)
1016 {
1017 	return 0;
1018 }
1019 #endif
1020 
1021 #if defined(TVE_TOP_SUPPORT)
tv_top_init(struct sunxi_tv * p_tv)1022 static int tv_top_init(struct sunxi_tv *p_tv)
1023 {
1024 	int ret = -1;
1025 	struct platform_device *pdev = p_tv->pdev;
1026 
1027 	pdev->id = of_alias_get_id(pdev->dev.of_node, "tv");
1028 	if (pdev->id < 0) {
1029 		TV_DBG("failed to get alias id\n");
1030 		return -EINVAL;
1031 	}
1032 
1033 	p_tv->top_addr = of_iomap(pdev->dev.of_node, 0);
1034 	if (IS_ERR_OR_NULL(p_tv->top_addr)) {
1035 		dev_err(&pdev->dev, "unable to map tve common registers\n");
1036 		ret = -EINVAL;
1037 		goto err_iomap;
1038 	}
1039 
1040 	p_tv->top_clk = of_clk_get(pdev->dev.of_node, 0);
1041 	if (IS_ERR(p_tv->top_clk)) {
1042 		dev_err(&pdev->dev, "fail to get clk for tve common module!\n");
1043 		goto err_iomap;
1044 	}
1045 
1046 	tve_low_set_top_reg_base(p_tv->top_addr);
1047 
1048 	return 0;
1049 
1050 err_iomap:
1051 	if (p_tv->top_addr)
1052 		iounmap((char __iomem *)p_tv->top_addr);
1053 	return ret;
1054 }
1055 
1056 #endif
1057 
tve_top_clk_enable(struct sunxi_tv * p_tv)1058 static int tve_top_clk_enable(struct sunxi_tv *p_tv)
1059 {
1060 	int ret = -1;
1061 
1062 	if (!p_tv || !p_tv->top_clk) {
1063 		TV_ERR("NULL pointer!\n");
1064 		goto OUT;
1065 	}
1066 
1067 	ret = clk_prepare_enable(p_tv->top_clk);
1068 	if (ret != 0)
1069 		TV_ERR("fail to enable tve's top clk!\n");
1070 
1071 OUT:
1072 	return ret;
1073 }
1074 
tve_top_clk_disable(struct sunxi_tv * p_tv)1075 static int tve_top_clk_disable(struct sunxi_tv *p_tv)
1076 {
1077 	int ret = -1;
1078 
1079 	if (!p_tv || !p_tv->top_clk) {
1080 		TV_ERR("NULL pointer!\n");
1081 		goto OUT;
1082 	}
1083 
1084 	clk_disable(p_tv->top_clk);
1085 	ret = 0;
1086 OUT:
1087 	return ret;
1088 }
1089 
__get_offset(struct device_node * node,int i)1090 static s32 __get_offset(struct device_node *node, int i)
1091 {
1092 	char sub_key[20] = {0};
1093 	s32 value = 0;
1094 	int ret = 0;
1095 
1096 	snprintf(sub_key, sizeof(sub_key), "dac_offset%d", i);
1097 	ret = of_property_read_u32(node, sub_key, (u32 *)&value);
1098 	if (ret < 0) {
1099 		TV_DBG("there is no tve dac(%d) offset value.\n", i);
1100 	} else {
1101 		/* Sysconfig can not use signed params, however,
1102 		 * dac_offset as a signed param which ranges from
1103 		 * -100 to 100, is maping sysconfig params from
1104 		 * 0 to 200.
1105 		 */
1106 		if ((value > 200) || (value < 0))
1107 			TV_ERR("dac offset is out of range.\n");
1108 		else
1109 			return value - 100;
1110 	}
1111 
1112 	return 0;
1113 }
1114 
tve_clk_init(struct sunxi_tv * p_tv)1115 static void tve_clk_init(struct sunxi_tv *p_tv)
1116 {
1117 	if (!p_tv) {
1118 		TV_ERR("Null pointer!\n");
1119 		return;
1120 	}
1121 
1122 	p_tv->mclk_parent = clk_get_parent(p_tv->mclk);
1123 }
1124 
1125 /*TODO:handle smooth display*/
tv_init(struct sunxi_tv * p_tv)1126 static int tv_init(struct sunxi_tv *p_tv)
1127 {
1128 	s32 i = 0, ret = 0;
1129 	u32 cali_value = 0;
1130 	char sub_key[20] = {0};
1131 	unsigned int value;
1132 	unsigned int interface = 0;
1133 	unsigned long rate = 0;
1134 	struct platform_device *pdev = NULL;
1135 #if defined(CONFIG_ARCH_SUN8IW7)
1136 	unsigned int cali_default[4] = {512, 512, 512, 512};
1137 #else
1138 	unsigned int cali_default[4] = {625, 625, 625, 625};
1139 #endif
1140 
1141 #if defined(CONFIG_ARCH_SUN8IW7)
1142 	s32 sid_turn = 0;
1143 #endif
1144 	if (!p_tv) {
1145 		TV_ERR("Null pointer!\n");
1146 		goto OUT;
1147 	}
1148 
1149 	pdev = p_tv->pdev;
1150 	ret = of_property_read_u32(pdev->dev.of_node, "interface", &interface);
1151 	if (ret < 0) {
1152 		TV_ERR("get tv interface failed!\n");
1153 		goto OUT;
1154 	}
1155 	p_tv->tv_type = interface;
1156 
1157 	if (p_tv->tv_type == DISP_TV_CVBS)
1158 		p_tv->video_info = cvbs_timing;
1159 	else if (p_tv->tv_type == DISP_VGA)
1160 		p_tv->video_info = vga_timing;
1161 	else
1162 		p_tv->video_info = ypbpr_timing;
1163 
1164 	memcpy(p_tv->cali, cali_default, TVE_DAC_NUM * sizeof(unsigned int));
1165 	memset(p_tv->cali_offset, 0, TVE_DAC_NUM * sizeof(int));
1166 
1167 	tve_top_clk_enable(p_tv);
1168 	/* get mapping dac */
1169 	for (i = 0; i < TVE_DAC_NUM; i++) {
1170 		u32 dac_no;
1171 
1172 		snprintf(sub_key, sizeof(sub_key), "dac_src%d", i);
1173 		ret = of_property_read_u32(pdev->dev.of_node, sub_key, &value);
1174 		if (ret < 0) {
1175 			TV_DBG("tve%d have no dac %d\n", p_tv->id, i);
1176 		} else {
1177 			dac_no = value;
1178 			p_tv->dac_no[i] = value;
1179 			++p_tv->dac_num;
1180 			cali_value = tve_low_get_sid(dac_no);
1181 
1182 			TV_DBG("cali_temp = %u\n", cali_value);
1183 			/* VGA mode: 16~31 bits
1184 			 * CVBS & YPBPR mode: 0~15 bits
1185 			 * zero is not allow
1186 			 */
1187 			if (cali_value) {
1188 				if (interface == DISP_VGA)
1189 					p_tv->cali[dac_no] =
1190 					    (cali_value >> 16) & 0xffff;
1191 				else {
1192 #if defined(CONFIG_ARCH_SUN8IW7)
1193 					if (cali_value & (1 << 9))
1194 						sid_turn =
1195 						    0 + (cali_value & 0x1ff);
1196 					else
1197 						sid_turn =
1198 						    0 - (cali_value & 0x1ff);
1199 
1200 					sid_turn += 91;
1201 
1202 					if (sid_turn >= 0)
1203 						sid_turn = (1 << 9) | sid_turn;
1204 					else
1205 						sid_turn = 0 - sid_turn;
1206 					cali_value = (u32)sid_turn;
1207 #endif
1208 					p_tv->cali[dac_no] = cali_value & 0xffff;
1209 				}
1210 			}
1211 			p_tv->cali_offset[dac_no] = __get_offset(pdev->dev.of_node, i);
1212 			TV_DBG("cali[%u] = %u, offset[%u] = %u\n", dac_no,
1213 				 p_tv->cali[dac_no], dac_no, p_tv->cali_offset[dac_no]);
1214 		}
1215 
1216 		snprintf(sub_key, sizeof(sub_key), "dac_type%d", i);
1217 		ret = of_property_read_u32(pdev->dev.of_node, sub_key, &value);
1218 		if (ret < 0) {
1219 			TV_DBG("tve%d have no type%d\n", p_tv->id, i);
1220 			/* if do'not config type, set disabled status */
1221 			p_tv->dac_type[i] = DISP_TV_DAC_SRC_NONE;
1222 		} else {
1223 			p_tv->dac_type[i] = value;
1224 		}
1225 	}
1226 
1227 	/* parse boot params */
1228 
1229 	mutex_init(&p_tv->mlock);
1230 	p_tv->tv_mode = DISP_TV_MOD_PAL;
1231 	ret = tve_get_pixclk(p_tv, &rate);
1232 	if (ret)
1233 		TV_ERR("%s:tve_get_pixclk fail!\n", __func__);
1234 	ret = clk_set_rate(p_tv->mclk, rate);
1235 	if (ret)
1236 		TV_ERR("fail to set rate(%ld) fo tve%d's clock!\n",
1237 		       rate, p_tv->id);
1238 
1239 	tve_low_set_reg_base(p_tv->id, p_tv->base_addr);
1240 	tve_clk_init(p_tv);
1241 #if !defined(CONFIG_COMMON_CLK_ENABLE_SYNCBOOT)
1242 	tve_clk_enable(p_tv);
1243 #endif
1244 
1245 	tve_low_init(p_tv->id, &p_tv->dac_no[0], p_tv->cali,
1246 		     p_tv->cali_offset, p_tv->dac_type,
1247 		     p_tv->dac_num);
1248 
1249 	tve_low_dac_autocheck_enable(p_tv->id);
1250 
1251 OUT:
1252 	return ret;
1253 }
1254 
sunxi_tv_probe(struct platform_device * pdev)1255 static int sunxi_tv_probe(struct platform_device *pdev)
1256 {
1257 	int ret = -1;
1258 	int index = 0;
1259 	struct sunxi_tv *p_tv = NULL;
1260 
1261 	TV_INFO(" start\n");
1262 	pdev->id = of_alias_get_id(pdev->dev.of_node, "tv");
1263 	if (pdev->id < 0) {
1264 		TV_ERR("failed to get alias id\n");
1265 		goto OUT;
1266 	}
1267 
1268 	if (pdev->id > MAX_TV_COUNT) {
1269 		TV_ERR("alias id:%d is too big!\n", pdev->id);
1270 		goto OUT;
1271 	}
1272 
1273 	p_tv = kmalloc(sizeof(struct sunxi_tv), GFP_KERNEL | __GFP_ZERO);
1274 	if (!p_tv) {
1275 		TV_ERR("Malloc sunxi_tv fail!\n");
1276 		goto OUT;
1277 	}
1278 
1279 	hwtv[pdev->id] = p_tv;
1280 
1281 	p_tv->id = pdev->id;
1282 	p_tv->pdev = pdev;
1283 
1284 	if (of_property_read_string(pdev->dev.of_node, "tv_power",
1285 				    &p_tv->p_tv_power))
1286 		TV_DBG("of_property_read_string tv_power failed!\n");
1287 	else
1288 		tv_power_enable(p_tv->p_tv_power);
1289 
1290 #if defined(TVE_TOP_SUPPORT)
1291 	tv_top_init(p_tv);
1292 	index = 1;
1293 #endif
1294 
1295 	p_tv->base_addr =
1296 	    of_iomap(pdev->dev.of_node, index);
1297 	if (IS_ERR_OR_NULL(p_tv->base_addr)) {
1298 		dev_err(&pdev->dev, "fail to get addr for tve%d!\n", pdev->id);
1299 		goto FREE_TV;
1300 	}
1301 
1302 	p_tv->mclk = of_clk_get(pdev->dev.of_node, index);
1303 	if (IS_ERR_OR_NULL(p_tv->mclk)) {
1304 		dev_err(&pdev->dev, "fail to get clk for tve%d's!\n", pdev->id);
1305 		goto err_iomap;
1306 	}
1307 
1308 	ret = tv_init(p_tv);
1309 	if (ret)
1310 		goto err_iomap;
1311 
1312 	tv_count++;
1313 
1314 	return 0;
1315 
1316 err_iomap:
1317 	if (p_tv->base_addr)
1318 		iounmap((char __iomem *)p_tv->base_addr);
1319 
1320 	if (p_tv->top_addr)
1321 		iounmap((char __iomem *)p_tv->top_addr);
1322 
1323 FREE_TV:
1324 	kfree(p_tv);
1325 OUT:
1326 	return ret;
1327 }
1328 
sunxi_tv_remove(struct platform_device * pdev)1329 static int sunxi_tv_remove(struct platform_device *pdev)
1330 {
1331 	struct sunxi_tv *p_tv = hwtv[pdev->id];
1332 
1333 	if (!p_tv) {
1334 		TV_ERR("Null pointer!\n");
1335 		return -1;
1336 	}
1337 
1338 	sunxi_tv_disable(pdev->id);
1339 	tve_top_clk_disable(p_tv);
1340 	tv_power_disable(p_tv->p_tv_power);
1341 	kfree(p_tv);
1342 	return 0;
1343 }
1344 
1345 static const struct of_device_id sunxi_tv_match[] = {
1346 	{ .compatible = "allwinner,sunxi-tv", },
1347 
1348 	{},
1349 };
1350 
1351 struct platform_driver sunxi_tv_platform_driver = {
1352 	.probe = sunxi_tv_probe,
1353 	.remove = sunxi_tv_remove,
1354 	.driver = {
1355 		   .name = "tv",
1356 		   .owner = THIS_MODULE,
1357 		   .of_match_table = sunxi_tv_match,
1358 	},
1359 };
1360 
tv_state_show(struct device * dev,struct device_attribute * attr,char * buf)1361 static ssize_t tv_state_show(struct device *dev, struct device_attribute *attr,
1362 			     char *buf)
1363 {
1364 	ssize_t n = 0;
1365 	struct sunxi_tv *p_tv = NULL;
1366 	int num_of_tv = 0, i = 0;
1367 	char name[40];
1368 
1369 	num_of_tv = sunxi_tv_get_tv_count();
1370 
1371 	for (i = 0; i < num_of_tv; ++i) {
1372 		p_tv = sunxi_tv_get_tv(i);
1373 
1374 		switch (p_tv->tv_type) {
1375 		case DISP_TV_CVBS:
1376 			strncpy(name, "cvbs", 40);
1377 			break;
1378 		case DISP_VGA:
1379 			strncpy(name, "vga", 40);
1380 			break;
1381 		case DISP_TV_YPBPR:
1382 			strncpy(name, "ypbpr", 40);
1383 			break;
1384 		default:
1385 			strncpy(name, "unknown", 40);
1386 			break;
1387 		}
1388 		n += sprintf(buf + n, "%s%d=%d\n", name, p_tv->id,
1389 			     sunxi_tv_get_connect_status(p_tv->id));
1390 	}
1391 
1392 	return n;
1393 }
1394 
1395 static DEVICE_ATTR(tv_state, 0660, tv_state_show, NULL);
1396 
1397 static struct attribute *tv_attributes[] = {
1398 	&dev_attr_tv_state.attr,
1399 	NULL
1400 };
1401 
1402 static struct attribute_group tv_attribute_group = {
1403 	.name = "attr",
1404 	.attrs = tv_attributes,
1405 };
1406 
sunxi_tv_module_init(void)1407 int sunxi_tv_module_init(void)
1408 {
1409 	int ret = -1;
1410 
1411 	TV_INFO(" start\n");
1412 	p_tv_drv = kmalloc(sizeof(struct drv_model_info), GFP_KERNEL | __GFP_ZERO);
1413 	if (!p_tv_drv) {
1414 		TV_ERR("Null drv_model_info pointer\n");
1415 		goto OUT;
1416 	}
1417 	ret = alloc_chrdev_region(&p_tv_drv->devid, 0, 1, "tv");
1418 	if (ret < 0) {
1419 		TV_ERR("alloc_chrdev_region failed\n");
1420 		goto FREE_DRV;
1421 	}
1422 
1423 	p_tv_drv->cdev = cdev_alloc();
1424 	if (!p_tv_drv->cdev) {
1425 		TV_ERR("cdev_alloc failed\n");
1426 		goto FREE_DRV;
1427 	}
1428 
1429 	cdev_init(p_tv_drv->cdev, NULL);
1430 	p_tv_drv->cdev->owner = THIS_MODULE;
1431 	ret = cdev_add(p_tv_drv->cdev, p_tv_drv->devid, 1);
1432 	if (ret) {
1433 		TV_ERR("cdev_add major number:%d failed\n",
1434 		       MAJOR(p_tv_drv->devid));
1435 		goto FREE_DRV;
1436 	}
1437 
1438 	p_tv_drv->sysclass = class_create(THIS_MODULE, "tv");
1439 	if (IS_ERR(p_tv_drv->sysclass)) {
1440 		TV_ERR("create class error\n");
1441 		goto FREE_DRV;
1442 	}
1443 
1444 	p_tv_drv->dev = device_create(p_tv_drv->sysclass, NULL, p_tv_drv->devid,
1445 				      NULL, "tv");
1446 	if (!p_tv_drv->dev) {
1447 		TV_ERR("device_create failed\n");
1448 		goto FREE_DRV;
1449 	}
1450 
1451 	tv_count = 0;
1452 
1453 	ret = platform_driver_register(&sunxi_tv_platform_driver);
1454 	if (ret) {
1455 		TV_ERR("platform_driver_register failed\n");
1456 		goto FREE_DEVICE;
1457 	}
1458 
1459 	ret = sysfs_create_group(&p_tv_drv->dev->kobj, &tv_attribute_group);
1460 	if (ret < 0) {
1461 		TV_ERR("sysfs_create_file fail!\n");
1462 		goto UNREGISTER;
1463 	}
1464 
1465 
1466 	TV_INFO(" end\n");
1467 	return ret;
1468 
1469 UNREGISTER:
1470 	platform_driver_unregister(&sunxi_tv_platform_driver);
1471 FREE_DEVICE:
1472 	device_destroy(p_tv_drv->sysclass, p_tv_drv->devid);
1473 FREE_DRV:
1474 	kfree(p_tv_drv);
1475 OUT:
1476 	TV_ERR(" failed\n");
1477 	return -EINVAL;
1478 }
1479 
sunxi_tv_module_exit(void)1480 void sunxi_tv_module_exit(void)
1481 {
1482 	TV_INFO("\n");
1483 	if (p_tv_drv) {
1484 		platform_driver_unregister(&sunxi_tv_platform_driver);
1485 
1486 		device_destroy(p_tv_drv->sysclass, p_tv_drv->devid);
1487 		class_destroy(p_tv_drv->sysclass);
1488 
1489 		cdev_del(p_tv_drv->cdev);
1490 		kfree(p_tv_drv);
1491 	}
1492 }
1493