2 * Copyright 2009-2011 Freescale Semiconductor, Inc. All Rights Reserved.
6 * The code contained herein is licensed under the GNU General Public
7 * License. You may obtain a copy of the GNU General Public License
8 * Version 2 or later at the following locations:
10 * http://www.opensource.org/licenses/gpl-license.html
11 * http://www.gnu.org/copyleft/gpl.html
15 * @defgroup Framebuffer Framebuffer Driver for SDC and ADC.
21 * @brief MXC EDID driver
23 * @ingroup Framebuffer
29 #include <linux/i2c.h>
31 #include <mach/mxc_edid.h>
34 #undef DEBUG /* define this for verbose EDID parsing output */
37 #define DPRINTK(fmt, args...) printk(fmt, ## args)
39 #define DPRINTK(fmt, args...)
42 const struct fb_videomode mxc_cea_mode[64] = {
43 /* #1: 640x480p@59.94/60Hz 4:3 */
45 NULL, 60, 640, 480, 39722, 48, 16, 33, 10, 96, 2, 0,
46 FB_VMODE_NONINTERLACED, FB_MODE_ASPECT_4_3,
48 /* #2: 720x480p@59.94/60Hz 4:3 */
50 NULL, 60, 640, 480, 39722, 48, 16, 33, 10, 96, 2, 0,
51 FB_VMODE_NONINTERLACED, FB_MODE_ASPECT_4_3,
53 /* #3: 720x480p@59.94/60Hz 16:9 */
55 NULL, 60, 720, 480, 37037, 60, 16, 30, 9, 62, 6, 0,
56 FB_VMODE_NONINTERLACED, FB_MODE_ASPECT_16_9,
58 /* #4: 1280x720p@59.94/60Hz 16:9 */
60 NULL, 60, 1280, 720, 13468, 220, 110, 20, 5, 40, 5,
61 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
62 FB_VMODE_NONINTERLACED, FB_MODE_ASPECT_16_9,
64 /* #5: 1920x1080i@59.94/60Hz 16:9 */
66 NULL, 60, 1920, 1080, 13763, 148, 88, 15, 2, 44, 5,
67 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
68 FB_VMODE_INTERLACED, FB_MODE_ASPECT_16_9,
70 /* #6: 720(1440)x480iH@59.94/60Hz 4:3 */
72 NULL, 60, 1440, 480, 18554/*37108*/, 114, 38, 15, 4, 124, 3, 0,
73 FB_VMODE_INTERLACED, FB_MODE_ASPECT_4_3,
75 /* #7: 720(1440)x480iH@59.94/60Hz 16:9 */
77 NULL, 60, 1440, 480, 18554/*37108*/, 114, 38, 15, 4, 124, 3, 0,
78 FB_VMODE_INTERLACED, FB_MODE_ASPECT_16_9,
80 /* #8: 720(1440)x240pH@59.94/60Hz 4:3 */
82 NULL, 60, 1440, 240, 18554, 114, 38, 16, 4, 124, 3, 0,
83 FB_VMODE_NONINTERLACED, FB_MODE_ASPECT_16_9,
85 /* #9: 720(1440)x240pH@59.94/60Hz 16:9 */
87 NULL, 60, 1440, 240, 18554, 114, 38, 16, 4, 124, 3, 0,
88 FB_VMODE_NONINTERLACED, FB_MODE_ASPECT_16_9,
90 /* #16: 1920x1080p@60Hz 16:9 */
92 NULL, 60, 1920, 1080, 6734, 148, 88, 36, 4, 44, 5,
93 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
94 FB_VMODE_NONINTERLACED, FB_MODE_ASPECT_16_9,
96 /* #17: 720x576pH@50Hz 4:3 */
98 NULL, 50, 720, 576, 37037, 68, 12, 39, 5, 64, 5, 0,
99 FB_VMODE_NONINTERLACED, FB_MODE_ASPECT_4_3,
101 /* #18: 720x576pH@50Hz 16:9 */
103 NULL, 50, 720, 576, 37037, 68, 12, 39, 5, 64, 5, 0,
104 FB_VMODE_NONINTERLACED, FB_MODE_ASPECT_16_9,
106 /* #19: 1280x720p@50Hz */
108 NULL, 50, 1280, 720, 13468, 220, 440, 20, 5, 40, 5,
109 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
110 FB_VMODE_NONINTERLACED, FB_MODE_ASPECT_16_9,
112 /* #20: 1920x1080i@50Hz */
114 NULL, 50, 1920, 1080, 13480, 148, 528, 15, 5, 528, 5,
115 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
116 FB_VMODE_INTERLACED, FB_MODE_ASPECT_16_9,
118 /* #31: 1920x1080p@50Hz */
120 NULL, 50, 1920, 1080, 6734, 148, 528, 36, 4, 44, 5,
121 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
122 FB_VMODE_NONINTERLACED, FB_MODE_ASPECT_16_9,
124 /* #32: 1920x1080p@23.98/24Hz */
126 NULL, 24, 1920, 1080, 13468, 148, 638, 36, 4, 44, 5,
127 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
128 FB_VMODE_NONINTERLACED, FB_MODE_ASPECT_16_9,
130 /* #35: (2880)x480p4x@59.94/60Hz */
132 NULL, 60, 2880, 480, 9250, 240, 64, 30, 9, 248, 6, 0,
133 FB_VMODE_NONINTERLACED, FB_MODE_ASPECT_4_3,
138 * We have a special version of fb_mode_is_equal that ignores
139 * pixclock, since for many CEA modes, 2 frequencies are supported
140 * e.g. 640x480 @ 60Hz or 59.94Hz
142 int mxc_edid_fb_mode_is_equal(const struct fb_videomode *mode1,
143 const struct fb_videomode *mode2)
145 return (mode1->xres == mode2->xres &&
146 mode1->yres == mode2->yres &&
147 mode1->hsync_len == mode2->hsync_len &&
148 mode1->vsync_len == mode2->vsync_len &&
149 mode1->left_margin == mode2->left_margin &&
150 mode1->right_margin == mode2->right_margin &&
151 mode1->upper_margin == mode2->upper_margin &&
152 mode1->lower_margin == mode2->lower_margin &&
153 mode1->sync == mode2->sync &&
154 mode1->vmode == mode2->vmode);
157 static void get_detailed_timing(unsigned char *block,
158 struct fb_videomode *mode)
160 mode->xres = H_ACTIVE;
161 mode->yres = V_ACTIVE;
162 mode->pixclock = PIXEL_CLOCK;
163 mode->pixclock /= 1000;
164 mode->pixclock = KHZ2PICOS(mode->pixclock);
165 mode->right_margin = H_SYNC_OFFSET;
166 mode->left_margin = (H_ACTIVE + H_BLANKING) -
167 (H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH);
168 mode->upper_margin = V_BLANKING - V_SYNC_OFFSET -
170 mode->lower_margin = V_SYNC_OFFSET;
171 mode->hsync_len = H_SYNC_WIDTH;
172 mode->vsync_len = V_SYNC_WIDTH;
174 mode->sync |= FB_SYNC_HOR_HIGH_ACT;
176 mode->sync |= FB_SYNC_VERT_HIGH_ACT;
177 mode->refresh = PIXEL_CLOCK/((H_ACTIVE + H_BLANKING) *
178 (V_ACTIVE + V_BLANKING));
181 mode->upper_margin *= 2;
182 mode->lower_margin *= 2;
183 mode->vsync_len *= 2;
184 mode->vmode |= FB_VMODE_INTERLACED;
186 mode->flag = FB_MODE_IS_DETAILED;
188 DPRINTK(" %d MHz ", PIXEL_CLOCK/1000000);
189 DPRINTK("%d %d %d %d ", H_ACTIVE, H_ACTIVE + H_SYNC_OFFSET,
190 H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH, H_ACTIVE + H_BLANKING);
191 DPRINTK("%d %d %d %d ", V_ACTIVE, V_ACTIVE + V_SYNC_OFFSET,
192 V_ACTIVE + V_SYNC_OFFSET + V_SYNC_WIDTH, V_ACTIVE + V_BLANKING);
193 DPRINTK("%sHSync %sVSync\n\n", (HSYNC_POSITIVE) ? "+" : "-",
194 (VSYNC_POSITIVE) ? "+" : "-");
197 int mxc_edid_parse_ext_blk(unsigned char *edid,
198 struct mxc_edid_cfg *cfg,
199 struct fb_monspecs *specs)
201 char detail_timing_desc_offset;
202 struct fb_videomode *mode, *m;
203 unsigned char index = 0x0;
204 unsigned char *block;
205 int i, num = 0, revision;
207 if (edid[index++] != 0x2) /* only support cea ext block now */
209 revision = edid[index++];
210 DPRINTK("cea extent revision %d\n", revision);
211 mode = kzalloc(50 * sizeof(struct fb_videomode), GFP_KERNEL);
215 detail_timing_desc_offset = edid[index++];
218 cfg->cea_underscan = (edid[index] >> 7) & 0x1;
219 cfg->cea_basicaudio = (edid[index] >> 6) & 0x1;
220 cfg->cea_ycbcr444 = (edid[index] >> 5) & 0x1;
221 cfg->cea_ycbcr422 = (edid[index] >> 4) & 0x1;
223 DPRINTK("CEA underscan %d\n", cfg->cea_underscan);
224 DPRINTK("CEA basicaudio %d\n", cfg->cea_basicaudio);
225 DPRINTK("CEA ycbcr444 %d\n", cfg->cea_ycbcr444);
226 DPRINTK("CEA ycbcr422 %d\n", cfg->cea_ycbcr422);
231 DPRINTK("CEA Short desc timmings\n");
233 while (index < detail_timing_desc_offset) {
234 unsigned char tagcode, blklen;
236 tagcode = (edid[index] >> 5) & 0x7;
237 blklen = (edid[index]) & 0x1f;
239 DPRINTK("Tagcode %x Len %d\n", tagcode, blklen);
242 case 0x2: /*Video data block*/
248 cea_idx = edid[index] & 0x7f;
249 if (cea_idx < ARRAY_SIZE(mxc_cea_mode) &&
250 (mxc_cea_mode[cea_idx].xres)) {
251 DPRINTK("Support CEA Format #%d\n", cea_idx);
252 mode[num] = mxc_cea_mode[cea_idx];
253 mode[num].flag |= FB_MODE_IS_STANDARD;
260 case 0x3: /*Vendor specific data*/
262 unsigned char IEEE_reg_iden[3];
263 unsigned char deep_color;
264 IEEE_reg_iden[0] = edid[index+1];
265 IEEE_reg_iden[1] = edid[index+2];
266 IEEE_reg_iden[2] = edid[index+3];
267 deep_color = edid[index+6];
269 if ((IEEE_reg_iden[0] == 0x03) &&
270 (IEEE_reg_iden[1] == 0x0c) &&
271 (IEEE_reg_iden[2] == 0x00))
274 if (deep_color & 0x40)
275 cfg->vsd_dc_48bit = true;
276 if (deep_color & 0x20)
277 cfg->vsd_dc_36bit = true;
278 if (deep_color & 0x10)
279 cfg->vsd_dc_30bit = true;
280 if (deep_color & 0x08)
281 cfg->vsd_dc_y444 = true;
282 if (deep_color & 0x01)
283 cfg->vsd_dvi_dual = true;
285 DPRINTK("VSD hdmi capability %d\n", cfg->hdmi_cap);
286 DPRINTK("VSD support deep color 48bit %d\n", cfg->vsd_dc_48bit);
287 DPRINTK("VSD support deep color 36bit %d\n", cfg->vsd_dc_36bit);
288 DPRINTK("VSD support deep color 30bit %d\n", cfg->vsd_dc_30bit);
289 DPRINTK("VSD support deep color y444 %d\n", cfg->vsd_dc_y444);
290 DPRINTK("VSD support dvi dual %d\n", cfg->vsd_dvi_dual);
295 case 0x1: /*Audio data block*/
296 case 0x4: /*Speaker allocation block*/
297 case 0x7: /*User extended block*/
309 DPRINTK("CEA long desc timmings\n");
310 index = detail_timing_desc_offset;
311 block = edid + index;
312 while (index < (EDID_LENGTH - DETAILED_TIMING_DESCRIPTION_SIZE)) {
313 if (!(block[0] == 0x00 && block[1] == 0x00)) {
314 get_detailed_timing(block, &mode[num]);
317 block += DETAILED_TIMING_DESCRIPTION_SIZE;
318 index += DETAILED_TIMING_DESCRIPTION_SIZE;
326 m = kmalloc((num + specs->modedb_len) *
327 sizeof(struct fb_videomode), GFP_KERNEL);
331 if (specs->modedb_len) {
332 memmove(m, specs->modedb,
333 specs->modedb_len * sizeof(struct fb_videomode));
334 kfree(specs->modedb);
336 memmove(m+specs->modedb_len, mode,
337 num * sizeof(struct fb_videomode));
340 specs->modedb_len += num;
346 static int mxc_edid_readblk(struct i2c_adapter *adp,
347 unsigned short addr, unsigned char *edid)
349 int ret = 0, extblknum = 0;
350 unsigned char regaddr = 0x0;
351 struct i2c_msg msg[2] = {
365 ret = i2c_transfer(adp, msg, ARRAY_SIZE(msg));
366 if (ret != ARRAY_SIZE(msg)) {
367 DPRINTK("unable to read EDID block\n");
374 extblknum = edid[0x7E];
378 msg[1].buf = edid + EDID_LENGTH;
380 ret = i2c_transfer(adp, msg, ARRAY_SIZE(msg));
381 if (ret != ARRAY_SIZE(msg)) {
382 DPRINTK("unable to read EDID ext block\n");
390 static int mxc_edid_readsegblk(struct i2c_adapter *adp, unsigned short addr,
391 unsigned char *edid, int seg_num)
394 unsigned char segment = 0x1, regaddr = 0;
395 struct i2c_msg msg[3] = {
414 ret = i2c_transfer(adp, msg, ARRAY_SIZE(msg));
415 if (ret != ARRAY_SIZE(msg)) {
416 DPRINTK("unable to read EDID block\n");
422 msg[2].buf = edid + EDID_LENGTH;
424 ret = i2c_transfer(adp, msg, ARRAY_SIZE(msg));
425 if (ret != ARRAY_SIZE(msg)) {
426 DPRINTK("unable to read EDID block\n");
434 int mxc_edid_var_to_vic(struct fb_var_screeninfo *var)
437 struct fb_videomode m;
439 for (i = 0; i < ARRAY_SIZE(mxc_cea_mode); i++) {
440 fb_var_to_videomode(&m, var);
441 if (mxc_edid_fb_mode_is_equal(&m, &mxc_cea_mode[i]))
445 if (i == ARRAY_SIZE(mxc_cea_mode))
451 EXPORT_SYMBOL(mxc_edid_var_to_vic);
453 int mxc_edid_mode_to_vic(const struct fb_videomode *mode)
456 u32 aspect_flags = FB_MODE_ASPECT_16_9 | FB_MODE_ASPECT_4_3;
458 for (i = 0; i < ARRAY_SIZE(mxc_cea_mode); i++) {
459 if (mxc_edid_fb_mode_is_equal(mode, &mxc_cea_mode[i])) {
460 if (mode->flag & FB_MODE_IS_STANDARD) {
461 if ((mode->flag & aspect_flags) ==
462 mxc_cea_mode[i].flag)
469 if (i == ARRAY_SIZE(mxc_cea_mode))
474 EXPORT_SYMBOL(mxc_edid_mode_to_vic);
476 /* make sure edid has 512 bytes*/
477 int mxc_edid_read(struct i2c_adapter *adp, unsigned short addr,
478 unsigned char *edid, struct mxc_edid_cfg *cfg, struct fb_info *fbi)
480 int ret = 0, extblknum;
481 if (!adp || !edid || !cfg || !fbi)
484 memset(edid, 0, EDID_LENGTH*4);
485 memset(cfg, 0, sizeof(struct mxc_edid_cfg));
487 extblknum = mxc_edid_readblk(adp, addr, edid);
491 /* edid first block parsing */
492 memset(&fbi->monspecs, 0, sizeof(fbi->monspecs));
493 fb_edid_to_monspecs(edid, &fbi->monspecs);
498 /* need read segment block? */
500 ret = mxc_edid_readsegblk(adp, addr,
501 edid + EDID_LENGTH*2, extblknum - 1);
506 for (i = 1; i <= extblknum; i++)
507 /* edid ext block parsing */
508 mxc_edid_parse_ext_blk(edid + i*EDID_LENGTH,
509 cfg, &fbi->monspecs);
514 EXPORT_SYMBOL(mxc_edid_read);