1 #include <linux/console.h>
2 #include<linux/rk_fb.h>
5 #define OUT_TYPE SCREEN_HDMI
6 #define OUT_FACE OUT_P888
9 #define LCD_ACLK 800000000
11 static struct hdmi *m_hdmi_drv = NULL;
13 static const struct fb_videomode hdmi_mode [] = {
14 //name refresh xres yres pixclock h_bp h_fp v_bp v_fp h_pw v_pw polariry PorI flag(used for vic)
15 //{ "640x480p@60Hz", 60, 640, 480, 25175000, 48, 16, 33, 10, 96, 2, 0, 0, 1 },
16 //{ "720x480i@60Hz", 60, 720, 480, 27000000, 114, 38, 15, 4, 124, 3, 0, 1, 6 },
17 //{ "720x576i@50Hz", 50, 720, 576, 27000000, 138, 24, 19, 2, 126, 3, 0, 1, 21 },
18 { "720x480p@60Hz", 60, 720, 480, 27000000, 60, 16, 30, 9, 62, 6, 0, 0, 2 },
19 { "720x576p@50Hz", 50, 720, 576, 27000000, 68, 12, 39, 5, 64, 5, 0, 0, 17 },
20 //{ "1280x720p@24Hz", 24, 1280, 720, 59400000, 220, 1760, 20, 5, 40, 5, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 60 },
21 //{ "1280x720p@25Hz", 25, 1280, 720, 74250000, 220, 2420, 20, 5, 40, 5, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 61 },
22 //{ "1280x720p@30Hz", 30, 1280, 720, 74250000, 220, 1760, 20, 5, 40, 5, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 62 },
23 { "1280x720p@50Hz", 50, 1280, 720, 74250000, 220, 440, 20, 5, 40, 5, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 19 },
24 { "1280x720p@60Hz", 60, 1280, 720, 74250000, 220, 110, 20, 5, 40, 5, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 4 },
25 //{ "1920x1080p@24Hz", 24, 1920, 1080, 74250000, 148, 638, 36, 4, 44, 5, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 32 },
26 //{ "1920x1080p@25Hz", 25, 1920, 1080, 74250000, 148, 528, 36, 4, 44, 5, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 33 },
27 //{ "1920x1080p@30Hz", 30, 1920, 1080, 74250000, 148, 88, 36, 4, 44, 5, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 34 },
28 //{ "1920x1080i@50Hz_2", 50, 1920, 1080, 72000000, 184, 32, 57, 23, 168, 5, FB_SYNC_HOR_HIGH_ACT, 1, 39 },
29 //{ "1920x1080i@50Hz", 50, 1920, 1080, 74250000, 148, 528, 15, 2, 44, 5, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 1, 20 },
30 //{ "1920x1080i@60Hz", 60, 1920, 1080, 74250000, 148, 88, 15, 2, 44, 5, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 1, 5 },
31 { "1920x1080p@50Hz", 50, 1920, 1080, 148500000, 148, 528, 36, 4, 44, 5, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 31 },
32 { "1920x1080p@60Hz", 60, 1920, 1080, 148500000, 148, 88, 36, 4, 44, 5, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 16 },
34 { "1440x288p@50Hz", 50, 720, 480, 27000000, 138, 24, 19, 2, 126, 3, 0, 0, 23 },
35 { "2880x576i@50Hz", 50, 1440, 240, 54000000, 276, 48, 19, 2, 252, 3, 0, 1, 25 },
36 { "2880x288p@50Hz", 50, 2880, 480, 54000000, 276, 48, 19, 3, 252, 3, 0, 0, 27 },
37 { "1440x576p@50Hz", 50, 2880, 480, 54000000, 136, 24, 39, 5, 128, 5, 0, 0, 29 },
38 { "2880x576p@50Hz", 50, 1920, 1080, 108000000, 272, 48, 39, 5, 256, 5, 0, 0, 37 },
39 { "1440x240p@60Hz", 60, 1440, 240, 27000000, 114, 38, 15, 4, 124, 3, 0, 0, 8 },
40 { "2880x480i@60Hz", 60, 2880, 480, 54000000, 228, 76, 15, 4, 248, 3, 0, 1, 10 },
41 { "2880x480p@60Hz", 60, 2880, 480, 54000000, 228, 76, 15, 4, 248, 3, 0, 0, 12 },
42 { "1440x480p@60Hz", 60, 1440, 480, 54000000, 120, 32, 30, 9, 124, 6, 0, 0, 14 },
43 { "2880x480p@60Hz", 60, 2880, 480, 54000000, 240, 64, 30, 9, 248, 6, 0, 0, 35 },
45 { "1920x1080i@100Hz", 100, 1920, 1080, 148500000, 148, 528, 15, 2, 44, 5, 1, 1, 40 },
46 { "1280x720p@100Hz", 100, 1280, 720, 148500000, 220, 440, 20, 5, 40, 5, 1, 0, 41 },
47 { "720x576p@100Hz", 100, 720, 576, 54000000, 68, 12, 39, 5, 64, 5, 0, 0, 42 },
48 { "1440x576i@100Hz", 100, 1440, 576, 54000000, 138, 24, 19, 2, 12, 3, 0, 1, 44 },
49 { "1920x1080p@100Hz", 100, 1920, 1080, 297000000, 148, 528, 36, 4, 44, 5, 1, 0, 64 },
51 { "1920x1080i@120Hz", 120, 1920, 1080, 148500000, 148, 88, 15, 2, 44, 5, 1, 1, 46 },
52 { "1280x720p@120Hz", 120, 1280, 720, 148500000, 220, 110, 20, 5, 40, 5, 1, 0, 47 },
53 { "720x480p@120Hz", 120, 720, 480, 54000000, 60, 16, 30, 9, 62, 6, 0, 0, 48 },
54 { "1440x480i@120Hz", 120, 1440, 480, 54000000, 114, 38, 15, 4, 12, 3, 0, 1, 50 },
55 { "1920x1080p@120Hz", 120, 1920, 1080, 297000000, 148, 88, 36, 4, 44, 5, 1, 0, 63 },
57 { "720x576p@200Hz", 200, 720, 576, 108000000, 68, 12, 39, 5, 64, 5, 0, 0, 52 },
58 { "1440x576i@200Hz", 200, 1920, 1080, 108000000, 138, 24, 19, 2, 12, 3, 0, 1, 54 },
60 { "720x480p@240Hz", 240, 720, 480, 108000000, 60, 16, 30, 9, 62, 6, 0, 0, 56 },
61 { "1440x480i@240Hz", 240, 1440, 480, 108000000, 114, 38, 15, 4, 12, 3, 0, 1, 58 },
63 { "3840x2160p@24Hz", 24, 3840, 2160, 297000000, 296, 1276, 72, 8, 88, 10, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 93 },
64 { "3840x2160p@25Hz", 25, 3840, 2160, 297000000, 296, 1056, 72, 8, 88, 10, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 94 },
65 { "3840x2160p@30Hz", 30, 3840, 2160, 297000000, 296, 176, 72, 8, 88, 10, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 95 },
66 { "4096x2160p@24Hz", 24, 4096, 2160, 297000000, 296, 1020, 72, 8, 88, 10, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 98 },
70 void hdmi_init_lcdc(struct rk_screen *screen, struct rk29lcd_info *lcd_info)
72 hdmi_set_info(screen, HDMI_VIDEO_DEFAULT_MODE);
75 int hdmi_set_info(struct rk_screen *screen, unsigned int vic)
83 vic = HDMI_VIDEO_DEFAULT_MODE;
85 for(i = 0; i < ARRAY_SIZE(hdmi_mode); i++)
87 if(hdmi_mode[i].flag == vic)
90 if(i == ARRAY_SIZE(hdmi_mode))
93 memset(screen, 0, sizeof(struct rk_screen));
95 /* screen type & face */
96 screen->type = OUT_TYPE;
97 screen->face = OUT_FACE;
100 screen->mode.xres = hdmi_mode[i].xres;
101 screen->mode.yres = hdmi_mode[i].yres;
104 screen->mode.pixclock = hdmi_mode[i].pixclock;
105 screen->mode.refresh = hdmi_mode[i].refresh;
106 //screen->lcdc_aclk = LCD_ACLK;
107 screen->mode.left_margin = hdmi_mode[i].left_margin;
108 screen->mode.right_margin = hdmi_mode[i].right_margin;
109 screen->mode.hsync_len = hdmi_mode[i].hsync_len;
110 screen->mode.upper_margin = hdmi_mode[i].upper_margin;
111 screen->mode.lower_margin = hdmi_mode[i].lower_margin;
112 screen->mode.vsync_len = hdmi_mode[i].vsync_len;
113 screen->hdmi_resolution = hdmi_mode[i].flag;
116 #if defined(CONFIG_HDMI_RK616) && !defined(CONFIG_ARCH_RK3026)
117 screen->pin_hsync = 0;
118 screen->pin_vsync = 0;
120 screen->pin_hsync = 0;
121 if(FB_SYNC_HOR_HIGH_ACT & hdmi_mode[i].sync)
122 screen->pin_hsync = 1;
124 screen->pin_hsync = 0;
125 if(FB_SYNC_VERT_HIGH_ACT & hdmi_mode[i].sync)
126 screen->pin_vsync = 1;
128 screen->pin_vsync = 0;
131 screen->pin_dclk = DCLK_POL;
134 screen->swap_rb = SWAP_RB;
137 screen->swap_delta = 0;
138 screen->swap_dumy = 0;
140 /* Operation function*/
142 screen->standby = NULL;
147 static void hdmi_show_sink_info(struct hdmi *hdmi)
149 struct list_head *pos, *head = &hdmi->edid.modelist;
150 struct fb_modelist *modelist;
151 struct fb_videomode *m;
153 struct hdmi_audio *audio;
155 hdmi_dbg(hdmi->dev, "******** Show Sink Info ********\n");
156 hdmi_dbg(hdmi->dev, "Support video mode: \n");
157 list_for_each(pos, head) {
158 modelist = list_entry(pos, struct fb_modelist, list);
160 hdmi_dbg(hdmi->dev, " %s.\n", m->name);
163 for(i = 0; i < hdmi->edid.audio_num; i++)
165 audio = &(hdmi->edid.audio[i]);
168 case HDMI_AUDIO_LPCM:
169 hdmi_dbg(hdmi->dev, "Support audio type: LPCM\n");
172 hdmi_dbg(hdmi->dev, "Support audio type: AC3\n");
174 case HDMI_AUDIO_MPEG1:
175 hdmi_dbg(hdmi->dev, "Support audio type: MPEG1\n");
178 hdmi_dbg(hdmi->dev, "Support audio type: MP3\n");
180 case HDMI_AUDIO_MPEG2:
181 hdmi_dbg(hdmi->dev, "Support audio type: MPEG2\n");
183 case HDMI_AUDIO_AAC_LC:
184 hdmi_dbg(hdmi->dev, "Support audio type: AAC\n");
187 hdmi_dbg(hdmi->dev, "Support audio type: DTS\n");
189 case HDMI_AUDIO_ATARC:
190 hdmi_dbg(hdmi->dev, "Support audio type: ATARC\n");
193 hdmi_dbg(hdmi->dev, "Support audio type: DSD\n");
195 case HDMI_AUDIO_E_AC3:
196 hdmi_dbg(hdmi->dev, "Support audio type: E-AC3\n");
198 case HDMI_AUDIO_DTS_HD:
199 hdmi_dbg(hdmi->dev, "Support audio type: DTS-HD\n");
202 hdmi_dbg(hdmi->dev, "Support audio type: MLP\n");
205 hdmi_dbg(hdmi->dev, "Support audio type: DST\n");
207 case HDMI_AUDIO_WMA_PRO:
208 hdmi_dbg(hdmi->dev, "Support audio type: WMP-PRO\n");
211 hdmi_dbg(hdmi->dev, "Support audio type: Unkown\n");
215 hdmi_dbg(hdmi->dev, "Support audio sample rate: \n");
216 if(audio->rate & HDMI_AUDIO_FS_32000)
217 hdmi_dbg(hdmi->dev, " 32000\n");
218 if(audio->rate & HDMI_AUDIO_FS_44100)
219 hdmi_dbg(hdmi->dev, " 44100\n");
220 if(audio->rate & HDMI_AUDIO_FS_48000)
221 hdmi_dbg(hdmi->dev, " 48000\n");
222 if(audio->rate & HDMI_AUDIO_FS_88200)
223 hdmi_dbg(hdmi->dev, " 88200\n");
224 if(audio->rate & HDMI_AUDIO_FS_96000)
225 hdmi_dbg(hdmi->dev, " 96000\n");
226 if(audio->rate & HDMI_AUDIO_FS_176400)
227 hdmi_dbg(hdmi->dev, " 176400\n");
228 if(audio->rate & HDMI_AUDIO_FS_192000)
229 hdmi_dbg(hdmi->dev, " 192000\n");
231 hdmi_dbg(hdmi->dev, "Support audio word lenght: \n");
232 if(audio->rate & HDMI_AUDIO_WORD_LENGTH_16bit)
233 hdmi_dbg(hdmi->dev, " 16bit\n");
234 if(audio->rate & HDMI_AUDIO_WORD_LENGTH_20bit)
235 hdmi_dbg(hdmi->dev, " 20bit\n");
236 if(audio->rate & HDMI_AUDIO_WORD_LENGTH_24bit)
237 hdmi_dbg(hdmi->dev, " 24bit\n");
239 hdmi_dbg(hdmi->dev, "******** Show Sink Info ********\n");
243 * hdmi_ouputmode_select - select hdmi transmitter output mode: hdmi or dvi?
244 * @hdmi: handle of hdmi
245 * @edid_ok: get EDID data success or not, HDMI_ERROR_SUCESS means success.
247 int hdmi_ouputmode_select(struct hdmi *hdmi, int edid_ok)
249 struct list_head *head = &hdmi->edid.modelist;
250 struct fb_monspecs *specs = hdmi->edid.specs;
251 struct fb_videomode *modedb = NULL;
254 if(edid_ok != HDMI_ERROR_SUCESS) {
255 dev_err(hdmi->dev, "warning: EDID error, assume sink as HDMI and asume minitor support audio output!!!!");
256 hdmi->edid.sink_hdmi = 1;
257 //if edid error,asume monitor support audio output.
258 hdmi->edid.base_audio_support = 1;
261 if(edid_ok != HDMI_ERROR_SUCESS) {
262 hdmi->edid.ycbcr444 = 0;
263 hdmi->edid.ycbcr422 = 0;
264 hdmi->autoconfig = HDMI_DISABLE;
266 if(head->next == head) {
267 dev_info(hdmi->dev, "warning: no CEA video mode parsed from EDID !!!!");
268 // If EDID get error, list all system supported mode.
269 // If output mode is set to DVI and EDID is ok, check
270 // the output timing.
272 if(hdmi->edid.sink_hdmi == 0 && specs && specs->modedb_len) {
273 /* Get max resolution timing */
274 modedb = &specs->modedb[0];
275 for (i = 0; i < specs->modedb_len; i++) {
276 if(specs->modedb[i].xres > modedb->xres)
277 modedb = &specs->modedb[i];
278 else if(specs->modedb[i].yres > modedb->yres)
279 modedb = &specs->modedb[i];
281 // For some monitor, the max pixclock read from EDID is smaller
282 // than the clock of max resolution mode supported. We fix it.
283 pixclock = PICOS2KHZ(modedb->pixclock);
287 if(pixclock == 148250000)
288 pixclock = 148500000;
289 if(pixclock > specs->dclkmax)
290 specs->dclkmax = pixclock;
293 for(i = 0; i < ARRAY_SIZE(hdmi_mode); i++) {
295 if( (hdmi_mode[i].pixclock < specs->dclkmin) ||
296 (hdmi_mode[i].pixclock > specs->dclkmax) ||
297 (hdmi_mode[i].refresh < specs->vfmin) ||
298 (hdmi_mode[i].refresh > specs->vfmax) ||
299 (hdmi_mode[i].xres > modedb->xres) ||
300 (hdmi_mode[i].yres > modedb->yres) )
303 hdmi_add_videomode(&hdmi_mode[i], head);
308 hdmi_show_sink_info(hdmi);
310 return HDMI_ERROR_SUCESS;
313 * hdmi_videomode_compare - compare 2 videomodes
314 * @mode1: first videomode
315 * @mode2: second videomode
318 * 1 if mode1 > mode2, 0 if mode1 = mode2, -1 mode1 < mode2
320 static int hdmi_videomode_compare(const struct fb_videomode *mode1,
321 const struct fb_videomode *mode2)
323 if(mode1->xres > mode2->xres)
325 else if(mode1->xres == mode2->xres)
327 if(mode1->yres > mode2->yres)
329 else if(mode1->yres == mode2->yres)
331 if(mode1->pixclock > mode2->pixclock)
333 else if(mode1->pixclock == mode2->pixclock)
335 if(mode1->refresh > mode2->refresh)
337 else if(mode1->refresh == mode2->refresh)
345 * hdmi_add_videomode: adds videomode entry to modelist
346 * @mode: videomode to add
347 * @head: struct list_head of modelist
350 * Will only add unmatched mode entries
352 int hdmi_add_videomode(const struct fb_videomode *mode, struct list_head *head)
354 struct list_head *pos;
355 struct fb_modelist *modelist, *modelist_new;
356 struct fb_videomode *m;
359 for(i = 0; i < ARRAY_SIZE(hdmi_mode); i++)
361 m =(struct fb_videomode*) &hdmi_mode[i];
362 if (fb_mode_is_equal(m, mode)) {
369 list_for_each(pos, head) {
370 modelist = list_entry(pos, struct fb_modelist, list);
372 if (fb_mode_is_equal(m, mode)) {
378 if(hdmi_videomode_compare(m, mode) == -1) {
384 modelist_new = kmalloc(sizeof(struct fb_modelist),
388 modelist_new->mode = hdmi_mode[i];
389 list_add_tail(&modelist_new->list, pos);
396 * hdmi_videomode_to_vic: transverse video mode to vic
397 * @vmode: videomode to transverse
400 int hdmi_videomode_to_vic(struct fb_videomode *vmode)
402 unsigned char vic = 0;
405 for(i = 0; i < ARRAY_SIZE(hdmi_mode); i++)
407 if( vmode->vmode == hdmi_mode[i].vmode &&
408 vmode->refresh == hdmi_mode[i].refresh &&
409 vmode->xres == hdmi_mode[i].xres &&
410 vmode->left_margin == hdmi_mode[i].left_margin &&
411 vmode->right_margin == hdmi_mode[i].right_margin &&
412 vmode->upper_margin == hdmi_mode[i].upper_margin &&
413 vmode->lower_margin == hdmi_mode[i].lower_margin &&
414 vmode->hsync_len == hdmi_mode[i].hsync_len &&
415 vmode->vsync_len == hdmi_mode[i].vsync_len)
417 if( (vmode->vmode == FB_VMODE_NONINTERLACED && vmode->yres == hdmi_mode[i].yres) ||
418 (vmode->vmode == FB_VMODE_INTERLACED && vmode->yres == hdmi_mode[i].yres/2))
420 vic = hdmi_mode[i].flag;
429 * hdmi_vic_to_videomode: transverse vic mode to video mode
430 * @vmode: vic to transverse
433 const struct fb_videomode* hdmi_vic_to_videomode(int vic)
440 for(i = 0; i < ARRAY_SIZE(hdmi_mode); i++)
442 if(hdmi_mode[i].flag == vic)
443 return &hdmi_mode[i];
449 * hdmi_find_best_mode: find the video mode nearest to input vic
454 * If vic is zero, return the high resolution video mode vic.
456 int hdmi_find_best_mode(struct hdmi* hdmi, int vic)
458 struct list_head *pos, *head = &hdmi->edid.modelist;
459 struct fb_modelist *modelist;
460 struct fb_videomode *m = NULL;
465 list_for_each(pos, head) {
466 modelist = list_entry(pos, struct fb_modelist, list);
475 if( (vic == 0 || found == 0) && head->next != head)
477 modelist = list_entry(head->next, struct fb_modelist, list);
486 const char *hdmi_get_video_mode_name(unsigned char vic)
490 for(i = 0; i < ARRAY_SIZE(hdmi_mode); i++)
492 if(vic == hdmi_mode[i].flag)
495 if(i == ARRAY_SIZE(hdmi_mode))
498 return hdmi_mode[i].name;
502 * hdmi_switch_fb: switch lcdc mode to required video mode
509 int hdmi_switch_fb(struct hdmi *hdmi, int vic)
512 struct rk_screen *screen;
515 screen = kzalloc(sizeof(struct rk_screen), GFP_KERNEL);
520 hdmi->vic = HDMI_VIDEO_DEFAULT_MODE;
523 rc = hdmi_set_info(screen, hdmi->vic);
527 hdmi->set_vif(hdmi,screen,0); //turn off vif for jettab
528 rk_fb_switch_screen(screen, 1, hdmi->lcdc->id);
529 rk_fb_disp_scale(hdmi->xscale, hdmi->yscale, hdmi->lcdc->id);
531 hdmi->set_vif(hdmi,screen,1);
541 * hdmi_drv_register: init hdmi_drv variable
546 int hdmi_drv_register(struct hdmi *hdmi_drv)
548 m_hdmi_drv = hdmi_drv;
553 * hdmi_get_status: get hdmi hotplug status
558 int hdmi_get_hotplug(void)
561 return m_hdmi_drv->hotplug;
563 return HDMI_HPD_REMOVED;