diff options
Diffstat (limited to 'drivers/video/omap2/dss/hdmi.c')
-rw-r--r-- | drivers/video/omap2/dss/hdmi.c | 1260 |
1 files changed, 144 insertions, 1116 deletions
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c index 256f27a9064a..3262f0f1fa35 100644 --- a/drivers/video/omap2/dss/hdmi.c +++ b/drivers/video/omap2/dss/hdmi.c | |||
@@ -37,26 +37,41 @@ | |||
37 | defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE) | 37 | defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE) |
38 | #include <sound/soc.h> | 38 | #include <sound/soc.h> |
39 | #include <sound/pcm_params.h> | 39 | #include <sound/pcm_params.h> |
40 | #include "ti_hdmi_4xxx_ip.h" | ||
40 | #endif | 41 | #endif |
41 | 42 | ||
43 | #include "ti_hdmi.h" | ||
42 | #include "dss.h" | 44 | #include "dss.h" |
43 | #include "hdmi.h" | ||
44 | #include "dss_features.h" | 45 | #include "dss_features.h" |
45 | 46 | ||
47 | #define HDMI_WP 0x0 | ||
48 | #define HDMI_CORE_SYS 0x400 | ||
49 | #define HDMI_CORE_AV 0x900 | ||
50 | #define HDMI_PLLCTRL 0x200 | ||
51 | #define HDMI_PHY 0x300 | ||
52 | |||
53 | /* HDMI EDID Length move this */ | ||
54 | #define HDMI_EDID_MAX_LENGTH 256 | ||
55 | #define EDID_TIMING_DESCRIPTOR_SIZE 0x12 | ||
56 | #define EDID_DESCRIPTOR_BLOCK0_ADDRESS 0x36 | ||
57 | #define EDID_DESCRIPTOR_BLOCK1_ADDRESS 0x80 | ||
58 | #define EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR 4 | ||
59 | #define EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR 4 | ||
60 | |||
61 | #define OMAP_HDMI_TIMINGS_NB 34 | ||
62 | |||
63 | #define HDMI_DEFAULT_REGN 16 | ||
64 | #define HDMI_DEFAULT_REGM2 1 | ||
65 | |||
46 | static struct { | 66 | static struct { |
47 | struct mutex lock; | 67 | struct mutex lock; |
48 | struct omap_display_platform_data *pdata; | 68 | struct omap_display_platform_data *pdata; |
49 | struct platform_device *pdev; | 69 | struct platform_device *pdev; |
50 | void __iomem *base_wp; /* HDMI wrapper */ | 70 | struct hdmi_ip_data ip_data; |
51 | int code; | 71 | int code; |
52 | int mode; | 72 | int mode; |
53 | u8 edid[HDMI_EDID_MAX_LENGTH]; | ||
54 | u8 edid_set; | ||
55 | bool custom_set; | ||
56 | struct hdmi_config cfg; | ||
57 | 73 | ||
58 | struct clk *sys_clk; | 74 | struct clk *sys_clk; |
59 | struct clk *hdmi_clk; | ||
60 | } hdmi; | 75 | } hdmi; |
61 | 76 | ||
62 | /* | 77 | /* |
@@ -144,30 +159,6 @@ static const int code_vesa[85] = { | |||
144 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | 159 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
145 | -1, 27, 28, -1, 33}; | 160 | -1, 27, 28, -1, 33}; |
146 | 161 | ||
147 | static const u8 edid_header[8] = {0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0}; | ||
148 | |||
149 | static inline void hdmi_write_reg(const struct hdmi_reg idx, u32 val) | ||
150 | { | ||
151 | __raw_writel(val, hdmi.base_wp + idx.idx); | ||
152 | } | ||
153 | |||
154 | static inline u32 hdmi_read_reg(const struct hdmi_reg idx) | ||
155 | { | ||
156 | return __raw_readl(hdmi.base_wp + idx.idx); | ||
157 | } | ||
158 | |||
159 | static inline int hdmi_wait_for_bit_change(const struct hdmi_reg idx, | ||
160 | int b2, int b1, u32 val) | ||
161 | { | ||
162 | u32 t = 0; | ||
163 | while (val != REG_GET(idx, b2, b1)) { | ||
164 | udelay(1); | ||
165 | if (t++ > 10000) | ||
166 | return !val; | ||
167 | } | ||
168 | return val; | ||
169 | } | ||
170 | |||
171 | static int hdmi_runtime_get(void) | 162 | static int hdmi_runtime_get(void) |
172 | { | 163 | { |
173 | int r; | 164 | int r; |
@@ -193,304 +184,7 @@ int hdmi_init_display(struct omap_dss_device *dssdev) | |||
193 | { | 184 | { |
194 | DSSDBG("init_display\n"); | 185 | DSSDBG("init_display\n"); |
195 | 186 | ||
196 | return 0; | 187 | dss_init_hdmi_ip_ops(&hdmi.ip_data); |
197 | } | ||
198 | |||
199 | static int hdmi_pll_init(enum hdmi_clk_refsel refsel, int dcofreq, | ||
200 | struct hdmi_pll_info *fmt, u16 sd) | ||
201 | { | ||
202 | u32 r; | ||
203 | |||
204 | /* PLL start always use manual mode */ | ||
205 | REG_FLD_MOD(PLLCTRL_PLL_CONTROL, 0x0, 0, 0); | ||
206 | |||
207 | r = hdmi_read_reg(PLLCTRL_CFG1); | ||
208 | r = FLD_MOD(r, fmt->regm, 20, 9); /* CFG1_PLL_REGM */ | ||
209 | r = FLD_MOD(r, fmt->regn, 8, 1); /* CFG1_PLL_REGN */ | ||
210 | |||
211 | hdmi_write_reg(PLLCTRL_CFG1, r); | ||
212 | |||
213 | r = hdmi_read_reg(PLLCTRL_CFG2); | ||
214 | |||
215 | r = FLD_MOD(r, 0x0, 12, 12); /* PLL_HIGHFREQ divide by 2 */ | ||
216 | r = FLD_MOD(r, 0x1, 13, 13); /* PLL_REFEN */ | ||
217 | r = FLD_MOD(r, 0x0, 14, 14); /* PHY_CLKINEN de-assert during locking */ | ||
218 | |||
219 | if (dcofreq) { | ||
220 | /* divider programming for frequency beyond 1000Mhz */ | ||
221 | REG_FLD_MOD(PLLCTRL_CFG3, sd, 17, 10); | ||
222 | r = FLD_MOD(r, 0x4, 3, 1); /* 1000MHz and 2000MHz */ | ||
223 | } else { | ||
224 | r = FLD_MOD(r, 0x2, 3, 1); /* 500MHz and 1000MHz */ | ||
225 | } | ||
226 | |||
227 | hdmi_write_reg(PLLCTRL_CFG2, r); | ||
228 | |||
229 | r = hdmi_read_reg(PLLCTRL_CFG4); | ||
230 | r = FLD_MOD(r, fmt->regm2, 24, 18); | ||
231 | r = FLD_MOD(r, fmt->regmf, 17, 0); | ||
232 | |||
233 | hdmi_write_reg(PLLCTRL_CFG4, r); | ||
234 | |||
235 | /* go now */ | ||
236 | REG_FLD_MOD(PLLCTRL_PLL_GO, 0x1, 0, 0); | ||
237 | |||
238 | /* wait for bit change */ | ||
239 | if (hdmi_wait_for_bit_change(PLLCTRL_PLL_GO, 0, 0, 1) != 1) { | ||
240 | DSSERR("PLL GO bit not set\n"); | ||
241 | return -ETIMEDOUT; | ||
242 | } | ||
243 | |||
244 | /* Wait till the lock bit is set in PLL status */ | ||
245 | if (hdmi_wait_for_bit_change(PLLCTRL_PLL_STATUS, 1, 1, 1) != 1) { | ||
246 | DSSWARN("cannot lock PLL\n"); | ||
247 | DSSWARN("CFG1 0x%x\n", | ||
248 | hdmi_read_reg(PLLCTRL_CFG1)); | ||
249 | DSSWARN("CFG2 0x%x\n", | ||
250 | hdmi_read_reg(PLLCTRL_CFG2)); | ||
251 | DSSWARN("CFG4 0x%x\n", | ||
252 | hdmi_read_reg(PLLCTRL_CFG4)); | ||
253 | return -ETIMEDOUT; | ||
254 | } | ||
255 | |||
256 | DSSDBG("PLL locked!\n"); | ||
257 | |||
258 | return 0; | ||
259 | } | ||
260 | |||
261 | /* PHY_PWR_CMD */ | ||
262 | static int hdmi_set_phy_pwr(enum hdmi_phy_pwr val) | ||
263 | { | ||
264 | /* Command for power control of HDMI PHY */ | ||
265 | REG_FLD_MOD(HDMI_WP_PWR_CTRL, val, 7, 6); | ||
266 | |||
267 | /* Status of the power control of HDMI PHY */ | ||
268 | if (hdmi_wait_for_bit_change(HDMI_WP_PWR_CTRL, 5, 4, val) != val) { | ||
269 | DSSERR("Failed to set PHY power mode to %d\n", val); | ||
270 | return -ETIMEDOUT; | ||
271 | } | ||
272 | |||
273 | return 0; | ||
274 | } | ||
275 | |||
276 | /* PLL_PWR_CMD */ | ||
277 | static int hdmi_set_pll_pwr(enum hdmi_pll_pwr val) | ||
278 | { | ||
279 | /* Command for power control of HDMI PLL */ | ||
280 | REG_FLD_MOD(HDMI_WP_PWR_CTRL, val, 3, 2); | ||
281 | |||
282 | /* wait till PHY_PWR_STATUS is set */ | ||
283 | if (hdmi_wait_for_bit_change(HDMI_WP_PWR_CTRL, 1, 0, val) != val) { | ||
284 | DSSERR("Failed to set PHY_PWR_STATUS\n"); | ||
285 | return -ETIMEDOUT; | ||
286 | } | ||
287 | |||
288 | return 0; | ||
289 | } | ||
290 | |||
291 | static int hdmi_pll_reset(void) | ||
292 | { | ||
293 | /* SYSRESET controlled by power FSM */ | ||
294 | REG_FLD_MOD(PLLCTRL_PLL_CONTROL, 0x0, 3, 3); | ||
295 | |||
296 | /* READ 0x0 reset is in progress */ | ||
297 | if (hdmi_wait_for_bit_change(PLLCTRL_PLL_STATUS, 0, 0, 1) != 1) { | ||
298 | DSSERR("Failed to sysreset PLL\n"); | ||
299 | return -ETIMEDOUT; | ||
300 | } | ||
301 | |||
302 | return 0; | ||
303 | } | ||
304 | |||
305 | static int hdmi_phy_init(void) | ||
306 | { | ||
307 | u16 r = 0; | ||
308 | |||
309 | r = hdmi_set_phy_pwr(HDMI_PHYPWRCMD_LDOON); | ||
310 | if (r) | ||
311 | return r; | ||
312 | |||
313 | r = hdmi_set_phy_pwr(HDMI_PHYPWRCMD_TXON); | ||
314 | if (r) | ||
315 | return r; | ||
316 | |||
317 | /* | ||
318 | * Read address 0 in order to get the SCP reset done completed | ||
319 | * Dummy access performed to make sure reset is done | ||
320 | */ | ||
321 | hdmi_read_reg(HDMI_TXPHY_TX_CTRL); | ||
322 | |||
323 | /* | ||
324 | * Write to phy address 0 to configure the clock | ||
325 | * use HFBITCLK write HDMI_TXPHY_TX_CONTROL_FREQOUT field | ||
326 | */ | ||
327 | REG_FLD_MOD(HDMI_TXPHY_TX_CTRL, 0x1, 31, 30); | ||
328 | |||
329 | /* Write to phy address 1 to start HDMI line (TXVALID and TMDSCLKEN) */ | ||
330 | hdmi_write_reg(HDMI_TXPHY_DIGITAL_CTRL, 0xF0000000); | ||
331 | |||
332 | /* Setup max LDO voltage */ | ||
333 | REG_FLD_MOD(HDMI_TXPHY_POWER_CTRL, 0xB, 3, 0); | ||
334 | |||
335 | /* Write to phy address 3 to change the polarity control */ | ||
336 | REG_FLD_MOD(HDMI_TXPHY_PAD_CFG_CTRL, 0x1, 27, 27); | ||
337 | |||
338 | return 0; | ||
339 | } | ||
340 | |||
341 | static int hdmi_pll_program(struct hdmi_pll_info *fmt) | ||
342 | { | ||
343 | u16 r = 0; | ||
344 | enum hdmi_clk_refsel refsel; | ||
345 | |||
346 | r = hdmi_set_pll_pwr(HDMI_PLLPWRCMD_ALLOFF); | ||
347 | if (r) | ||
348 | return r; | ||
349 | |||
350 | r = hdmi_set_pll_pwr(HDMI_PLLPWRCMD_BOTHON_ALLCLKS); | ||
351 | if (r) | ||
352 | return r; | ||
353 | |||
354 | r = hdmi_pll_reset(); | ||
355 | if (r) | ||
356 | return r; | ||
357 | |||
358 | refsel = HDMI_REFSEL_SYSCLK; | ||
359 | |||
360 | r = hdmi_pll_init(refsel, fmt->dcofreq, fmt, fmt->regsd); | ||
361 | if (r) | ||
362 | return r; | ||
363 | |||
364 | return 0; | ||
365 | } | ||
366 | |||
367 | static void hdmi_phy_off(void) | ||
368 | { | ||
369 | hdmi_set_phy_pwr(HDMI_PHYPWRCMD_OFF); | ||
370 | } | ||
371 | |||
372 | static int hdmi_core_ddc_edid(u8 *pedid, int ext) | ||
373 | { | ||
374 | u32 i, j; | ||
375 | char checksum = 0; | ||
376 | u32 offset = 0; | ||
377 | |||
378 | /* Turn on CLK for DDC */ | ||
379 | REG_FLD_MOD(HDMI_CORE_AV_DPD, 0x7, 2, 0); | ||
380 | |||
381 | /* | ||
382 | * SW HACK : Without the Delay DDC(i2c bus) reads 0 values / | ||
383 | * right shifted values( The behavior is not consistent and seen only | ||
384 | * with some TV's) | ||
385 | */ | ||
386 | usleep_range(800, 1000); | ||
387 | |||
388 | if (!ext) { | ||
389 | /* Clk SCL Devices */ | ||
390 | REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0xA, 3, 0); | ||
391 | |||
392 | /* HDMI_CORE_DDC_STATUS_IN_PROG */ | ||
393 | if (hdmi_wait_for_bit_change(HDMI_CORE_DDC_STATUS, | ||
394 | 4, 4, 0) != 0) { | ||
395 | DSSERR("Failed to program DDC\n"); | ||
396 | return -ETIMEDOUT; | ||
397 | } | ||
398 | |||
399 | /* Clear FIFO */ | ||
400 | REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0x9, 3, 0); | ||
401 | |||
402 | /* HDMI_CORE_DDC_STATUS_IN_PROG */ | ||
403 | if (hdmi_wait_for_bit_change(HDMI_CORE_DDC_STATUS, | ||
404 | 4, 4, 0) != 0) { | ||
405 | DSSERR("Failed to program DDC\n"); | ||
406 | return -ETIMEDOUT; | ||
407 | } | ||
408 | |||
409 | } else { | ||
410 | if (ext % 2 != 0) | ||
411 | offset = 0x80; | ||
412 | } | ||
413 | |||
414 | /* Load Segment Address Register */ | ||
415 | REG_FLD_MOD(HDMI_CORE_DDC_SEGM, ext/2, 7, 0); | ||
416 | |||
417 | /* Load Slave Address Register */ | ||
418 | REG_FLD_MOD(HDMI_CORE_DDC_ADDR, 0xA0 >> 1, 7, 1); | ||
419 | |||
420 | /* Load Offset Address Register */ | ||
421 | REG_FLD_MOD(HDMI_CORE_DDC_OFFSET, offset, 7, 0); | ||
422 | |||
423 | /* Load Byte Count */ | ||
424 | REG_FLD_MOD(HDMI_CORE_DDC_COUNT1, 0x80, 7, 0); | ||
425 | REG_FLD_MOD(HDMI_CORE_DDC_COUNT2, 0x0, 1, 0); | ||
426 | |||
427 | /* Set DDC_CMD */ | ||
428 | if (ext) | ||
429 | REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0x4, 3, 0); | ||
430 | else | ||
431 | REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0x2, 3, 0); | ||
432 | |||
433 | /* HDMI_CORE_DDC_STATUS_BUS_LOW */ | ||
434 | if (REG_GET(HDMI_CORE_DDC_STATUS, 6, 6) == 1) { | ||
435 | DSSWARN("I2C Bus Low?\n"); | ||
436 | return -EIO; | ||
437 | } | ||
438 | /* HDMI_CORE_DDC_STATUS_NO_ACK */ | ||
439 | if (REG_GET(HDMI_CORE_DDC_STATUS, 5, 5) == 1) { | ||
440 | DSSWARN("I2C No Ack\n"); | ||
441 | return -EIO; | ||
442 | } | ||
443 | |||
444 | i = ext * 128; | ||
445 | j = 0; | ||
446 | while (((REG_GET(HDMI_CORE_DDC_STATUS, 4, 4) == 1) || | ||
447 | (REG_GET(HDMI_CORE_DDC_STATUS, 2, 2) == 0)) && | ||
448 | j < 128) { | ||
449 | |||
450 | if (REG_GET(HDMI_CORE_DDC_STATUS, 2, 2) == 0) { | ||
451 | /* FIFO not empty */ | ||
452 | pedid[i++] = REG_GET(HDMI_CORE_DDC_DATA, 7, 0); | ||
453 | j++; | ||
454 | } | ||
455 | } | ||
456 | |||
457 | for (j = 0; j < 128; j++) | ||
458 | checksum += pedid[j]; | ||
459 | |||
460 | if (checksum != 0) { | ||
461 | DSSERR("E-EDID checksum failed!!\n"); | ||
462 | return -EIO; | ||
463 | } | ||
464 | |||
465 | return 0; | ||
466 | } | ||
467 | |||
468 | static int read_edid(u8 *pedid, u16 max_length) | ||
469 | { | ||
470 | int r = 0, n = 0, i = 0; | ||
471 | int max_ext_blocks = (max_length / 128) - 1; | ||
472 | |||
473 | r = hdmi_core_ddc_edid(pedid, 0); | ||
474 | if (r) { | ||
475 | return r; | ||
476 | } else { | ||
477 | n = pedid[0x7e]; | ||
478 | |||
479 | /* | ||
480 | * README: need to comply with max_length set by the caller. | ||
481 | * Better implementation should be to allocate necessary | ||
482 | * memory to store EDID according to nb_block field found | ||
483 | * in first block | ||
484 | */ | ||
485 | if (n > max_ext_blocks) | ||
486 | n = max_ext_blocks; | ||
487 | |||
488 | for (i = 1; i <= n; i++) { | ||
489 | r = hdmi_core_ddc_edid(pedid, i); | ||
490 | if (r) | ||
491 | return r; | ||
492 | } | ||
493 | } | ||
494 | return 0; | 188 | return 0; |
495 | } | 189 | } |
496 | 190 | ||
@@ -518,7 +212,7 @@ static struct hdmi_cm hdmi_get_code(struct omap_video_timings *timing) | |||
518 | { | 212 | { |
519 | int i = 0, code = -1, temp_vsync = 0, temp_hsync = 0; | 213 | int i = 0, code = -1, temp_vsync = 0, temp_hsync = 0; |
520 | int timing_vsync = 0, timing_hsync = 0; | 214 | int timing_vsync = 0, timing_hsync = 0; |
521 | struct omap_video_timings temp; | 215 | struct hdmi_video_timings temp; |
522 | struct hdmi_cm cm = {-1}; | 216 | struct hdmi_cm cm = {-1}; |
523 | DSSDBG("hdmi_get_code\n"); | 217 | DSSDBG("hdmi_get_code\n"); |
524 | 218 | ||
@@ -556,500 +250,6 @@ static struct hdmi_cm hdmi_get_code(struct omap_video_timings *timing) | |||
556 | return cm; | 250 | return cm; |
557 | } | 251 | } |
558 | 252 | ||
559 | static void get_horz_vert_timing_info(int current_descriptor_addrs, u8 *edid , | ||
560 | struct omap_video_timings *timings) | ||
561 | { | ||
562 | /* X and Y resolution */ | ||
563 | timings->x_res = (((edid[current_descriptor_addrs + 4] & 0xF0) << 4) | | ||
564 | edid[current_descriptor_addrs + 2]); | ||
565 | timings->y_res = (((edid[current_descriptor_addrs + 7] & 0xF0) << 4) | | ||
566 | edid[current_descriptor_addrs + 5]); | ||
567 | |||
568 | timings->pixel_clock = ((edid[current_descriptor_addrs + 1] << 8) | | ||
569 | edid[current_descriptor_addrs]); | ||
570 | |||
571 | timings->pixel_clock = 10 * timings->pixel_clock; | ||
572 | |||
573 | /* HORIZONTAL FRONT PORCH */ | ||
574 | timings->hfp = edid[current_descriptor_addrs + 8] | | ||
575 | ((edid[current_descriptor_addrs + 11] & 0xc0) << 2); | ||
576 | /* HORIZONTAL SYNC WIDTH */ | ||
577 | timings->hsw = edid[current_descriptor_addrs + 9] | | ||
578 | ((edid[current_descriptor_addrs + 11] & 0x30) << 4); | ||
579 | /* HORIZONTAL BACK PORCH */ | ||
580 | timings->hbp = (((edid[current_descriptor_addrs + 4] & 0x0F) << 8) | | ||
581 | edid[current_descriptor_addrs + 3]) - | ||
582 | (timings->hfp + timings->hsw); | ||
583 | /* VERTICAL FRONT PORCH */ | ||
584 | timings->vfp = ((edid[current_descriptor_addrs + 10] & 0xF0) >> 4) | | ||
585 | ((edid[current_descriptor_addrs + 11] & 0x0f) << 2); | ||
586 | /* VERTICAL SYNC WIDTH */ | ||
587 | timings->vsw = (edid[current_descriptor_addrs + 10] & 0x0F) | | ||
588 | ((edid[current_descriptor_addrs + 11] & 0x03) << 4); | ||
589 | /* VERTICAL BACK PORCH */ | ||
590 | timings->vbp = (((edid[current_descriptor_addrs + 7] & 0x0F) << 8) | | ||
591 | edid[current_descriptor_addrs + 6]) - | ||
592 | (timings->vfp + timings->vsw); | ||
593 | |||
594 | } | ||
595 | |||
596 | /* Description : This function gets the resolution information from EDID */ | ||
597 | static void get_edid_timing_data(u8 *edid) | ||
598 | { | ||
599 | u8 count; | ||
600 | u16 current_descriptor_addrs; | ||
601 | struct hdmi_cm cm; | ||
602 | struct omap_video_timings edid_timings; | ||
603 | |||
604 | /* search block 0, there are 4 DTDs arranged in priority order */ | ||
605 | for (count = 0; count < EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR; count++) { | ||
606 | current_descriptor_addrs = | ||
607 | EDID_DESCRIPTOR_BLOCK0_ADDRESS + | ||
608 | count * EDID_TIMING_DESCRIPTOR_SIZE; | ||
609 | get_horz_vert_timing_info(current_descriptor_addrs, | ||
610 | edid, &edid_timings); | ||
611 | cm = hdmi_get_code(&edid_timings); | ||
612 | DSSDBG("Block0[%d] value matches code = %d , mode = %d\n", | ||
613 | count, cm.code, cm.mode); | ||
614 | if (cm.code == -1) { | ||
615 | continue; | ||
616 | } else { | ||
617 | hdmi.code = cm.code; | ||
618 | hdmi.mode = cm.mode; | ||
619 | DSSDBG("code = %d , mode = %d\n", | ||
620 | hdmi.code, hdmi.mode); | ||
621 | return; | ||
622 | } | ||
623 | } | ||
624 | if (edid[0x7e] != 0x00) { | ||
625 | for (count = 0; count < EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR; | ||
626 | count++) { | ||
627 | current_descriptor_addrs = | ||
628 | EDID_DESCRIPTOR_BLOCK1_ADDRESS + | ||
629 | count * EDID_TIMING_DESCRIPTOR_SIZE; | ||
630 | get_horz_vert_timing_info(current_descriptor_addrs, | ||
631 | edid, &edid_timings); | ||
632 | cm = hdmi_get_code(&edid_timings); | ||
633 | DSSDBG("Block1[%d] value matches code = %d, mode = %d", | ||
634 | count, cm.code, cm.mode); | ||
635 | if (cm.code == -1) { | ||
636 | continue; | ||
637 | } else { | ||
638 | hdmi.code = cm.code; | ||
639 | hdmi.mode = cm.mode; | ||
640 | DSSDBG("code = %d , mode = %d\n", | ||
641 | hdmi.code, hdmi.mode); | ||
642 | return; | ||
643 | } | ||
644 | } | ||
645 | } | ||
646 | |||
647 | DSSINFO("no valid timing found , falling back to VGA\n"); | ||
648 | hdmi.code = 4; /* setting default value of 640 480 VGA */ | ||
649 | hdmi.mode = HDMI_DVI; | ||
650 | } | ||
651 | |||
652 | static void hdmi_read_edid(struct omap_video_timings *dp) | ||
653 | { | ||
654 | int ret = 0, code; | ||
655 | |||
656 | memset(hdmi.edid, 0, HDMI_EDID_MAX_LENGTH); | ||
657 | |||
658 | if (!hdmi.edid_set) | ||
659 | ret = read_edid(hdmi.edid, HDMI_EDID_MAX_LENGTH); | ||
660 | |||
661 | if (!ret) { | ||
662 | if (!memcmp(hdmi.edid, edid_header, sizeof(edid_header))) { | ||
663 | /* search for timings of default resolution */ | ||
664 | get_edid_timing_data(hdmi.edid); | ||
665 | hdmi.edid_set = true; | ||
666 | } | ||
667 | } else { | ||
668 | DSSWARN("failed to read E-EDID\n"); | ||
669 | } | ||
670 | |||
671 | if (!hdmi.edid_set) { | ||
672 | DSSINFO("fallback to VGA\n"); | ||
673 | hdmi.code = 4; /* setting default value of 640 480 VGA */ | ||
674 | hdmi.mode = HDMI_DVI; | ||
675 | } | ||
676 | |||
677 | code = get_timings_index(); | ||
678 | |||
679 | *dp = cea_vesa_timings[code].timings; | ||
680 | } | ||
681 | |||
682 | static void hdmi_core_init(struct hdmi_core_video_config *video_cfg, | ||
683 | struct hdmi_core_infoframe_avi *avi_cfg, | ||
684 | struct hdmi_core_packet_enable_repeat *repeat_cfg) | ||
685 | { | ||
686 | DSSDBG("Enter hdmi_core_init\n"); | ||
687 | |||
688 | /* video core */ | ||
689 | video_cfg->ip_bus_width = HDMI_INPUT_8BIT; | ||
690 | video_cfg->op_dither_truc = HDMI_OUTPUTTRUNCATION_8BIT; | ||
691 | video_cfg->deep_color_pkt = HDMI_DEEPCOLORPACKECTDISABLE; | ||
692 | video_cfg->pkt_mode = HDMI_PACKETMODERESERVEDVALUE; | ||
693 | video_cfg->hdmi_dvi = HDMI_DVI; | ||
694 | video_cfg->tclk_sel_clkmult = HDMI_FPLL10IDCK; | ||
695 | |||
696 | /* info frame */ | ||
697 | avi_cfg->db1_format = 0; | ||
698 | avi_cfg->db1_active_info = 0; | ||
699 | avi_cfg->db1_bar_info_dv = 0; | ||
700 | avi_cfg->db1_scan_info = 0; | ||
701 | avi_cfg->db2_colorimetry = 0; | ||
702 | avi_cfg->db2_aspect_ratio = 0; | ||
703 | avi_cfg->db2_active_fmt_ar = 0; | ||
704 | avi_cfg->db3_itc = 0; | ||
705 | avi_cfg->db3_ec = 0; | ||
706 | avi_cfg->db3_q_range = 0; | ||
707 | avi_cfg->db3_nup_scaling = 0; | ||
708 | avi_cfg->db4_videocode = 0; | ||
709 | avi_cfg->db5_pixel_repeat = 0; | ||
710 | avi_cfg->db6_7_line_eoftop = 0 ; | ||
711 | avi_cfg->db8_9_line_sofbottom = 0; | ||
712 | avi_cfg->db10_11_pixel_eofleft = 0; | ||
713 | avi_cfg->db12_13_pixel_sofright = 0; | ||
714 | |||
715 | /* packet enable and repeat */ | ||
716 | repeat_cfg->audio_pkt = 0; | ||
717 | repeat_cfg->audio_pkt_repeat = 0; | ||
718 | repeat_cfg->avi_infoframe = 0; | ||
719 | repeat_cfg->avi_infoframe_repeat = 0; | ||
720 | repeat_cfg->gen_cntrl_pkt = 0; | ||
721 | repeat_cfg->gen_cntrl_pkt_repeat = 0; | ||
722 | repeat_cfg->generic_pkt = 0; | ||
723 | repeat_cfg->generic_pkt_repeat = 0; | ||
724 | } | ||
725 | |||
726 | static void hdmi_core_powerdown_disable(void) | ||
727 | { | ||
728 | DSSDBG("Enter hdmi_core_powerdown_disable\n"); | ||
729 | REG_FLD_MOD(HDMI_CORE_CTRL1, 0x0, 0, 0); | ||
730 | } | ||
731 | |||
732 | static void hdmi_core_swreset_release(void) | ||
733 | { | ||
734 | DSSDBG("Enter hdmi_core_swreset_release\n"); | ||
735 | REG_FLD_MOD(HDMI_CORE_SYS_SRST, 0x0, 0, 0); | ||
736 | } | ||
737 | |||
738 | static void hdmi_core_swreset_assert(void) | ||
739 | { | ||
740 | DSSDBG("Enter hdmi_core_swreset_assert\n"); | ||
741 | REG_FLD_MOD(HDMI_CORE_SYS_SRST, 0x1, 0, 0); | ||
742 | } | ||
743 | |||
744 | /* DSS_HDMI_CORE_VIDEO_CONFIG */ | ||
745 | static void hdmi_core_video_config(struct hdmi_core_video_config *cfg) | ||
746 | { | ||
747 | u32 r = 0; | ||
748 | |||
749 | /* sys_ctrl1 default configuration not tunable */ | ||
750 | r = hdmi_read_reg(HDMI_CORE_CTRL1); | ||
751 | r = FLD_MOD(r, HDMI_CORE_CTRL1_VEN_FOLLOWVSYNC, 5, 5); | ||
752 | r = FLD_MOD(r, HDMI_CORE_CTRL1_HEN_FOLLOWHSYNC, 4, 4); | ||
753 | r = FLD_MOD(r, HDMI_CORE_CTRL1_BSEL_24BITBUS, 2, 2); | ||
754 | r = FLD_MOD(r, HDMI_CORE_CTRL1_EDGE_RISINGEDGE, 1, 1); | ||
755 | hdmi_write_reg(HDMI_CORE_CTRL1, r); | ||
756 | |||
757 | REG_FLD_MOD(HDMI_CORE_SYS_VID_ACEN, cfg->ip_bus_width, 7, 6); | ||
758 | |||
759 | /* Vid_Mode */ | ||
760 | r = hdmi_read_reg(HDMI_CORE_SYS_VID_MODE); | ||
761 | |||
762 | /* dither truncation configuration */ | ||
763 | if (cfg->op_dither_truc > HDMI_OUTPUTTRUNCATION_12BIT) { | ||
764 | r = FLD_MOD(r, cfg->op_dither_truc - 3, 7, 6); | ||
765 | r = FLD_MOD(r, 1, 5, 5); | ||
766 | } else { | ||
767 | r = FLD_MOD(r, cfg->op_dither_truc, 7, 6); | ||
768 | r = FLD_MOD(r, 0, 5, 5); | ||
769 | } | ||
770 | hdmi_write_reg(HDMI_CORE_SYS_VID_MODE, r); | ||
771 | |||
772 | /* HDMI_Ctrl */ | ||
773 | r = hdmi_read_reg(HDMI_CORE_AV_HDMI_CTRL); | ||
774 | r = FLD_MOD(r, cfg->deep_color_pkt, 6, 6); | ||
775 | r = FLD_MOD(r, cfg->pkt_mode, 5, 3); | ||
776 | r = FLD_MOD(r, cfg->hdmi_dvi, 0, 0); | ||
777 | hdmi_write_reg(HDMI_CORE_AV_HDMI_CTRL, r); | ||
778 | |||
779 | /* TMDS_CTRL */ | ||
780 | REG_FLD_MOD(HDMI_CORE_SYS_TMDS_CTRL, | ||
781 | cfg->tclk_sel_clkmult, 6, 5); | ||
782 | } | ||
783 | |||
784 | static void hdmi_core_aux_infoframe_avi_config( | ||
785 | struct hdmi_core_infoframe_avi info_avi) | ||
786 | { | ||
787 | u32 val; | ||
788 | char sum = 0, checksum = 0; | ||
789 | |||
790 | sum += 0x82 + 0x002 + 0x00D; | ||
791 | hdmi_write_reg(HDMI_CORE_AV_AVI_TYPE, 0x082); | ||
792 | hdmi_write_reg(HDMI_CORE_AV_AVI_VERS, 0x002); | ||
793 | hdmi_write_reg(HDMI_CORE_AV_AVI_LEN, 0x00D); | ||
794 | |||
795 | val = (info_avi.db1_format << 5) | | ||
796 | (info_avi.db1_active_info << 4) | | ||
797 | (info_avi.db1_bar_info_dv << 2) | | ||
798 | (info_avi.db1_scan_info); | ||
799 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(0), val); | ||
800 | sum += val; | ||
801 | |||
802 | val = (info_avi.db2_colorimetry << 6) | | ||
803 | (info_avi.db2_aspect_ratio << 4) | | ||
804 | (info_avi.db2_active_fmt_ar); | ||
805 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(1), val); | ||
806 | sum += val; | ||
807 | |||
808 | val = (info_avi.db3_itc << 7) | | ||
809 | (info_avi.db3_ec << 4) | | ||
810 | (info_avi.db3_q_range << 2) | | ||
811 | (info_avi.db3_nup_scaling); | ||
812 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(2), val); | ||
813 | sum += val; | ||
814 | |||
815 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(3), info_avi.db4_videocode); | ||
816 | sum += info_avi.db4_videocode; | ||
817 | |||
818 | val = info_avi.db5_pixel_repeat; | ||
819 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(4), val); | ||
820 | sum += val; | ||
821 | |||
822 | val = info_avi.db6_7_line_eoftop & 0x00FF; | ||
823 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(5), val); | ||
824 | sum += val; | ||
825 | |||
826 | val = ((info_avi.db6_7_line_eoftop >> 8) & 0x00FF); | ||
827 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(6), val); | ||
828 | sum += val; | ||
829 | |||
830 | val = info_avi.db8_9_line_sofbottom & 0x00FF; | ||
831 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(7), val); | ||
832 | sum += val; | ||
833 | |||
834 | val = ((info_avi.db8_9_line_sofbottom >> 8) & 0x00FF); | ||
835 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(8), val); | ||
836 | sum += val; | ||
837 | |||
838 | val = info_avi.db10_11_pixel_eofleft & 0x00FF; | ||
839 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(9), val); | ||
840 | sum += val; | ||
841 | |||
842 | val = ((info_avi.db10_11_pixel_eofleft >> 8) & 0x00FF); | ||
843 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(10), val); | ||
844 | sum += val; | ||
845 | |||
846 | val = info_avi.db12_13_pixel_sofright & 0x00FF; | ||
847 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(11), val); | ||
848 | sum += val; | ||
849 | |||
850 | val = ((info_avi.db12_13_pixel_sofright >> 8) & 0x00FF); | ||
851 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(12), val); | ||
852 | sum += val; | ||
853 | |||
854 | checksum = 0x100 - sum; | ||
855 | hdmi_write_reg(HDMI_CORE_AV_AVI_CHSUM, checksum); | ||
856 | } | ||
857 | |||
858 | static void hdmi_core_av_packet_config( | ||
859 | struct hdmi_core_packet_enable_repeat repeat_cfg) | ||
860 | { | ||
861 | /* enable/repeat the infoframe */ | ||
862 | hdmi_write_reg(HDMI_CORE_AV_PB_CTRL1, | ||
863 | (repeat_cfg.audio_pkt << 5) | | ||
864 | (repeat_cfg.audio_pkt_repeat << 4) | | ||
865 | (repeat_cfg.avi_infoframe << 1) | | ||
866 | (repeat_cfg.avi_infoframe_repeat)); | ||
867 | |||
868 | /* enable/repeat the packet */ | ||
869 | hdmi_write_reg(HDMI_CORE_AV_PB_CTRL2, | ||
870 | (repeat_cfg.gen_cntrl_pkt << 3) | | ||
871 | (repeat_cfg.gen_cntrl_pkt_repeat << 2) | | ||
872 | (repeat_cfg.generic_pkt << 1) | | ||
873 | (repeat_cfg.generic_pkt_repeat)); | ||
874 | } | ||
875 | |||
876 | static void hdmi_wp_init(struct omap_video_timings *timings, | ||
877 | struct hdmi_video_format *video_fmt, | ||
878 | struct hdmi_video_interface *video_int) | ||
879 | { | ||
880 | DSSDBG("Enter hdmi_wp_init\n"); | ||
881 | |||
882 | timings->hbp = 0; | ||
883 | timings->hfp = 0; | ||
884 | timings->hsw = 0; | ||
885 | timings->vbp = 0; | ||
886 | timings->vfp = 0; | ||
887 | timings->vsw = 0; | ||
888 | |||
889 | video_fmt->packing_mode = HDMI_PACK_10b_RGB_YUV444; | ||
890 | video_fmt->y_res = 0; | ||
891 | video_fmt->x_res = 0; | ||
892 | |||
893 | video_int->vsp = 0; | ||
894 | video_int->hsp = 0; | ||
895 | |||
896 | video_int->interlacing = 0; | ||
897 | video_int->tm = 0; /* HDMI_TIMING_SLAVE */ | ||
898 | |||
899 | } | ||
900 | |||
901 | static void hdmi_wp_video_start(bool start) | ||
902 | { | ||
903 | REG_FLD_MOD(HDMI_WP_VIDEO_CFG, start, 31, 31); | ||
904 | } | ||
905 | |||
906 | static void hdmi_wp_video_init_format(struct hdmi_video_format *video_fmt, | ||
907 | struct omap_video_timings *timings, struct hdmi_config *param) | ||
908 | { | ||
909 | DSSDBG("Enter hdmi_wp_video_init_format\n"); | ||
910 | |||
911 | video_fmt->y_res = param->timings.timings.y_res; | ||
912 | video_fmt->x_res = param->timings.timings.x_res; | ||
913 | |||
914 | timings->hbp = param->timings.timings.hbp; | ||
915 | timings->hfp = param->timings.timings.hfp; | ||
916 | timings->hsw = param->timings.timings.hsw; | ||
917 | timings->vbp = param->timings.timings.vbp; | ||
918 | timings->vfp = param->timings.timings.vfp; | ||
919 | timings->vsw = param->timings.timings.vsw; | ||
920 | } | ||
921 | |||
922 | static void hdmi_wp_video_config_format( | ||
923 | struct hdmi_video_format *video_fmt) | ||
924 | { | ||
925 | u32 l = 0; | ||
926 | |||
927 | REG_FLD_MOD(HDMI_WP_VIDEO_CFG, video_fmt->packing_mode, 10, 8); | ||
928 | |||
929 | l |= FLD_VAL(video_fmt->y_res, 31, 16); | ||
930 | l |= FLD_VAL(video_fmt->x_res, 15, 0); | ||
931 | hdmi_write_reg(HDMI_WP_VIDEO_SIZE, l); | ||
932 | } | ||
933 | |||
934 | static void hdmi_wp_video_config_interface( | ||
935 | struct hdmi_video_interface *video_int) | ||
936 | { | ||
937 | u32 r; | ||
938 | DSSDBG("Enter hdmi_wp_video_config_interface\n"); | ||
939 | |||
940 | r = hdmi_read_reg(HDMI_WP_VIDEO_CFG); | ||
941 | r = FLD_MOD(r, video_int->vsp, 7, 7); | ||
942 | r = FLD_MOD(r, video_int->hsp, 6, 6); | ||
943 | r = FLD_MOD(r, video_int->interlacing, 3, 3); | ||
944 | r = FLD_MOD(r, video_int->tm, 1, 0); | ||
945 | hdmi_write_reg(HDMI_WP_VIDEO_CFG, r); | ||
946 | } | ||
947 | |||
948 | static void hdmi_wp_video_config_timing( | ||
949 | struct omap_video_timings *timings) | ||
950 | { | ||
951 | u32 timing_h = 0; | ||
952 | u32 timing_v = 0; | ||
953 | |||
954 | DSSDBG("Enter hdmi_wp_video_config_timing\n"); | ||
955 | |||
956 | timing_h |= FLD_VAL(timings->hbp, 31, 20); | ||
957 | timing_h |= FLD_VAL(timings->hfp, 19, 8); | ||
958 | timing_h |= FLD_VAL(timings->hsw, 7, 0); | ||
959 | hdmi_write_reg(HDMI_WP_VIDEO_TIMING_H, timing_h); | ||
960 | |||
961 | timing_v |= FLD_VAL(timings->vbp, 31, 20); | ||
962 | timing_v |= FLD_VAL(timings->vfp, 19, 8); | ||
963 | timing_v |= FLD_VAL(timings->vsw, 7, 0); | ||
964 | hdmi_write_reg(HDMI_WP_VIDEO_TIMING_V, timing_v); | ||
965 | } | ||
966 | |||
967 | static void hdmi_basic_configure(struct hdmi_config *cfg) | ||
968 | { | ||
969 | /* HDMI */ | ||
970 | struct omap_video_timings video_timing; | ||
971 | struct hdmi_video_format video_format; | ||
972 | struct hdmi_video_interface video_interface; | ||
973 | /* HDMI core */ | ||
974 | struct hdmi_core_infoframe_avi avi_cfg; | ||
975 | struct hdmi_core_video_config v_core_cfg; | ||
976 | struct hdmi_core_packet_enable_repeat repeat_cfg; | ||
977 | |||
978 | hdmi_wp_init(&video_timing, &video_format, | ||
979 | &video_interface); | ||
980 | |||
981 | hdmi_core_init(&v_core_cfg, | ||
982 | &avi_cfg, | ||
983 | &repeat_cfg); | ||
984 | |||
985 | hdmi_wp_video_init_format(&video_format, | ||
986 | &video_timing, cfg); | ||
987 | |||
988 | hdmi_wp_video_config_timing(&video_timing); | ||
989 | |||
990 | /* video config */ | ||
991 | video_format.packing_mode = HDMI_PACK_24b_RGB_YUV444_YUV422; | ||
992 | |||
993 | hdmi_wp_video_config_format(&video_format); | ||
994 | |||
995 | video_interface.vsp = cfg->timings.vsync_pol; | ||
996 | video_interface.hsp = cfg->timings.hsync_pol; | ||
997 | video_interface.interlacing = cfg->interlace; | ||
998 | video_interface.tm = 1 ; /* HDMI_TIMING_MASTER_24BIT */ | ||
999 | |||
1000 | hdmi_wp_video_config_interface(&video_interface); | ||
1001 | |||
1002 | /* | ||
1003 | * configure core video part | ||
1004 | * set software reset in the core | ||
1005 | */ | ||
1006 | hdmi_core_swreset_assert(); | ||
1007 | |||
1008 | /* power down off */ | ||
1009 | hdmi_core_powerdown_disable(); | ||
1010 | |||
1011 | v_core_cfg.pkt_mode = HDMI_PACKETMODE24BITPERPIXEL; | ||
1012 | v_core_cfg.hdmi_dvi = cfg->cm.mode; | ||
1013 | |||
1014 | hdmi_core_video_config(&v_core_cfg); | ||
1015 | |||
1016 | /* release software reset in the core */ | ||
1017 | hdmi_core_swreset_release(); | ||
1018 | |||
1019 | /* | ||
1020 | * configure packet | ||
1021 | * info frame video see doc CEA861-D page 65 | ||
1022 | */ | ||
1023 | avi_cfg.db1_format = HDMI_INFOFRAME_AVI_DB1Y_RGB; | ||
1024 | avi_cfg.db1_active_info = | ||
1025 | HDMI_INFOFRAME_AVI_DB1A_ACTIVE_FORMAT_OFF; | ||
1026 | avi_cfg.db1_bar_info_dv = HDMI_INFOFRAME_AVI_DB1B_NO; | ||
1027 | avi_cfg.db1_scan_info = HDMI_INFOFRAME_AVI_DB1S_0; | ||
1028 | avi_cfg.db2_colorimetry = HDMI_INFOFRAME_AVI_DB2C_NO; | ||
1029 | avi_cfg.db2_aspect_ratio = HDMI_INFOFRAME_AVI_DB2M_NO; | ||
1030 | avi_cfg.db2_active_fmt_ar = HDMI_INFOFRAME_AVI_DB2R_SAME; | ||
1031 | avi_cfg.db3_itc = HDMI_INFOFRAME_AVI_DB3ITC_NO; | ||
1032 | avi_cfg.db3_ec = HDMI_INFOFRAME_AVI_DB3EC_XVYUV601; | ||
1033 | avi_cfg.db3_q_range = HDMI_INFOFRAME_AVI_DB3Q_DEFAULT; | ||
1034 | avi_cfg.db3_nup_scaling = HDMI_INFOFRAME_AVI_DB3SC_NO; | ||
1035 | avi_cfg.db4_videocode = cfg->cm.code; | ||
1036 | avi_cfg.db5_pixel_repeat = HDMI_INFOFRAME_AVI_DB5PR_NO; | ||
1037 | avi_cfg.db6_7_line_eoftop = 0; | ||
1038 | avi_cfg.db8_9_line_sofbottom = 0; | ||
1039 | avi_cfg.db10_11_pixel_eofleft = 0; | ||
1040 | avi_cfg.db12_13_pixel_sofright = 0; | ||
1041 | |||
1042 | hdmi_core_aux_infoframe_avi_config(avi_cfg); | ||
1043 | |||
1044 | /* enable/repeat the infoframe */ | ||
1045 | repeat_cfg.avi_infoframe = HDMI_PACKETENABLE; | ||
1046 | repeat_cfg.avi_infoframe_repeat = HDMI_PACKETREPEATON; | ||
1047 | /* wakeup */ | ||
1048 | repeat_cfg.audio_pkt = HDMI_PACKETENABLE; | ||
1049 | repeat_cfg.audio_pkt_repeat = HDMI_PACKETREPEATON; | ||
1050 | hdmi_core_av_packet_config(repeat_cfg); | ||
1051 | } | ||
1052 | |||
1053 | static void update_hdmi_timings(struct hdmi_config *cfg, | 253 | static void update_hdmi_timings(struct hdmi_config *cfg, |
1054 | struct omap_video_timings *timings, int code) | 254 | struct omap_video_timings *timings, int code) |
1055 | { | 255 | { |
@@ -1066,6 +266,12 @@ static void update_hdmi_timings(struct hdmi_config *cfg, | |||
1066 | cfg->timings.hsync_pol = cea_vesa_timings[code].hsync_pol; | 266 | cfg->timings.hsync_pol = cea_vesa_timings[code].hsync_pol; |
1067 | } | 267 | } |
1068 | 268 | ||
269 | unsigned long hdmi_get_pixel_clock(void) | ||
270 | { | ||
271 | /* HDMI Pixel Clock in Mhz */ | ||
272 | return hdmi.ip_data.cfg.timings.timings.pixel_clock * 10000; | ||
273 | } | ||
274 | |||
1069 | static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy, | 275 | static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy, |
1070 | struct hdmi_pll_info *pi) | 276 | struct hdmi_pll_info *pi) |
1071 | { | 277 | { |
@@ -1077,15 +283,23 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy, | |||
1077 | * Input clock is predivided by N + 1 | 283 | * Input clock is predivided by N + 1 |
1078 | * out put of which is reference clk | 284 | * out put of which is reference clk |
1079 | */ | 285 | */ |
1080 | pi->regn = dssdev->clocks.hdmi.regn; | 286 | if (dssdev->clocks.hdmi.regn == 0) |
1081 | refclk = clkin / (pi->regn + 1); | 287 | pi->regn = HDMI_DEFAULT_REGN; |
288 | else | ||
289 | pi->regn = dssdev->clocks.hdmi.regn; | ||
290 | |||
291 | refclk = clkin / pi->regn; | ||
1082 | 292 | ||
1083 | /* | 293 | /* |
1084 | * multiplier is pixel_clk/ref_clk | 294 | * multiplier is pixel_clk/ref_clk |
1085 | * Multiplying by 100 to avoid fractional part removal | 295 | * Multiplying by 100 to avoid fractional part removal |
1086 | */ | 296 | */ |
1087 | pi->regm = (phy * 100 / (refclk)) / 100; | 297 | pi->regm = (phy * 100 / (refclk)) / 100; |
1088 | pi->regm2 = dssdev->clocks.hdmi.regm2; | 298 | |
299 | if (dssdev->clocks.hdmi.regm2 == 0) | ||
300 | pi->regm2 = HDMI_DEFAULT_REGM2; | ||
301 | else | ||
302 | pi->regm2 = dssdev->clocks.hdmi.regm2; | ||
1089 | 303 | ||
1090 | /* | 304 | /* |
1091 | * fractional multiplier is remainder of the difference between | 305 | * fractional multiplier is remainder of the difference between |
@@ -1100,7 +314,10 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy, | |||
1100 | * is greater than 1000MHz | 314 | * is greater than 1000MHz |
1101 | */ | 315 | */ |
1102 | pi->dcofreq = phy > 1000 * 100; | 316 | pi->dcofreq = phy > 1000 * 100; |
1103 | pi->regsd = ((pi->regm * clkin / 10) / ((pi->regn + 1) * 250) + 5) / 10; | 317 | pi->regsd = ((pi->regm * clkin / 10) / (pi->regn * 250) + 5) / 10; |
318 | |||
319 | /* Set the reference clock to sysclk reference */ | ||
320 | pi->refsel = HDMI_REFSEL_SYSCLK; | ||
1104 | 321 | ||
1105 | DSSDBG("M = %d Mf = %d\n", pi->regm, pi->regmf); | 322 | DSSDBG("M = %d Mf = %d\n", pi->regm, pi->regmf); |
1106 | DSSDBG("range = %d sd = %d\n", pi->dcofreq, pi->regsd); | 323 | DSSDBG("range = %d sd = %d\n", pi->dcofreq, pi->regsd); |
@@ -1109,7 +326,6 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy, | |||
1109 | static int hdmi_power_on(struct omap_dss_device *dssdev) | 326 | static int hdmi_power_on(struct omap_dss_device *dssdev) |
1110 | { | 327 | { |
1111 | int r, code = 0; | 328 | int r, code = 0; |
1112 | struct hdmi_pll_info pll_data; | ||
1113 | struct omap_video_timings *p; | 329 | struct omap_video_timings *p; |
1114 | unsigned long phy; | 330 | unsigned long phy; |
1115 | 331 | ||
@@ -1117,7 +333,7 @@ static int hdmi_power_on(struct omap_dss_device *dssdev) | |||
1117 | if (r) | 333 | if (r) |
1118 | return r; | 334 | return r; |
1119 | 335 | ||
1120 | dispc_enable_channel(OMAP_DSS_CHANNEL_DIGIT, 0); | 336 | dispc_mgr_enable(OMAP_DSS_CHANNEL_DIGIT, 0); |
1121 | 337 | ||
1122 | p = &dssdev->panel.timings; | 338 | p = &dssdev->panel.timings; |
1123 | 339 | ||
@@ -1125,36 +341,31 @@ static int hdmi_power_on(struct omap_dss_device *dssdev) | |||
1125 | dssdev->panel.timings.x_res, | 341 | dssdev->panel.timings.x_res, |
1126 | dssdev->panel.timings.y_res); | 342 | dssdev->panel.timings.y_res); |
1127 | 343 | ||
1128 | if (!hdmi.custom_set) { | ||
1129 | DSSDBG("Read EDID as no EDID is not set on poweron\n"); | ||
1130 | hdmi_read_edid(p); | ||
1131 | } | ||
1132 | code = get_timings_index(); | 344 | code = get_timings_index(); |
1133 | dssdev->panel.timings = cea_vesa_timings[code].timings; | 345 | update_hdmi_timings(&hdmi.ip_data.cfg, p, code); |
1134 | update_hdmi_timings(&hdmi.cfg, p, code); | ||
1135 | 346 | ||
1136 | phy = p->pixel_clock; | 347 | phy = p->pixel_clock; |
1137 | 348 | ||
1138 | hdmi_compute_pll(dssdev, phy, &pll_data); | 349 | hdmi_compute_pll(dssdev, phy, &hdmi.ip_data.pll_data); |
1139 | 350 | ||
1140 | hdmi_wp_video_start(0); | 351 | hdmi.ip_data.ops->video_enable(&hdmi.ip_data, 0); |
1141 | 352 | ||
1142 | /* config the PLL and PHY first */ | 353 | /* config the PLL and PHY hdmi_set_pll_pwrfirst */ |
1143 | r = hdmi_pll_program(&pll_data); | 354 | r = hdmi.ip_data.ops->pll_enable(&hdmi.ip_data); |
1144 | if (r) { | 355 | if (r) { |
1145 | DSSDBG("Failed to lock PLL\n"); | 356 | DSSDBG("Failed to lock PLL\n"); |
1146 | goto err; | 357 | goto err; |
1147 | } | 358 | } |
1148 | 359 | ||
1149 | r = hdmi_phy_init(); | 360 | r = hdmi.ip_data.ops->phy_enable(&hdmi.ip_data); |
1150 | if (r) { | 361 | if (r) { |
1151 | DSSDBG("Failed to start PHY\n"); | 362 | DSSDBG("Failed to start PHY\n"); |
1152 | goto err; | 363 | goto err; |
1153 | } | 364 | } |
1154 | 365 | ||
1155 | hdmi.cfg.cm.mode = hdmi.mode; | 366 | hdmi.ip_data.cfg.cm.mode = hdmi.mode; |
1156 | hdmi.cfg.cm.code = hdmi.code; | 367 | hdmi.ip_data.cfg.cm.code = hdmi.code; |
1157 | hdmi_basic_configure(&hdmi.cfg); | 368 | hdmi.ip_data.ops->video_configure(&hdmi.ip_data); |
1158 | 369 | ||
1159 | /* Make selection of HDMI in DSS */ | 370 | /* Make selection of HDMI in DSS */ |
1160 | dss_select_hdmi_venc_clk_source(DSS_HDMI_M_PCLK); | 371 | dss_select_hdmi_venc_clk_source(DSS_HDMI_M_PCLK); |
@@ -1174,9 +385,9 @@ static int hdmi_power_on(struct omap_dss_device *dssdev) | |||
1174 | dispc_set_digit_size(dssdev->panel.timings.x_res, | 385 | dispc_set_digit_size(dssdev->panel.timings.x_res, |
1175 | dssdev->panel.timings.y_res); | 386 | dssdev->panel.timings.y_res); |
1176 | 387 | ||
1177 | dispc_enable_channel(OMAP_DSS_CHANNEL_DIGIT, 1); | 388 | hdmi.ip_data.ops->video_enable(&hdmi.ip_data, 1); |
1178 | 389 | ||
1179 | hdmi_wp_video_start(1); | 390 | dispc_mgr_enable(OMAP_DSS_CHANNEL_DIGIT, 1); |
1180 | 391 | ||
1181 | return 0; | 392 | return 0; |
1182 | err: | 393 | err: |
@@ -1186,14 +397,12 @@ err: | |||
1186 | 397 | ||
1187 | static void hdmi_power_off(struct omap_dss_device *dssdev) | 398 | static void hdmi_power_off(struct omap_dss_device *dssdev) |
1188 | { | 399 | { |
1189 | dispc_enable_channel(OMAP_DSS_CHANNEL_DIGIT, 0); | 400 | dispc_mgr_enable(OMAP_DSS_CHANNEL_DIGIT, 0); |
1190 | 401 | ||
1191 | hdmi_wp_video_start(0); | 402 | hdmi.ip_data.ops->video_enable(&hdmi.ip_data, 0); |
1192 | hdmi_phy_off(); | 403 | hdmi.ip_data.ops->phy_disable(&hdmi.ip_data); |
1193 | hdmi_set_pll_pwr(HDMI_PLLPWRCMD_ALLOFF); | 404 | hdmi.ip_data.ops->pll_disable(&hdmi.ip_data); |
1194 | hdmi_runtime_put(); | 405 | hdmi_runtime_put(); |
1195 | |||
1196 | hdmi.edid_set = 0; | ||
1197 | } | 406 | } |
1198 | 407 | ||
1199 | int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev, | 408 | int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev, |
@@ -1203,7 +412,6 @@ int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev, | |||
1203 | 412 | ||
1204 | cm = hdmi_get_code(timings); | 413 | cm = hdmi_get_code(timings); |
1205 | if (cm.code == -1) { | 414 | if (cm.code == -1) { |
1206 | DSSERR("Invalid timing entered\n"); | ||
1207 | return -EINVAL; | 415 | return -EINVAL; |
1208 | } | 416 | } |
1209 | 417 | ||
@@ -1215,12 +423,69 @@ void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev) | |||
1215 | { | 423 | { |
1216 | struct hdmi_cm cm; | 424 | struct hdmi_cm cm; |
1217 | 425 | ||
1218 | hdmi.custom_set = 1; | ||
1219 | cm = hdmi_get_code(&dssdev->panel.timings); | 426 | cm = hdmi_get_code(&dssdev->panel.timings); |
1220 | hdmi.code = cm.code; | 427 | hdmi.code = cm.code; |
1221 | hdmi.mode = cm.mode; | 428 | hdmi.mode = cm.mode; |
1222 | omapdss_hdmi_display_enable(dssdev); | 429 | |
1223 | hdmi.custom_set = 0; | 430 | if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) { |
431 | int r; | ||
432 | |||
433 | hdmi_power_off(dssdev); | ||
434 | |||
435 | r = hdmi_power_on(dssdev); | ||
436 | if (r) | ||
437 | DSSERR("failed to power on device\n"); | ||
438 | } | ||
439 | } | ||
440 | |||
441 | void hdmi_dump_regs(struct seq_file *s) | ||
442 | { | ||
443 | mutex_lock(&hdmi.lock); | ||
444 | |||
445 | if (hdmi_runtime_get()) | ||
446 | return; | ||
447 | |||
448 | hdmi.ip_data.ops->dump_wrapper(&hdmi.ip_data, s); | ||
449 | hdmi.ip_data.ops->dump_pll(&hdmi.ip_data, s); | ||
450 | hdmi.ip_data.ops->dump_phy(&hdmi.ip_data, s); | ||
451 | hdmi.ip_data.ops->dump_core(&hdmi.ip_data, s); | ||
452 | |||
453 | hdmi_runtime_put(); | ||
454 | mutex_unlock(&hdmi.lock); | ||
455 | } | ||
456 | |||
457 | int omapdss_hdmi_read_edid(u8 *buf, int len) | ||
458 | { | ||
459 | int r; | ||
460 | |||
461 | mutex_lock(&hdmi.lock); | ||
462 | |||
463 | r = hdmi_runtime_get(); | ||
464 | BUG_ON(r); | ||
465 | |||
466 | r = hdmi.ip_data.ops->read_edid(&hdmi.ip_data, buf, len); | ||
467 | |||
468 | hdmi_runtime_put(); | ||
469 | mutex_unlock(&hdmi.lock); | ||
470 | |||
471 | return r; | ||
472 | } | ||
473 | |||
474 | bool omapdss_hdmi_detect(void) | ||
475 | { | ||
476 | int r; | ||
477 | |||
478 | mutex_lock(&hdmi.lock); | ||
479 | |||
480 | r = hdmi_runtime_get(); | ||
481 | BUG_ON(r); | ||
482 | |||
483 | r = hdmi.ip_data.ops->detect(&hdmi.ip_data); | ||
484 | |||
485 | hdmi_runtime_put(); | ||
486 | mutex_unlock(&hdmi.lock); | ||
487 | |||
488 | return r == 1; | ||
1224 | } | 489 | } |
1225 | 490 | ||
1226 | int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev) | 491 | int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev) |
@@ -1231,6 +496,12 @@ int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev) | |||
1231 | 496 | ||
1232 | mutex_lock(&hdmi.lock); | 497 | mutex_lock(&hdmi.lock); |
1233 | 498 | ||
499 | if (dssdev->manager == NULL) { | ||
500 | DSSERR("failed to enable display: no manager\n"); | ||
501 | r = -ENODEV; | ||
502 | goto err0; | ||
503 | } | ||
504 | |||
1234 | r = omap_dss_start_device(dssdev); | 505 | r = omap_dss_start_device(dssdev); |
1235 | if (r) { | 506 | if (r) { |
1236 | DSSERR("failed to start device\n"); | 507 | DSSERR("failed to start device\n"); |
@@ -1282,219 +553,9 @@ void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev) | |||
1282 | 553 | ||
1283 | #if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ | 554 | #if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ |
1284 | defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE) | 555 | defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE) |
1285 | static void hdmi_wp_audio_config_format( | ||
1286 | struct hdmi_audio_format *aud_fmt) | ||
1287 | { | ||
1288 | u32 r; | ||
1289 | |||
1290 | DSSDBG("Enter hdmi_wp_audio_config_format\n"); | ||
1291 | |||
1292 | r = hdmi_read_reg(HDMI_WP_AUDIO_CFG); | ||
1293 | r = FLD_MOD(r, aud_fmt->stereo_channels, 26, 24); | ||
1294 | r = FLD_MOD(r, aud_fmt->active_chnnls_msk, 23, 16); | ||
1295 | r = FLD_MOD(r, aud_fmt->en_sig_blk_strt_end, 5, 5); | ||
1296 | r = FLD_MOD(r, aud_fmt->type, 4, 4); | ||
1297 | r = FLD_MOD(r, aud_fmt->justification, 3, 3); | ||
1298 | r = FLD_MOD(r, aud_fmt->sample_order, 2, 2); | ||
1299 | r = FLD_MOD(r, aud_fmt->samples_per_word, 1, 1); | ||
1300 | r = FLD_MOD(r, aud_fmt->sample_size, 0, 0); | ||
1301 | hdmi_write_reg(HDMI_WP_AUDIO_CFG, r); | ||
1302 | } | ||
1303 | |||
1304 | static void hdmi_wp_audio_config_dma(struct hdmi_audio_dma *aud_dma) | ||
1305 | { | ||
1306 | u32 r; | ||
1307 | |||
1308 | DSSDBG("Enter hdmi_wp_audio_config_dma\n"); | ||
1309 | |||
1310 | r = hdmi_read_reg(HDMI_WP_AUDIO_CFG2); | ||
1311 | r = FLD_MOD(r, aud_dma->transfer_size, 15, 8); | ||
1312 | r = FLD_MOD(r, aud_dma->block_size, 7, 0); | ||
1313 | hdmi_write_reg(HDMI_WP_AUDIO_CFG2, r); | ||
1314 | |||
1315 | r = hdmi_read_reg(HDMI_WP_AUDIO_CTRL); | ||
1316 | r = FLD_MOD(r, aud_dma->mode, 9, 9); | ||
1317 | r = FLD_MOD(r, aud_dma->fifo_threshold, 8, 0); | ||
1318 | hdmi_write_reg(HDMI_WP_AUDIO_CTRL, r); | ||
1319 | } | ||
1320 | |||
1321 | static void hdmi_core_audio_config(struct hdmi_core_audio_config *cfg) | ||
1322 | { | ||
1323 | u32 r; | ||
1324 | |||
1325 | /* audio clock recovery parameters */ | ||
1326 | r = hdmi_read_reg(HDMI_CORE_AV_ACR_CTRL); | ||
1327 | r = FLD_MOD(r, cfg->use_mclk, 2, 2); | ||
1328 | r = FLD_MOD(r, cfg->en_acr_pkt, 1, 1); | ||
1329 | r = FLD_MOD(r, cfg->cts_mode, 0, 0); | ||
1330 | hdmi_write_reg(HDMI_CORE_AV_ACR_CTRL, r); | ||
1331 | |||
1332 | REG_FLD_MOD(HDMI_CORE_AV_N_SVAL1, cfg->n, 7, 0); | ||
1333 | REG_FLD_MOD(HDMI_CORE_AV_N_SVAL2, cfg->n >> 8, 7, 0); | ||
1334 | REG_FLD_MOD(HDMI_CORE_AV_N_SVAL3, cfg->n >> 16, 7, 0); | ||
1335 | |||
1336 | if (cfg->cts_mode == HDMI_AUDIO_CTS_MODE_SW) { | ||
1337 | REG_FLD_MOD(HDMI_CORE_AV_CTS_SVAL1, cfg->cts, 7, 0); | ||
1338 | REG_FLD_MOD(HDMI_CORE_AV_CTS_SVAL2, cfg->cts >> 8, 7, 0); | ||
1339 | REG_FLD_MOD(HDMI_CORE_AV_CTS_SVAL3, cfg->cts >> 16, 7, 0); | ||
1340 | } else { | ||
1341 | /* | ||
1342 | * HDMI IP uses this configuration to divide the MCLK to | ||
1343 | * update CTS value. | ||
1344 | */ | ||
1345 | REG_FLD_MOD(HDMI_CORE_AV_FREQ_SVAL, cfg->mclk_mode, 2, 0); | ||
1346 | |||
1347 | /* Configure clock for audio packets */ | ||
1348 | REG_FLD_MOD(HDMI_CORE_AV_AUD_PAR_BUSCLK_1, | ||
1349 | cfg->aud_par_busclk, 7, 0); | ||
1350 | REG_FLD_MOD(HDMI_CORE_AV_AUD_PAR_BUSCLK_2, | ||
1351 | (cfg->aud_par_busclk >> 8), 7, 0); | ||
1352 | REG_FLD_MOD(HDMI_CORE_AV_AUD_PAR_BUSCLK_3, | ||
1353 | (cfg->aud_par_busclk >> 16), 7, 0); | ||
1354 | } | ||
1355 | |||
1356 | /* Override of SPDIF sample frequency with value in I2S_CHST4 */ | ||
1357 | REG_FLD_MOD(HDMI_CORE_AV_SPDIF_CTRL, cfg->fs_override, 1, 1); | ||
1358 | |||
1359 | /* I2S parameters */ | ||
1360 | REG_FLD_MOD(HDMI_CORE_AV_I2S_CHST4, cfg->freq_sample, 3, 0); | ||
1361 | |||
1362 | r = hdmi_read_reg(HDMI_CORE_AV_I2S_IN_CTRL); | ||
1363 | r = FLD_MOD(r, cfg->i2s_cfg.en_high_bitrate_aud, 7, 7); | ||
1364 | r = FLD_MOD(r, cfg->i2s_cfg.sck_edge_mode, 6, 6); | ||
1365 | r = FLD_MOD(r, cfg->i2s_cfg.cbit_order, 5, 5); | ||
1366 | r = FLD_MOD(r, cfg->i2s_cfg.vbit, 4, 4); | ||
1367 | r = FLD_MOD(r, cfg->i2s_cfg.ws_polarity, 3, 3); | ||
1368 | r = FLD_MOD(r, cfg->i2s_cfg.justification, 2, 2); | ||
1369 | r = FLD_MOD(r, cfg->i2s_cfg.direction, 1, 1); | ||
1370 | r = FLD_MOD(r, cfg->i2s_cfg.shift, 0, 0); | ||
1371 | hdmi_write_reg(HDMI_CORE_AV_I2S_IN_CTRL, r); | ||
1372 | |||
1373 | r = hdmi_read_reg(HDMI_CORE_AV_I2S_CHST5); | ||
1374 | r = FLD_MOD(r, cfg->freq_sample, 7, 4); | ||
1375 | r = FLD_MOD(r, cfg->i2s_cfg.word_length, 3, 1); | ||
1376 | r = FLD_MOD(r, cfg->i2s_cfg.word_max_length, 0, 0); | ||
1377 | hdmi_write_reg(HDMI_CORE_AV_I2S_CHST5, r); | ||
1378 | |||
1379 | REG_FLD_MOD(HDMI_CORE_AV_I2S_IN_LEN, cfg->i2s_cfg.in_length_bits, 3, 0); | ||
1380 | |||
1381 | /* Audio channels and mode parameters */ | ||
1382 | REG_FLD_MOD(HDMI_CORE_AV_HDMI_CTRL, cfg->layout, 2, 1); | ||
1383 | r = hdmi_read_reg(HDMI_CORE_AV_AUD_MODE); | ||
1384 | r = FLD_MOD(r, cfg->i2s_cfg.active_sds, 7, 4); | ||
1385 | r = FLD_MOD(r, cfg->en_dsd_audio, 3, 3); | ||
1386 | r = FLD_MOD(r, cfg->en_parallel_aud_input, 2, 2); | ||
1387 | r = FLD_MOD(r, cfg->en_spdif, 1, 1); | ||
1388 | hdmi_write_reg(HDMI_CORE_AV_AUD_MODE, r); | ||
1389 | } | ||
1390 | |||
1391 | static void hdmi_core_audio_infoframe_config( | ||
1392 | struct hdmi_core_infoframe_audio *info_aud) | ||
1393 | { | ||
1394 | u8 val; | ||
1395 | u8 sum = 0, checksum = 0; | ||
1396 | |||
1397 | /* | ||
1398 | * Set audio info frame type, version and length as | ||
1399 | * described in HDMI 1.4a Section 8.2.2 specification. | ||
1400 | * Checksum calculation is defined in Section 5.3.5. | ||
1401 | */ | ||
1402 | hdmi_write_reg(HDMI_CORE_AV_AUDIO_TYPE, 0x84); | ||
1403 | hdmi_write_reg(HDMI_CORE_AV_AUDIO_VERS, 0x01); | ||
1404 | hdmi_write_reg(HDMI_CORE_AV_AUDIO_LEN, 0x0a); | ||
1405 | sum += 0x84 + 0x001 + 0x00a; | ||
1406 | |||
1407 | val = (info_aud->db1_coding_type << 4) | ||
1408 | | (info_aud->db1_channel_count - 1); | ||
1409 | hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(0), val); | ||
1410 | sum += val; | ||
1411 | |||
1412 | val = (info_aud->db2_sample_freq << 2) | info_aud->db2_sample_size; | ||
1413 | hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(1), val); | ||
1414 | sum += val; | ||
1415 | |||
1416 | hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(2), 0x00); | ||
1417 | |||
1418 | val = info_aud->db4_channel_alloc; | ||
1419 | hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(3), val); | ||
1420 | sum += val; | ||
1421 | |||
1422 | val = (info_aud->db5_downmix_inh << 7) | (info_aud->db5_lsv << 3); | ||
1423 | hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(4), val); | ||
1424 | sum += val; | ||
1425 | |||
1426 | hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(5), 0x00); | ||
1427 | hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(6), 0x00); | ||
1428 | hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(7), 0x00); | ||
1429 | hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(8), 0x00); | ||
1430 | hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(9), 0x00); | ||
1431 | 556 | ||
1432 | checksum = 0x100 - sum; | 557 | static int hdmi_audio_hw_params(struct hdmi_ip_data *ip_data, |
1433 | hdmi_write_reg(HDMI_CORE_AV_AUDIO_CHSUM, checksum); | 558 | struct snd_pcm_substream *substream, |
1434 | |||
1435 | /* | ||
1436 | * TODO: Add MPEG and SPD enable and repeat cfg when EDID parsing | ||
1437 | * is available. | ||
1438 | */ | ||
1439 | } | ||
1440 | |||
1441 | static int hdmi_config_audio_acr(u32 sample_freq, u32 *n, u32 *cts) | ||
1442 | { | ||
1443 | u32 r; | ||
1444 | u32 deep_color = 0; | ||
1445 | u32 pclk = hdmi.cfg.timings.timings.pixel_clock; | ||
1446 | |||
1447 | if (n == NULL || cts == NULL) | ||
1448 | return -EINVAL; | ||
1449 | /* | ||
1450 | * Obtain current deep color configuration. This needed | ||
1451 | * to calculate the TMDS clock based on the pixel clock. | ||
1452 | */ | ||
1453 | r = REG_GET(HDMI_WP_VIDEO_CFG, 1, 0); | ||
1454 | switch (r) { | ||
1455 | case 1: /* No deep color selected */ | ||
1456 | deep_color = 100; | ||
1457 | break; | ||
1458 | case 2: /* 10-bit deep color selected */ | ||
1459 | deep_color = 125; | ||
1460 | break; | ||
1461 | case 3: /* 12-bit deep color selected */ | ||
1462 | deep_color = 150; | ||
1463 | break; | ||
1464 | default: | ||
1465 | return -EINVAL; | ||
1466 | } | ||
1467 | |||
1468 | switch (sample_freq) { | ||
1469 | case 32000: | ||
1470 | if ((deep_color == 125) && ((pclk == 54054) | ||
1471 | || (pclk == 74250))) | ||
1472 | *n = 8192; | ||
1473 | else | ||
1474 | *n = 4096; | ||
1475 | break; | ||
1476 | case 44100: | ||
1477 | *n = 6272; | ||
1478 | break; | ||
1479 | case 48000: | ||
1480 | if ((deep_color == 125) && ((pclk == 54054) | ||
1481 | || (pclk == 74250))) | ||
1482 | *n = 8192; | ||
1483 | else | ||
1484 | *n = 6144; | ||
1485 | break; | ||
1486 | default: | ||
1487 | *n = 0; | ||
1488 | return -EINVAL; | ||
1489 | } | ||
1490 | |||
1491 | /* Calculate CTS. See HDMI 1.3a or 1.4a specifications */ | ||
1492 | *cts = pclk * (*n / 128) * deep_color / (sample_freq / 10); | ||
1493 | |||
1494 | return 0; | ||
1495 | } | ||
1496 | |||
1497 | static int hdmi_audio_hw_params(struct snd_pcm_substream *substream, | ||
1498 | struct snd_pcm_hw_params *params, | 559 | struct snd_pcm_hw_params *params, |
1499 | struct snd_soc_dai *dai) | 560 | struct snd_soc_dai *dai) |
1500 | { | 561 | { |
@@ -1548,7 +609,7 @@ static int hdmi_audio_hw_params(struct snd_pcm_substream *substream, | |||
1548 | return -EINVAL; | 609 | return -EINVAL; |
1549 | } | 610 | } |
1550 | 611 | ||
1551 | err = hdmi_config_audio_acr(params_rate(params), &n, &cts); | 612 | err = hdmi_config_audio_acr(ip_data, params_rate(params), &n, &cts); |
1552 | if (err < 0) | 613 | if (err < 0) |
1553 | return err; | 614 | return err; |
1554 | 615 | ||
@@ -1564,8 +625,8 @@ static int hdmi_audio_hw_params(struct snd_pcm_substream *substream, | |||
1564 | audio_dma.mode = HDMI_AUDIO_TRANSF_DMA; | 625 | audio_dma.mode = HDMI_AUDIO_TRANSF_DMA; |
1565 | audio_dma.fifo_threshold = 0x20; /* in number of samples */ | 626 | audio_dma.fifo_threshold = 0x20; /* in number of samples */ |
1566 | 627 | ||
1567 | hdmi_wp_audio_config_dma(&audio_dma); | 628 | hdmi_wp_audio_config_dma(ip_data, &audio_dma); |
1568 | hdmi_wp_audio_config_format(&audio_format); | 629 | hdmi_wp_audio_config_format(ip_data, &audio_format); |
1569 | 630 | ||
1570 | /* | 631 | /* |
1571 | * I2S config | 632 | * I2S config |
@@ -1609,7 +670,7 @@ static int hdmi_audio_hw_params(struct snd_pcm_substream *substream, | |||
1609 | /* Use parallel audio interface */ | 670 | /* Use parallel audio interface */ |
1610 | core_cfg.en_parallel_aud_input = true; | 671 | core_cfg.en_parallel_aud_input = true; |
1611 | 672 | ||
1612 | hdmi_core_audio_config(&core_cfg); | 673 | hdmi_core_audio_config(ip_data, &core_cfg); |
1613 | 674 | ||
1614 | /* | 675 | /* |
1615 | * Configure packet | 676 | * Configure packet |
@@ -1623,36 +684,10 @@ static int hdmi_audio_hw_params(struct snd_pcm_substream *substream, | |||
1623 | aud_if_cfg.db5_downmix_inh = false; | 684 | aud_if_cfg.db5_downmix_inh = false; |
1624 | aud_if_cfg.db5_lsv = 0; | 685 | aud_if_cfg.db5_lsv = 0; |
1625 | 686 | ||
1626 | hdmi_core_audio_infoframe_config(&aud_if_cfg); | 687 | hdmi_core_audio_infoframe_config(ip_data, &aud_if_cfg); |
1627 | return 0; | 688 | return 0; |
1628 | } | 689 | } |
1629 | 690 | ||
1630 | static int hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd, | ||
1631 | struct snd_soc_dai *dai) | ||
1632 | { | ||
1633 | int err = 0; | ||
1634 | switch (cmd) { | ||
1635 | case SNDRV_PCM_TRIGGER_START: | ||
1636 | case SNDRV_PCM_TRIGGER_RESUME: | ||
1637 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
1638 | REG_FLD_MOD(HDMI_CORE_AV_AUD_MODE, 1, 0, 0); | ||
1639 | REG_FLD_MOD(HDMI_WP_AUDIO_CTRL, 1, 31, 31); | ||
1640 | REG_FLD_MOD(HDMI_WP_AUDIO_CTRL, 1, 30, 30); | ||
1641 | break; | ||
1642 | |||
1643 | case SNDRV_PCM_TRIGGER_STOP: | ||
1644 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
1645 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
1646 | REG_FLD_MOD(HDMI_CORE_AV_AUD_MODE, 0, 0, 0); | ||
1647 | REG_FLD_MOD(HDMI_WP_AUDIO_CTRL, 0, 30, 30); | ||
1648 | REG_FLD_MOD(HDMI_WP_AUDIO_CTRL, 0, 31, 31); | ||
1649 | break; | ||
1650 | default: | ||
1651 | err = -EINVAL; | ||
1652 | } | ||
1653 | return err; | ||
1654 | } | ||
1655 | |||
1656 | static int hdmi_audio_startup(struct snd_pcm_substream *substream, | 691 | static int hdmi_audio_startup(struct snd_pcm_substream *substream, |
1657 | struct snd_soc_dai *dai) | 692 | struct snd_soc_dai *dai) |
1658 | { | 693 | { |
@@ -1698,15 +733,6 @@ static int hdmi_get_clocks(struct platform_device *pdev) | |||
1698 | 733 | ||
1699 | hdmi.sys_clk = clk; | 734 | hdmi.sys_clk = clk; |
1700 | 735 | ||
1701 | clk = clk_get(&pdev->dev, "dss_48mhz_clk"); | ||
1702 | if (IS_ERR(clk)) { | ||
1703 | DSSERR("can't get hdmi_clk\n"); | ||
1704 | clk_put(hdmi.sys_clk); | ||
1705 | return PTR_ERR(clk); | ||
1706 | } | ||
1707 | |||
1708 | hdmi.hdmi_clk = clk; | ||
1709 | |||
1710 | return 0; | 736 | return 0; |
1711 | } | 737 | } |
1712 | 738 | ||
@@ -1714,8 +740,6 @@ static void hdmi_put_clocks(void) | |||
1714 | { | 740 | { |
1715 | if (hdmi.sys_clk) | 741 | if (hdmi.sys_clk) |
1716 | clk_put(hdmi.sys_clk); | 742 | clk_put(hdmi.sys_clk); |
1717 | if (hdmi.hdmi_clk) | ||
1718 | clk_put(hdmi.hdmi_clk); | ||
1719 | } | 743 | } |
1720 | 744 | ||
1721 | /* HDMI HW IP initialisation */ | 745 | /* HDMI HW IP initialisation */ |
@@ -1736,20 +760,26 @@ static int omapdss_hdmihw_probe(struct platform_device *pdev) | |||
1736 | } | 760 | } |
1737 | 761 | ||
1738 | /* Base address taken from platform */ | 762 | /* Base address taken from platform */ |
1739 | hdmi.base_wp = ioremap(hdmi_mem->start, resource_size(hdmi_mem)); | 763 | hdmi.ip_data.base_wp = ioremap(hdmi_mem->start, |
1740 | if (!hdmi.base_wp) { | 764 | resource_size(hdmi_mem)); |
765 | if (!hdmi.ip_data.base_wp) { | ||
1741 | DSSERR("can't ioremap WP\n"); | 766 | DSSERR("can't ioremap WP\n"); |
1742 | return -ENOMEM; | 767 | return -ENOMEM; |
1743 | } | 768 | } |
1744 | 769 | ||
1745 | r = hdmi_get_clocks(pdev); | 770 | r = hdmi_get_clocks(pdev); |
1746 | if (r) { | 771 | if (r) { |
1747 | iounmap(hdmi.base_wp); | 772 | iounmap(hdmi.ip_data.base_wp); |
1748 | return r; | 773 | return r; |
1749 | } | 774 | } |
1750 | 775 | ||
1751 | pm_runtime_enable(&pdev->dev); | 776 | pm_runtime_enable(&pdev->dev); |
1752 | 777 | ||
778 | hdmi.ip_data.core_sys_offset = HDMI_CORE_SYS; | ||
779 | hdmi.ip_data.core_av_offset = HDMI_CORE_AV; | ||
780 | hdmi.ip_data.pll_offset = HDMI_PLLCTRL; | ||
781 | hdmi.ip_data.phy_offset = HDMI_PHY; | ||
782 | |||
1753 | hdmi_panel_init(); | 783 | hdmi_panel_init(); |
1754 | 784 | ||
1755 | #if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ | 785 | #if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ |
@@ -1779,14 +809,13 @@ static int omapdss_hdmihw_remove(struct platform_device *pdev) | |||
1779 | 809 | ||
1780 | hdmi_put_clocks(); | 810 | hdmi_put_clocks(); |
1781 | 811 | ||
1782 | iounmap(hdmi.base_wp); | 812 | iounmap(hdmi.ip_data.base_wp); |
1783 | 813 | ||
1784 | return 0; | 814 | return 0; |
1785 | } | 815 | } |
1786 | 816 | ||
1787 | static int hdmi_runtime_suspend(struct device *dev) | 817 | static int hdmi_runtime_suspend(struct device *dev) |
1788 | { | 818 | { |
1789 | clk_disable(hdmi.hdmi_clk); | ||
1790 | clk_disable(hdmi.sys_clk); | 819 | clk_disable(hdmi.sys_clk); |
1791 | 820 | ||
1792 | dispc_runtime_put(); | 821 | dispc_runtime_put(); |
@@ -1809,7 +838,6 @@ static int hdmi_runtime_resume(struct device *dev) | |||
1809 | 838 | ||
1810 | 839 | ||
1811 | clk_enable(hdmi.sys_clk); | 840 | clk_enable(hdmi.sys_clk); |
1812 | clk_enable(hdmi.hdmi_clk); | ||
1813 | 841 | ||
1814 | return 0; | 842 | return 0; |
1815 | 843 | ||