OLD | NEW |
(Empty) | |
| 1 /* linux/drivers/media/video/samsung/tv20/hdmi_s5pv210.c |
| 2 * |
| 3 * Copyright (c) 2010 Samsung Electronics Co., Ltd. |
| 4 * http://www.samsung.com/ |
| 5 * |
| 6 * S5PV210 - hdmi raw ftn file for Samsung TVOut driver |
| 7 * |
| 8 * This program is free software; you can redistribute it and/or modify |
| 9 * it under the terms of the GNU General Public License version 2 as |
| 10 * published by the Free Software Foundation. |
| 11 */ |
| 12 |
| 13 #include <linux/module.h> |
| 14 #include <linux/kernel.h> |
| 15 #include <linux/i2c.h> |
| 16 #include <linux/platform_device.h> |
| 17 #include <linux/clk.h> |
| 18 #include <linux/interrupt.h> |
| 19 #include <linux/delay.h> |
| 20 |
| 21 #include <plat/clock.h> |
| 22 #include <linux/io.h> |
| 23 |
| 24 #include "tv_out_s5pv210.h" |
| 25 |
| 26 #include <mach/regs-hdmi.h> |
| 27 |
| 28 #include <mach/regs-clock.h> |
| 29 |
| 30 #include "hdmi_param.h" |
| 31 |
| 32 #ifdef CONFIG_TVOUT_RAW_DBG |
| 33 #define S5P_HDMI_DEBUG 1 |
| 34 #endif |
| 35 |
| 36 #ifdef S5P_HDMI_DEBUG |
| 37 #define HDMIPRINTK(fmt, args...) \ |
| 38 printk(KERN_INFO "\t\t[HDMI] %s: " fmt, __func__ , ## args) |
| 39 #else |
| 40 #define HDMIPRINTK(fmt, args...) |
| 41 #endif |
| 42 |
| 43 static struct resource *hdmi_mem; |
| 44 void __iomem *hdmi_base; |
| 45 |
| 46 static struct resource *i2c_hdmi_phy_mem; |
| 47 void __iomem *i2c_hdmi_phy_base; |
| 48 |
| 49 |
| 50 spinlock_t lock_hdmi; |
| 51 |
| 52 /* |
| 53 * i2c_hdmi_phy related |
| 54 */ |
| 55 |
| 56 #define PHY_I2C_ADDRESS 0x70 |
| 57 |
| 58 #define I2C_ACK (1<<7) |
| 59 #define I2C_INT (1<<5) |
| 60 #define I2C_PEND (1<<4) |
| 61 |
| 62 #define I2C_INT_CLEAR (0<<4) |
| 63 |
| 64 #define I2C_CLK (0x41) |
| 65 #define I2C_CLK_PEND_INT (I2C_CLK|I2C_INT_CLEAR|I2C_INT) |
| 66 |
| 67 #define I2C_ENABLE (1<<4) |
| 68 #define I2C_START (1<<5) |
| 69 |
| 70 #define I2C_MODE_MTX 0xC0 |
| 71 #define I2C_MODE_MRX 0x80 |
| 72 |
| 73 #define I2C_IDLE 0 |
| 74 |
| 75 static struct { |
| 76 s32 state; |
| 77 u8 *buffer; |
| 78 s32 bytes; |
| 79 } i2c_hdmi_phy_context; |
| 80 |
| 81 enum i2c_hdmi_phy_state { |
| 82 STATE_IDLE, |
| 83 STATE_TX_EDDC_SEGADDR, |
| 84 STATE_TX_EDDC_SEGNUM, |
| 85 STATE_TX_DDC_ADDR, |
| 86 STATE_TX_DDC_OFFSET, |
| 87 STATE_RX_DDC_ADDR, |
| 88 STATE_RX_DDC_DATA, |
| 89 STATE_RX_ADDR, |
| 90 STATE_RX_DATA, |
| 91 STATE_TX_ADDR, |
| 92 STATE_TX_DATA, |
| 93 STATE_TX_STOP, |
| 94 STATE_RX_STOP |
| 95 }; |
| 96 |
| 97 static s32 i2c_hdmi_phy_interruptwait(void) |
| 98 { |
| 99 u8 status, reg; |
| 100 s32 retval = 0; |
| 101 |
| 102 do { |
| 103 status = readb(i2c_hdmi_phy_base + I2C_HDMI_CON); |
| 104 |
| 105 if (status & I2C_PEND) { |
| 106 /* check status flags */ |
| 107 reg = readb(i2c_hdmi_phy_base + I2C_HDMI_STAT); |
| 108 break; |
| 109 } |
| 110 |
| 111 } while (1); |
| 112 |
| 113 return retval; |
| 114 } |
| 115 |
| 116 s32 i2c_hdmi_phy_read(u8 addr, u8 nbytes, u8 *buffer) |
| 117 { |
| 118 u8 reg; |
| 119 s32 ret = 0; |
| 120 u32 i, proc = true; |
| 121 |
| 122 i2c_hdmi_phy_context.state = STATE_RX_ADDR; |
| 123 |
| 124 i2c_hdmi_phy_context.buffer = buffer; |
| 125 i2c_hdmi_phy_context.bytes = nbytes; |
| 126 |
| 127 writeb(I2C_CLK | I2C_INT | I2C_ACK, |
| 128 i2c_hdmi_phy_base + I2C_HDMI_CON); |
| 129 writeb(I2C_ENABLE | I2C_MODE_MRX, |
| 130 i2c_hdmi_phy_base + I2C_HDMI_STAT); |
| 131 writeb(addr & 0xFE, |
| 132 i2c_hdmi_phy_base + I2C_HDMI_DS); |
| 133 |
| 134 writeb(I2C_ENABLE | I2C_START | I2C_MODE_MRX, |
| 135 i2c_hdmi_phy_base + I2C_HDMI_STAT); |
| 136 |
| 137 while (proc) { |
| 138 |
| 139 if (i2c_hdmi_phy_context.state != STATE_RX_STOP) { |
| 140 if (i2c_hdmi_phy_interruptwait() != 0) { |
| 141 HDMIPRINTK("interrupt wait failed!!!\n"); |
| 142 ret = EINVAL; |
| 143 break; |
| 144 } |
| 145 |
| 146 } |
| 147 |
| 148 switch (i2c_hdmi_phy_context.state) { |
| 149 |
| 150 case STATE_RX_DATA: |
| 151 |
| 152 reg = readb(i2c_hdmi_phy_base + I2C_HDMI_DS); |
| 153 *(i2c_hdmi_phy_context.buffer) = reg; |
| 154 |
| 155 i2c_hdmi_phy_context.buffer++; |
| 156 --(i2c_hdmi_phy_context.bytes); |
| 157 |
| 158 if (i2c_hdmi_phy_context.bytes == 1) { |
| 159 i2c_hdmi_phy_context.state = STATE_RX_STOP; |
| 160 writeb(I2C_CLK_PEND_INT, |
| 161 i2c_hdmi_phy_base + I2C_HDMI_CON); |
| 162 } else { |
| 163 writeb(I2C_CLK_PEND_INT | I2C_ACK, |
| 164 i2c_hdmi_phy_base + I2C_HDMI_CON); |
| 165 |
| 166 } |
| 167 break; |
| 168 |
| 169 case STATE_RX_ADDR: |
| 170 i2c_hdmi_phy_context.state = STATE_RX_DATA; |
| 171 |
| 172 if (i2c_hdmi_phy_context.bytes == 1) { |
| 173 i2c_hdmi_phy_context.state = STATE_RX_STOP; |
| 174 writeb(I2C_CLK_PEND_INT, |
| 175 i2c_hdmi_phy_base + I2C_HDMI_CON); |
| 176 } else { |
| 177 writeb(I2C_CLK_PEND_INT | I2C_ACK, |
| 178 i2c_hdmi_phy_base + I2C_HDMI_CON); |
| 179 } |
| 180 |
| 181 break; |
| 182 |
| 183 case STATE_RX_STOP: |
| 184 |
| 185 i2c_hdmi_phy_context.state = STATE_IDLE; |
| 186 |
| 187 for (i = 0 ; i < 10000 ; i++) |
| 188 ; |
| 189 reg = readb(i2c_hdmi_phy_base + I2C_HDMI_DS); |
| 190 |
| 191 *(i2c_hdmi_phy_context.buffer) = reg; |
| 192 |
| 193 writeb(I2C_MODE_MRX|I2C_ENABLE, |
| 194 i2c_hdmi_phy_base + I2C_HDMI_STAT); |
| 195 |
| 196 writeb(I2C_CLK_PEND_INT, |
| 197 i2c_hdmi_phy_base + I2C_HDMI_CON); |
| 198 |
| 199 writeb(I2C_MODE_MRX, i2c_hdmi_phy_base + I2C_HDMI_STAT); |
| 200 |
| 201 while (readb(i2c_hdmi_phy_base + I2C_HDMI_STAT) & |
| 202 (1<<5)) |
| 203 ; |
| 204 proc = false; |
| 205 |
| 206 break; |
| 207 |
| 208 case STATE_IDLE: |
| 209 |
| 210 default: |
| 211 HDMIPRINTK("error state!!!\n"); |
| 212 |
| 213 ret = EINVAL; |
| 214 |
| 215 proc = false; |
| 216 |
| 217 break; |
| 218 } |
| 219 } |
| 220 |
| 221 return ret; |
| 222 } |
| 223 |
| 224 s32 i2c_hdmi_phy_write(u8 addr, u8 nbytes, u8 *buffer) |
| 225 { |
| 226 u8 reg; |
| 227 s32 ret = 0; |
| 228 u32 proc = true; |
| 229 |
| 230 i2c_hdmi_phy_context.state = STATE_TX_ADDR; |
| 231 |
| 232 i2c_hdmi_phy_context.buffer = buffer; |
| 233 i2c_hdmi_phy_context.bytes = nbytes; |
| 234 |
| 235 writeb(I2C_CLK | I2C_INT | I2C_ACK, |
| 236 i2c_hdmi_phy_base + I2C_HDMI_CON); |
| 237 writeb(I2C_ENABLE | I2C_MODE_MTX, |
| 238 i2c_hdmi_phy_base + I2C_HDMI_STAT); |
| 239 writeb(addr & 0xFE, |
| 240 i2c_hdmi_phy_base + I2C_HDMI_DS); |
| 241 writeb(I2C_ENABLE | I2C_START | I2C_MODE_MTX, |
| 242 i2c_hdmi_phy_base + I2C_HDMI_STAT); |
| 243 |
| 244 while (proc) { |
| 245 |
| 246 if (i2c_hdmi_phy_interruptwait() != 0) { |
| 247 HDMIPRINTK("interrupt wait failed!!!\n"); |
| 248 ret = EINVAL; |
| 249 break; |
| 250 } |
| 251 |
| 252 |
| 253 switch (i2c_hdmi_phy_context.state) { |
| 254 |
| 255 case STATE_TX_ADDR: |
| 256 case STATE_TX_DATA: |
| 257 i2c_hdmi_phy_context.state = STATE_TX_DATA; |
| 258 |
| 259 reg = *(i2c_hdmi_phy_context.buffer); |
| 260 |
| 261 writeb(reg, i2c_hdmi_phy_base + I2C_HDMI_DS); |
| 262 |
| 263 i2c_hdmi_phy_context.buffer++; |
| 264 --(i2c_hdmi_phy_context.bytes); |
| 265 |
| 266 if (i2c_hdmi_phy_context.bytes == 0) { |
| 267 i2c_hdmi_phy_context.state = STATE_TX_STOP; |
| 268 writeb(I2C_CLK_PEND_INT, |
| 269 i2c_hdmi_phy_base + I2C_HDMI_CON); |
| 270 } else |
| 271 writeb(I2C_CLK_PEND_INT | I2C_ACK, |
| 272 i2c_hdmi_phy_base + I2C_HDMI_CON); |
| 273 break; |
| 274 |
| 275 case STATE_TX_STOP: |
| 276 i2c_hdmi_phy_context.state = STATE_IDLE; |
| 277 |
| 278 writeb(I2C_MODE_MTX | I2C_ENABLE, |
| 279 i2c_hdmi_phy_base + I2C_HDMI_STAT); |
| 280 |
| 281 writeb(I2C_CLK_PEND_INT, |
| 282 i2c_hdmi_phy_base + I2C_HDMI_CON); |
| 283 |
| 284 writeb(I2C_MODE_MTX, i2c_hdmi_phy_base + I2C_HDMI_STAT); |
| 285 |
| 286 while (readb(i2c_hdmi_phy_base + |
| 287 I2C_HDMI_STAT) & (1<<5)) |
| 288 ; |
| 289 |
| 290 proc = false; |
| 291 |
| 292 break; |
| 293 |
| 294 case STATE_IDLE: |
| 295 default: |
| 296 HDMIPRINTK("error state!!!\n"); |
| 297 |
| 298 ret = EINVAL; |
| 299 |
| 300 proc = false; |
| 301 |
| 302 break; |
| 303 } |
| 304 } |
| 305 |
| 306 return ret; |
| 307 } |
| 308 |
| 309 int hdmi_phy_down(bool on, u8 addr, u8 offset, u8 *read_buffer) |
| 310 { |
| 311 u8 buff[2] = {0}; |
| 312 |
| 313 buff[0] = addr; |
| 314 buff[1] = (on) ? (read_buffer[addr] & (~(1<<offset))) : |
| 315 (read_buffer[addr] | (1<<offset)); |
| 316 |
| 317 if (i2c_hdmi_phy_write(PHY_I2C_ADDRESS, 2, buff) != 0) |
| 318 return EINVAL; |
| 319 |
| 320 return 0; |
| 321 } |
| 322 |
| 323 |
| 324 int tv_hdmi_phy_power(bool on) |
| 325 { |
| 326 u32 size; |
| 327 u8 *buffer; |
| 328 u8 read_buffer[0x40] = {0, }; |
| 329 |
| 330 size = sizeof(phy_config[0][0]) |
| 331 / sizeof(phy_config[0][0][0]); |
| 332 |
| 333 buffer = (u8 *) phy_config[0][0]; |
| 334 |
| 335 /* write offset */ |
| 336 if (i2c_hdmi_phy_write(PHY_I2C_ADDRESS, 1, buffer) != 0) |
| 337 return EINVAL; |
| 338 |
| 339 /* read data */ |
| 340 if (i2c_hdmi_phy_read(PHY_I2C_ADDRESS, size, read_buffer) != 0) { |
| 341 HDMIPRINTK("i2c_hdmi_phy_read failed.\n"); |
| 342 return EINVAL; |
| 343 } |
| 344 |
| 345 /* i can't get the information about phy setting */ |
| 346 if (on) { |
| 347 /* on */ |
| 348 /* biaspd */ |
| 349 hdmi_phy_down(true, 0x1, 0x5, read_buffer); |
| 350 /* clockgenpd */ |
| 351 hdmi_phy_down(true, 0x1, 0x7, read_buffer); |
| 352 /* pllpd */ |
| 353 hdmi_phy_down(true, 0x5, 0x5, read_buffer); |
| 354 /* pcgpd */ |
| 355 hdmi_phy_down(true, 0x17, 0x0, read_buffer); |
| 356 /* txpd */ |
| 357 hdmi_phy_down(true, 0x17, 0x1, read_buffer); |
| 358 } else { |
| 359 /* off */ |
| 360 /* biaspd */ |
| 361 hdmi_phy_down(false, 0x1, 0x5, read_buffer); |
| 362 /* clockgenpd */ |
| 363 hdmi_phy_down(false, 0x1, 0x7, read_buffer); |
| 364 /* pllpd */ |
| 365 hdmi_phy_down(false, 0x5, 0x5, read_buffer); |
| 366 /* pcgpd */ |
| 367 hdmi_phy_down(false, 0x17, 0x0, read_buffer); |
| 368 /* txpd */ |
| 369 hdmi_phy_down(false, 0x17, 0x1, read_buffer); |
| 370 } |
| 371 |
| 372 return 0; |
| 373 } |
| 374 |
| 375 s32 hdmi_corereset(void) |
| 376 { |
| 377 u32 i; |
| 378 |
| 379 writeb(0x0, hdmi_base + S5P_HDMI_CTRL_CORE_RSTOUT); |
| 380 |
| 381 for (i = 0 ; i < 1000 ; i++) |
| 382 ; |
| 383 |
| 384 writeb(0x1, hdmi_base + S5P_HDMI_CTRL_CORE_RSTOUT); |
| 385 |
| 386 return 0; |
| 387 } |
| 388 |
| 389 s32 hdmi_phy_config(enum phy_freq freq, enum s5p_hdmi_color_depth cd) |
| 390 { |
| 391 s32 index; |
| 392 s32 size; |
| 393 u8 buffer[32] = {0, }; |
| 394 u8 reg; |
| 395 |
| 396 switch (cd) { |
| 397 |
| 398 case HDMI_CD_24: |
| 399 index = 0; |
| 400 break; |
| 401 |
| 402 case HDMI_CD_30: |
| 403 index = 1; |
| 404 break; |
| 405 |
| 406 case HDMI_CD_36: |
| 407 index = 2; |
| 408 break; |
| 409 |
| 410 default: |
| 411 return false; |
| 412 } |
| 413 |
| 414 |
| 415 /* i2c_hdmi init - set i2c filtering */ |
| 416 buffer[0] = PHY_REG_MODE_SET_DONE; |
| 417 buffer[1] = 0x00; |
| 418 |
| 419 if (i2c_hdmi_phy_write(PHY_I2C_ADDRESS, 2, buffer) != 0) { |
| 420 HDMIPRINTK("i2c_hdmi_phy_write failed.\n"); |
| 421 return EINVAL; |
| 422 } |
| 423 |
| 424 writeb(0x5, i2c_hdmi_phy_base + I2C_HDMI_LC); |
| 425 |
| 426 size = sizeof(phy_config[freq][index]) |
| 427 / sizeof(phy_config[freq][index][0]); |
| 428 |
| 429 memcpy(buffer, phy_config[freq][index], sizeof(buffer)); |
| 430 |
| 431 if (i2c_hdmi_phy_write(PHY_I2C_ADDRESS, size, buffer) != 0) |
| 432 return EINVAL; |
| 433 |
| 434 /* write offset */ |
| 435 buffer[0] = 0x01; |
| 436 |
| 437 if (i2c_hdmi_phy_write(PHY_I2C_ADDRESS, 1, buffer) != 0) { |
| 438 HDMIPRINTK("i2c_hdmi_phy_write failed.\n"); |
| 439 return EINVAL; |
| 440 } |
| 441 |
| 442 #ifdef S5P_HDMI_DEBUG |
| 443 { |
| 444 int i = 0; |
| 445 u8 read_buffer[0x40] = {0, }; |
| 446 |
| 447 /* read data */ |
| 448 if (i2c_hdmi_phy_read(PHY_I2C_ADDRESS, size, read_buffer) != 0) { |
| 449 HDMIPRINTK("i2c_hdmi_phy_read failed.\n"); |
| 450 return EINVAL; |
| 451 } |
| 452 |
| 453 HDMIPRINTK("read buffer :\n\t\t"); |
| 454 |
| 455 for (i = 1; i < size; i++) { |
| 456 |
| 457 |
| 458 printk("0x%02x", read_buffer[i]); |
| 459 |
| 460 if (i % 8) |
| 461 printk(" "); |
| 462 else |
| 463 printk("\n\t\t"); |
| 464 } |
| 465 printk("\n"); |
| 466 } |
| 467 #endif |
| 468 hdmi_corereset(); |
| 469 |
| 470 do { |
| 471 reg = readb(hdmi_base + HDMI_PHY_STATUS); |
| 472 } while (!(reg & HDMI_PHY_READY)); |
| 473 |
| 474 writeb(I2C_CLK_PEND_INT, i2c_hdmi_phy_base + I2C_HDMI_CON); |
| 475 /* disable */ |
| 476 writeb(I2C_IDLE, i2c_hdmi_phy_base + I2C_HDMI_STAT); |
| 477 |
| 478 return 0; |
| 479 } |
| 480 |
| 481 s32 hdmi_set_tg(enum s5p_hdmi_v_fmt mode) |
| 482 { |
| 483 u16 temp_reg; |
| 484 u8 tc_cmd; |
| 485 |
| 486 temp_reg = hdmi_tg_param[mode].h_fsz; |
| 487 writeb((u8)(temp_reg&0xff), hdmi_base + S5P_TG_H_FSZ_L); |
| 488 writeb((u8)(temp_reg >> 8), hdmi_base + S5P_TG_H_FSZ_H); |
| 489 |
| 490 /* set Horizontal Active Start Position */ |
| 491 temp_reg = hdmi_tg_param[mode].hact_st ; |
| 492 writeb((u8)(temp_reg&0xff), hdmi_base + S5P_TG_HACT_ST_L); |
| 493 writeb((u8)(temp_reg >> 8), hdmi_base + S5P_TG_HACT_ST_H); |
| 494 |
| 495 /* set Horizontal Active Size */ |
| 496 temp_reg = hdmi_tg_param[mode].hact_sz ; |
| 497 writeb((u8)(temp_reg&0xff), hdmi_base + S5P_TG_HACT_SZ_L); |
| 498 writeb((u8)(temp_reg >> 8), hdmi_base + S5P_TG_HACT_SZ_H); |
| 499 |
| 500 /* set Vertical Full Size */ |
| 501 temp_reg = hdmi_tg_param[mode].v_fsz ; |
| 502 writeb((u8)(temp_reg&0xff), hdmi_base + S5P_TG_V_FSZ_L); |
| 503 writeb((u8)(temp_reg >> 8), hdmi_base + S5P_TG_V_FSZ_H); |
| 504 |
| 505 /* set VSYNC Position */ |
| 506 temp_reg = hdmi_tg_param[mode].vsync ; |
| 507 writeb((u8)(temp_reg&0xff), hdmi_base + S5P_TG_VSYNC_L); |
| 508 writeb((u8)(temp_reg >> 8), hdmi_base + S5P_TG_VSYNC_H); |
| 509 |
| 510 /* set Bottom Field VSYNC Position */ |
| 511 temp_reg = hdmi_tg_param[mode].vsync2; |
| 512 writeb((u8)(temp_reg&0xff), hdmi_base + S5P_TG_VSYNC2_L); |
| 513 writeb((u8)(temp_reg >> 8), hdmi_base + S5P_TG_VSYNC2_H); |
| 514 |
| 515 /* set Vertical Active Start Position */ |
| 516 temp_reg = hdmi_tg_param[mode].vact_st ; |
| 517 writeb((u8)(temp_reg&0xff), hdmi_base + S5P_TG_VACT_ST_L); |
| 518 writeb((u8)(temp_reg >> 8), hdmi_base + S5P_TG_VACT_ST_H); |
| 519 |
| 520 /* set Vertical Active Size */ |
| 521 temp_reg = hdmi_tg_param[mode].vact_sz ; |
| 522 writeb((u8)(temp_reg&0xff), hdmi_base + S5P_TG_VACT_SZ_L); |
| 523 writeb((u8)(temp_reg >> 8), hdmi_base + S5P_TG_VACT_SZ_H); |
| 524 |
| 525 /* set Field Change Position */ |
| 526 temp_reg = hdmi_tg_param[mode].field_chg ; |
| 527 writeb((u8)(temp_reg&0xff), hdmi_base + S5P_TG_FIELD_CHG_L); |
| 528 writeb((u8)(temp_reg >> 8), hdmi_base + S5P_TG_FIELD_CHG_H); |
| 529 |
| 530 /* set Bottom Field Vertical Active Start Position */ |
| 531 temp_reg = hdmi_tg_param[mode].vact_st2; |
| 532 writeb((u8)(temp_reg&0xff), hdmi_base + S5P_TG_VACT_ST2_L); |
| 533 writeb((u8)(temp_reg >> 8), hdmi_base + S5P_TG_VACT_ST2_H); |
| 534 |
| 535 /* set VSYNC Position for HDMI */ |
| 536 temp_reg = hdmi_tg_param[mode].vsync_top_hdmi; |
| 537 writeb((u8)(temp_reg&0xff), hdmi_base + S5P_TG_VSYNC_TOP_HDMI_L); |
| 538 writeb((u8)(temp_reg >> 8), hdmi_base + S5P_TG_VSYNC_TOP_HDMI_H); |
| 539 |
| 540 /* set Bottom Field VSYNC Position */ |
| 541 temp_reg = hdmi_tg_param[mode].vsync_bot_hdmi; |
| 542 writeb((u8)(temp_reg&0xff), hdmi_base + S5P_TG_VSYNC_BOT_HDMI_L); |
| 543 writeb((u8)(temp_reg >> 8), hdmi_base + S5P_TG_VSYNC_BOT_HDMI_H); |
| 544 |
| 545 /* set Top Field Change Position for HDMI */ |
| 546 temp_reg = hdmi_tg_param[mode].field_top_hdmi ; |
| 547 writeb((u8)(temp_reg&0xff), hdmi_base + S5P_TG_FIELD_TOP_HDMI_L); |
| 548 writeb((u8)(temp_reg >> 8), hdmi_base + S5P_TG_FIELD_TOP_HDMI_H); |
| 549 |
| 550 /* set Bottom Field Change Position for HDMI */ |
| 551 temp_reg = hdmi_tg_param[mode].field_bot_hdmi; |
| 552 writeb((u8)(temp_reg&0xff), hdmi_base + S5P_TG_FIELD_BOT_HDMI_L); |
| 553 writeb((u8)(temp_reg >> 8), hdmi_base + S5P_TG_FIELD_BOT_HDMI_H); |
| 554 |
| 555 tc_cmd = readb(hdmi_base + S5P_TG_CMD); |
| 556 |
| 557 if (video_params[mode].interlaced == 1) |
| 558 /* Field Mode enable(interlace mode) */ |
| 559 tc_cmd |= (1<<1); |
| 560 else |
| 561 /* Field Mode disable */ |
| 562 tc_cmd &= ~(1<<1); |
| 563 |
| 564 writeb(tc_cmd, hdmi_base + S5P_TG_CMD); |
| 565 |
| 566 return 0; |
| 567 } |
| 568 |
| 569 /** |
| 570 * Set registers related to color depth. |
| 571 */ |
| 572 static s32 hdmi_set_clr_depth(enum s5p_hdmi_color_depth cd) |
| 573 { |
| 574 /* if color depth is supported by RX, set GCP packet */ |
| 575 switch (cd) { |
| 576 |
| 577 case HDMI_CD_48: |
| 578 writeb(GCP_CD_48BPP, hdmi_base + S5P_GCP_BYTE2); |
| 579 break; |
| 580 |
| 581 case HDMI_CD_36: |
| 582 writeb(GCP_CD_36BPP, hdmi_base + S5P_GCP_BYTE2); |
| 583 /* set DC register */ |
| 584 writeb(HDMI_DC_CTL_12, hdmi_base + S5P_HDMI_DC_CONTROL); |
| 585 break; |
| 586 |
| 587 case HDMI_CD_30: |
| 588 writeb(GCP_CD_30BPP, hdmi_base + S5P_GCP_BYTE2); |
| 589 /* set DC register */ |
| 590 writeb(HDMI_DC_CTL_10, hdmi_base + S5P_HDMI_DC_CONTROL); |
| 591 break; |
| 592 |
| 593 case HDMI_CD_24: |
| 594 writeb(GCP_CD_24BPP, hdmi_base + S5P_GCP_BYTE2); |
| 595 /* set DC register */ |
| 596 writeb(HDMI_DC_CTL_8, hdmi_base + S5P_HDMI_DC_CONTROL); |
| 597 /* disable GCP */ |
| 598 writeb(DO_NOT_TRANSMIT, hdmi_base + S5P_GCP_CON); |
| 599 break; |
| 600 |
| 601 default: |
| 602 HDMIPRINTK( |
| 603 "HDMI core does not support requested Deep Color mode\n"); |
| 604 return -EINVAL; |
| 605 } |
| 606 |
| 607 return 0; |
| 608 } |
| 609 |
| 610 s32 hdmi_set_video_mode(enum s5p_hdmi_v_fmt mode, enum s5p_hdmi_color_depth cd, |
| 611 enum s5p_tv_hdmi_pxl_aspect pxl_ratio) |
| 612 { |
| 613 u8 temp_reg8; |
| 614 u16 temp_reg16; |
| 615 u32 temp_reg32, temp_sync2, temp_sync3; |
| 616 |
| 617 /* check if HDMI code support that mode */ |
| 618 if (mode > (sizeof(video_params)/sizeof(struct hdmi_v_params)) || |
| 619 (s32)mode < 0) { |
| 620 HDMIPRINTK("This video mode is not Supported\n"); |
| 621 return -EINVAL; |
| 622 } |
| 623 |
| 624 hdmi_set_tg(mode); |
| 625 |
| 626 /* set HBlank */ |
| 627 temp_reg16 = video_params[mode].h_blank; |
| 628 writeb((u8)(temp_reg16&0xff), hdmi_base + S5P_H_BLANK_0); |
| 629 writeb((u8)(temp_reg16 >> 8), hdmi_base + S5P_H_BLANK_1); |
| 630 |
| 631 /* set VBlank */ |
| 632 temp_reg32 = video_params[mode].v_blank; |
| 633 writeb((u8)(temp_reg32&0xff), hdmi_base + S5P_V_BLANK_0); |
| 634 writeb((u8)(temp_reg32 >> 8), hdmi_base + S5P_V_BLANK_1); |
| 635 writeb((u8)(temp_reg32 >> 16), hdmi_base + S5P_V_BLANK_2); |
| 636 |
| 637 /* set HVLine */ |
| 638 temp_reg32 = video_params[mode].hvline; |
| 639 writeb((u8)(temp_reg32&0xff), hdmi_base + S5P_H_V_LINE_0); |
| 640 writeb((u8)(temp_reg32 >> 8), hdmi_base + S5P_H_V_LINE_1); |
| 641 writeb((u8)(temp_reg32 >> 16), hdmi_base + S5P_H_V_LINE_2); |
| 642 |
| 643 /* set VSYNC polarity */ |
| 644 writeb(video_params[mode].polarity, hdmi_base + S5P_SYNC_MODE); |
| 645 |
| 646 /* set HSyncGen */ |
| 647 temp_reg32 = video_params[mode].h_sync_gen; |
| 648 writeb((u8)(temp_reg32&0xff), hdmi_base + S5P_H_SYNC_GEN_0); |
| 649 writeb((u8)(temp_reg32 >> 8), hdmi_base + S5P_H_SYNC_GEN_1); |
| 650 writeb((u8)(temp_reg32 >> 16), hdmi_base + S5P_H_SYNC_GEN_2); |
| 651 |
| 652 /* set VSyncGen1 */ |
| 653 temp_reg32 = video_params[mode].v_sync_gen; |
| 654 writeb((u8)(temp_reg32&0xff), hdmi_base + S5P_V_SYNC_GEN_1_0); |
| 655 writeb((u8)(temp_reg32 >> 8), hdmi_base + S5P_V_SYNC_GEN_1_1); |
| 656 writeb((u8)(temp_reg32 >> 16), hdmi_base + S5P_V_SYNC_GEN_1_2); |
| 657 |
| 658 if (video_params[mode].interlaced) { |
| 659 /* set up v_blank_f, v_sync_gen2, v_sync_gen3 */ |
| 660 temp_reg32 = video_params[mode].v_blank_f; |
| 661 temp_sync2 = video_params[mode].v_sync_gen2; |
| 662 temp_sync3 = video_params[mode].v_sync_gen3; |
| 663 |
| 664 writeb((u8)(temp_reg32 & 0xff), hdmi_base + S5P_V_BLANK_F_0); |
| 665 writeb((u8)(temp_reg32 >> 8), hdmi_base + S5P_V_BLANK_F_1); |
| 666 writeb((u8)(temp_reg32 >> 16), hdmi_base + S5P_V_BLANK_F_2); |
| 667 |
| 668 writeb((u8)(temp_sync2 & 0xff), hdmi_base + S5P_V_SYNC_GEN_2_0); |
| 669 writeb((u8)(temp_sync2 >> 8), hdmi_base + S5P_V_SYNC_GEN_2_1); |
| 670 writeb((u8)(temp_sync2 >> 16), hdmi_base + S5P_V_SYNC_GEN_2_2); |
| 671 |
| 672 writeb((u8)(temp_sync3 & 0xff), hdmi_base + S5P_V_SYNC_GEN_3_0); |
| 673 writeb((u8)(temp_sync3 >> 8), hdmi_base + S5P_V_SYNC_GEN_3_1); |
| 674 writeb((u8)(temp_sync3 >> 16), hdmi_base + S5P_V_SYNC_GEN_3_2); |
| 675 } else { |
| 676 /* progressive mode */ |
| 677 writeb(0x00, hdmi_base + S5P_V_BLANK_F_0); |
| 678 writeb(0x00, hdmi_base + S5P_V_BLANK_F_1); |
| 679 writeb(0x00, hdmi_base + S5P_V_BLANK_F_2); |
| 680 |
| 681 writeb(0x01, hdmi_base + S5P_V_SYNC_GEN_2_0); |
| 682 writeb(0x10, hdmi_base + S5P_V_SYNC_GEN_2_1); |
| 683 writeb(0x00, hdmi_base + S5P_V_SYNC_GEN_2_2); |
| 684 |
| 685 writeb(0x01, hdmi_base + S5P_V_SYNC_GEN_3_0); |
| 686 writeb(0x10, hdmi_base + S5P_V_SYNC_GEN_3_1); |
| 687 writeb(0x00, hdmi_base + S5P_V_SYNC_GEN_3_2); |
| 688 } |
| 689 |
| 690 /* set interlaced mode */ |
| 691 writeb(video_params[mode].interlaced, hdmi_base + S5P_INT_PRO_MODE); |
| 692 |
| 693 /* pixel repetition */ |
| 694 temp_reg8 = readb(hdmi_base + S5P_HDMI_CON_1); |
| 695 |
| 696 /* clear */ |
| 697 temp_reg8 &= ~HDMI_CON_PXL_REP_RATIO_MASK; |
| 698 |
| 699 if (video_params[mode].repetition) { |
| 700 /* set pixel repetition */ |
| 701 temp_reg8 |= HDMI_DOUBLE_PIXEL_REPETITION; |
| 702 /* AVI Packet */ |
| 703 writeb(AVI_PIXEL_REPETITION_DOUBLE, hdmi_base + S5P_AVI_BYTE5); |
| 704 } else/* clear pixel repetition */ |
| 705 writeb(0x00, hdmi_base + S5P_AVI_BYTE5); /* AVI Packet */ |
| 706 |
| 707 /* set pixel repetition */ |
| 708 writeb(temp_reg8, hdmi_base + S5P_HDMI_CON_1); |
| 709 |
| 710 /* set AVI packet VIC */ |
| 711 if (pxl_ratio == HDMI_PIXEL_RATIO_16_9) |
| 712 writeb(video_params[mode].avi_vic_16_9, |
| 713 hdmi_base + S5P_AVI_BYTE4); |
| 714 else |
| 715 writeb(video_params[mode].avi_vic, |
| 716 hdmi_base + S5P_AVI_BYTE4); |
| 717 |
| 718 /* clear */ |
| 719 temp_reg8 = readb(hdmi_base + S5P_AVI_BYTE2) & |
| 720 ~(AVI_PICTURE_ASPECT_4_3 | AVI_PICTURE_ASPECT_16_9); |
| 721 |
| 722 if (pxl_ratio == HDMI_PIXEL_RATIO_16_9) |
| 723 temp_reg8 |= AVI_PICTURE_ASPECT_16_9; |
| 724 else |
| 725 temp_reg8 |= AVI_PICTURE_ASPECT_4_3; |
| 726 |
| 727 /* set AVI packet MM */ |
| 728 writeb(temp_reg8, hdmi_base + S5P_AVI_BYTE2); |
| 729 |
| 730 /* set color depth */ |
| 731 if (hdmi_set_clr_depth(cd) != 0) { |
| 732 HDMIPRINTK("[ERR] Can't set hdmi clr. depth.\n"); |
| 733 return -EINVAL; |
| 734 } |
| 735 |
| 736 if (video_params[mode].interlaced == 1) { |
| 737 u32 gcp_con; |
| 738 |
| 739 gcp_con = readb(hdmi_base + S5P_GCP_CON); |
| 740 gcp_con |= (3<<2); |
| 741 |
| 742 writeb(gcp_con, hdmi_base + S5P_GCP_CON); |
| 743 } else { |
| 744 u32 gcp_con; |
| 745 |
| 746 gcp_con = readb(hdmi_base + S5P_GCP_CON); |
| 747 gcp_con &= (~(3<<2)); |
| 748 |
| 749 writeb(gcp_con, hdmi_base + S5P_GCP_CON); |
| 750 } |
| 751 |
| 752 return 0; |
| 753 } |
| 754 |
| 755 |
| 756 void tv_hdmi_set_hpd_onoff(bool on_off) |
| 757 { |
| 758 HDMIPRINTK("hpd is %s\n\r", on_off ? "on" : "off"); |
| 759 |
| 760 if (on_off) |
| 761 writel(SW_HPD_PLUGGED, hdmi_base + S5P_HPD); |
| 762 else |
| 763 writel(SW_HPD_UNPLUGGED, hdmi_base + S5P_HPD); |
| 764 |
| 765 HDMIPRINTK("0x%08x\n\r", readl(hdmi_base + S5P_HPD)); |
| 766 } |
| 767 |
| 768 |
| 769 void tv_hdmi_audio_set_config(enum s5p_tv_audio_codec_type audio_codec) |
| 770 { |
| 771 |
| 772 u32 data_type = (audio_codec == PCM) ? CONFIG_LINEAR_PCM_TYPE : |
| 773 (audio_codec == AC3) ? |
| 774 CONFIG_NON_LINEAR_PCM_TYPE : 0xff; |
| 775 |
| 776 HDMIPRINTK("audio codec type = %s\n\r", |
| 777 (audio_codec&PCM) ? "PCM" : |
| 778 (audio_codec&AC3) ? "AC3" : |
| 779 (audio_codec&MP3) ? "MP3" : |
| 780 (audio_codec&WMA) ? "WMA" : "Unknown"); |
| 781 |
| 782 /* open SPDIF path on HDMI_I2S */ |
| 783 writel(0x01, hdmi_base + S5P_HDMI_I2S_CLK_CON); |
| 784 writel(readl(hdmi_base + S5P_HDMI_I2S_MUX_CON) | 0x11, |
| 785 hdmi_base + S5P_HDMI_I2S_MUX_CON); |
| 786 writel(0xFF, hdmi_base + S5P_HDMI_I2S_MUX_CH); |
| 787 writel(0x03, hdmi_base + S5P_HDMI_I2S_MUX_CUV); |
| 788 |
| 789 writel(CONFIG_FILTER_2_SAMPLE | data_type |
| 790 | CONFIG_PCPD_MANUAL_SET | CONFIG_WORD_LENGTH_MANUAL_SET |
| 791 | CONFIG_U_V_C_P_REPORT | CONFIG_BURST_SIZE_2 |
| 792 | CONFIG_DATA_ALIGN_32BIT |
| 793 , hdmi_base + S5P_SPDIFIN_CONFIG_1); |
| 794 writel(0, hdmi_base + S5P_SPDIFIN_CONFIG_2); |
| 795 } |
| 796 |
| 797 void tv_hdmi_audio_set_acr(u32 sample_rate) |
| 798 { |
| 799 u32 value_n = (sample_rate == 32000) ? 4096 : |
| 800 (sample_rate == 44100) ? 6272 : |
| 801 (sample_rate == 88200) ? 12544 : |
| 802 (sample_rate == 176400) ? 25088 : |
| 803 (sample_rate == 48000) ? 6144 : |
| 804 (sample_rate == 96000) ? 12288 : |
| 805 (sample_rate == 192000) ? 24576 : 0; |
| 806 |
| 807 u32 cts = (sample_rate == 32000) ? 27000 : |
| 808 (sample_rate == 44100) ? 30000 : |
| 809 (sample_rate == 88200) ? 30000 : |
| 810 (sample_rate == 176400) ? 30000 : |
| 811 (sample_rate == 48000) ? 27000 : |
| 812 (sample_rate == 96000) ? 27000 : |
| 813 (sample_rate == 192000) ? 27000 : 0; |
| 814 |
| 815 HDMIPRINTK("sample rate = %d\n\r", sample_rate); |
| 816 HDMIPRINTK("cts = %d\n\r", cts); |
| 817 |
| 818 writel(value_n & 0xff, hdmi_base + S5P_ACR_N0); |
| 819 writel((value_n >> 8) & 0xff, hdmi_base + S5P_ACR_N1); |
| 820 writel((value_n >> 16) & 0xff, hdmi_base + S5P_ACR_N2); |
| 821 |
| 822 writel(cts & 0xff, hdmi_base + S5P_ACR_MCTS0); |
| 823 writel((cts >> 8) & 0xff, hdmi_base + S5P_ACR_MCTS1); |
| 824 writel((cts >> 16) & 0xff, hdmi_base + S5P_ACR_MCTS2); |
| 825 |
| 826 writel(cts & 0xff, hdmi_base + S5P_ACR_CTS0); |
| 827 writel((cts >> 8) & 0xff, hdmi_base + S5P_ACR_CTS1); |
| 828 writel((cts >> 16) & 0xff, hdmi_base + S5P_ACR_CTS2); |
| 829 |
| 830 writel(4, hdmi_base + S5P_ACR_CON); /* TO-DO : what it is? */ |
| 831 } |
| 832 |
| 833 void tv_hdmi_audio_set_asp(void) |
| 834 { |
| 835 writel(0x0, hdmi_base + S5P_ASP_CON); |
| 836 /* All Subpackets contain audio samples */ |
| 837 writel(0x0, hdmi_base + S5P_ASP_SP_FLAT); |
| 838 |
| 839 writel(1 << 3 | 0, hdmi_base + S5P_ASP_CHCFG0); |
| 840 writel(1 << 3 | 0, hdmi_base + S5P_ASP_CHCFG1); |
| 841 writel(1 << 3 | 0, hdmi_base + S5P_ASP_CHCFG2); |
| 842 writel(1 << 3 | 0, hdmi_base + S5P_ASP_CHCFG3); |
| 843 } |
| 844 |
| 845 void tv_hdmi_audio_clock_enable(void) |
| 846 { |
| 847 writel(0x1, hdmi_base + S5P_SPDIFIN_CLK_CTRL); |
| 848 /* HDMI operation mode */ |
| 849 writel(0x3, hdmi_base + S5P_SPDIFIN_OP_CTRL); |
| 850 } |
| 851 |
| 852 |
| 853 void tv_hdmi_audio_set_repetition_time(enum s5p_tv_audio_codec_type audio_codec, |
| 854 u32 bits, u32 frame_size_code) |
| 855 { |
| 856 /* Only 4'b1011 24bit */ |
| 857 u32 wl = 5 << 1 | 1; |
| 858 u32 rpt_cnt = (audio_codec == AC3) ? 1536 * 2 - 1 : 0; |
| 859 |
| 860 HDMIPRINTK("repetition count = %d\n\r", rpt_cnt); |
| 861 |
| 862 /* 24bit and manual mode */ |
| 863 writel(((rpt_cnt&0xf) << 4) | wl, hdmi_base + S5P_SPDIFIN_USER_VALUE_1); |
| 864 /* if PCM this value is 0 */ |
| 865 writel((rpt_cnt >> 4)&0xff, hdmi_base + S5P_SPDIFIN_USER_VALUE_2); |
| 866 /* if PCM this value is 0 */ |
| 867 writel(frame_size_code&0xff, hdmi_base + S5P_SPDIFIN_USER_VALUE_3); |
| 868 /* if PCM this value is 0 */ |
| 869 writel((frame_size_code >> 8)&0xff, |
| 870 hdmi_base + S5P_SPDIFIN_USER_VALUE_4); |
| 871 } |
| 872 |
| 873 void tv_hdmi_audio_irq_enable(u32 irq_en) |
| 874 { |
| 875 writel(irq_en, hdmi_base + S5P_SPDIFIN_IRQ_MASK); |
| 876 } |
| 877 |
| 878 |
| 879 void tv_hdmi_audio_set_aui(enum s5p_tv_audio_codec_type audio_codec, |
| 880 u32 sample_rate, |
| 881 u32 bits) |
| 882 { |
| 883 u8 sum_of_bits, bytes1, bytes2, bytes3, check_sum; |
| 884 u32 bit_rate; |
| 885 /* Ac3 16bit only */ |
| 886 u32 bps = (audio_codec == PCM) ? bits : 16; |
| 887 |
| 888 /* AUI Packet set. */ |
| 889 u32 type = (audio_codec == PCM) ? 1 : /* PCM */ |
| 890 (audio_codec == AC3) ? 2 : 0; |
| 891 /* AC3 or Refer stream header */ |
| 892 u32 ch = (audio_codec == PCM) ? 1 : 0; |
| 893 /* 2ch or refer to stream header */ |
| 894 |
| 895 u32 sample = (sample_rate == 32000) ? 1 : |
| 896 (sample_rate == 44100) ? 2 : |
| 897 (sample_rate == 48000) ? 3 : |
| 898 (sample_rate == 88200) ? 4 : |
| 899 (sample_rate == 96000) ? 5 : |
| 900 (sample_rate == 176400) ? 6 : |
| 901 (sample_rate == 192000) ? 7 : 0; |
| 902 |
| 903 u32 bpsType = (bps == 16) ? 1 : |
| 904 (bps == 20) ? 2 : |
| 905 (bps == 24) ? 3 : 0; |
| 906 |
| 907 |
| 908 bpsType = (audio_codec == PCM) ? bpsType : 0; |
| 909 |
| 910 sum_of_bits = (0x84 + 0x1 + 10); /* header */ |
| 911 |
| 912 bytes1 = (u8)((type << 4) | ch); |
| 913 |
| 914 bytes2 = (u8)((sample << 2) | bpsType); |
| 915 |
| 916 bit_rate = 256; /* AC3 Test */ |
| 917 |
| 918 bytes3 = (audio_codec == PCM) ? (u8)0 : (u8)(bit_rate / 8) ; |
| 919 |
| 920 |
| 921 sum_of_bits += (bytes1 + bytes2 + bytes3); |
| 922 check_sum = 256 - sum_of_bits; |
| 923 |
| 924 /* AUI Packet set. */ |
| 925 writel(check_sum , hdmi_base + S5P_AUI_CHECK_SUM); |
| 926 writel(bytes1 , hdmi_base + S5P_AUI_BYTE1); |
| 927 writel(bytes2 , hdmi_base + S5P_AUI_BYTE2); |
| 928 writel(bytes3 , hdmi_base + S5P_AUI_BYTE3); /* Pcm or stream */ |
| 929 writel(0x00 , hdmi_base + S5P_AUI_BYTE4); /* 2ch pcm or Stream */ |
| 930 writel(0x00 , hdmi_base + S5P_AUI_BYTE5); /* 2ch pcm or Stream */ |
| 931 |
| 932 |
| 933 writel(2 , hdmi_base + S5P_ACP_CON); |
| 934 writel(1 , hdmi_base + S5P_ACP_TYPE); |
| 935 |
| 936 writel(0x10 , hdmi_base + S5P_GCP_BYTE1); |
| 937 |
| 938 } |
| 939 |
| 940 void tv_hdmi_video_set_bluescreen(bool en, |
| 941 u8 cb_b, |
| 942 u8 y_g, |
| 943 u8 cr_r) |
| 944 { |
| 945 HDMIPRINTK("%d,%d,%d,%d\n\r", en, cb_b, y_g, cr_r); |
| 946 |
| 947 if (en) { |
| 948 writel(SET_BLUESCREEN_0(cb_b), hdmi_base + S5P_BLUE_SCREEN_0); |
| 949 writel(SET_BLUESCREEN_1(y_g), hdmi_base + S5P_BLUE_SCREEN_1); |
| 950 writel(SET_BLUESCREEN_2(cr_r), hdmi_base + S5P_BLUE_SCREEN_2); |
| 951 writel(readl(hdmi_base + S5P_HDMI_CON_0) | BLUE_SCR_EN, |
| 952 hdmi_base + S5P_HDMI_CON_0); |
| 953 |
| 954 HDMIPRINTK("HDMI_BLUE_SCREEN0 = 0x%08x \n\r", |
| 955 readl(hdmi_base + S5P_BLUE_SCREEN_0)); |
| 956 HDMIPRINTK("HDMI_BLUE_SCREEN1 = 0x%08x \n\r", |
| 957 readl(hdmi_base + S5P_BLUE_SCREEN_1)); |
| 958 HDMIPRINTK("HDMI_BLUE_SCREEN2 = 0x%08x \n\r", |
| 959 readl(hdmi_base + S5P_BLUE_SCREEN_2)); |
| 960 } else { |
| 961 writel(readl(hdmi_base + S5P_HDMI_CON_0)&~BLUE_SCR_EN, |
| 962 hdmi_base + S5P_HDMI_CON_0); |
| 963 } |
| 964 |
| 965 HDMIPRINTK("HDMI_CON0 = 0x%08x \n\r", |
| 966 readl(hdmi_base + S5P_HDMI_CON_0)); |
| 967 } |
| 968 |
| 969 |
| 970 enum s5p_tv_hdmi_err tv_hdmi_init_spd_infoframe( |
| 971 enum s5p_hdmi_transmit trans_type, |
| 972 u8 *spd_header, |
| 973 u8 *spd_data) |
| 974 { |
| 975 HDMIPRINTK("%d,%d,%d\n\r", (u32)trans_type, |
| 976 (u32)spd_header, |
| 977 (u32)spd_data); |
| 978 |
| 979 switch (trans_type) { |
| 980 |
| 981 case HDMI_DO_NOT_TANS: |
| 982 writel(SPD_TX_CON_NO_TRANS, hdmi_base + S5P_SPD_CON); |
| 983 break; |
| 984 |
| 985 case HDMI_TRANS_ONCE: |
| 986 writel(SPD_TX_CON_TRANS_ONCE, hdmi_base + S5P_SPD_CON); |
| 987 break; |
| 988 |
| 989 case HDMI_TRANS_EVERY_SYNC: |
| 990 writel(SPD_TX_CON_TRANS_EVERY_VSYNC, hdmi_base + S5P_SPD_CON); |
| 991 break; |
| 992 |
| 993 default: |
| 994 HDMIPRINTK(" invalid out_mode parameter(%d)\n\r", trans_type); |
| 995 return S5P_TV_HDMI_ERR_INVALID_PARAM; |
| 996 } |
| 997 |
| 998 writel(SET_SPD_HEADER(*(spd_header)), hdmi_base + S5P_SPD_HEADER0); |
| 999 |
| 1000 writel(SET_SPD_HEADER(*(spd_header + 1)) , hdmi_base + S5P_SPD_HEADER1); |
| 1001 writel(SET_SPD_HEADER(*(spd_header + 2)) , hdmi_base + S5P_SPD_HEADER2); |
| 1002 |
| 1003 writel(SET_SPD_DATA(*(spd_data)), hdmi_base + S5P_SPD_DATA0); |
| 1004 writel(SET_SPD_DATA(*(spd_data + 1)) , hdmi_base + S5P_SPD_DATA1); |
| 1005 writel(SET_SPD_DATA(*(spd_data + 2)) , hdmi_base + S5P_SPD_DATA2); |
| 1006 writel(SET_SPD_DATA(*(spd_data + 3)) , hdmi_base + S5P_SPD_DATA3); |
| 1007 writel(SET_SPD_DATA(*(spd_data + 4)) , hdmi_base + S5P_SPD_DATA4); |
| 1008 writel(SET_SPD_DATA(*(spd_data + 5)) , hdmi_base + S5P_SPD_DATA5); |
| 1009 writel(SET_SPD_DATA(*(spd_data + 6)) , hdmi_base + S5P_SPD_DATA6); |
| 1010 writel(SET_SPD_DATA(*(spd_data + 7)) , hdmi_base + S5P_SPD_DATA7); |
| 1011 writel(SET_SPD_DATA(*(spd_data + 8)) , hdmi_base + S5P_SPD_DATA8); |
| 1012 writel(SET_SPD_DATA(*(spd_data + 9)) , hdmi_base + S5P_SPD_DATA9); |
| 1013 writel(SET_SPD_DATA(*(spd_data + 10)) , hdmi_base + S5P_SPD_DATA10); |
| 1014 writel(SET_SPD_DATA(*(spd_data + 11)) , hdmi_base + S5P_SPD_DATA11); |
| 1015 writel(SET_SPD_DATA(*(spd_data + 12)) , hdmi_base + S5P_SPD_DATA12); |
| 1016 writel(SET_SPD_DATA(*(spd_data + 13)) , hdmi_base + S5P_SPD_DATA13); |
| 1017 writel(SET_SPD_DATA(*(spd_data + 14)) , hdmi_base + S5P_SPD_DATA14); |
| 1018 writel(SET_SPD_DATA(*(spd_data + 15)) , hdmi_base + S5P_SPD_DATA15); |
| 1019 writel(SET_SPD_DATA(*(spd_data + 16)) , hdmi_base + S5P_SPD_DATA16); |
| 1020 writel(SET_SPD_DATA(*(spd_data + 17)) , hdmi_base + S5P_SPD_DATA17); |
| 1021 writel(SET_SPD_DATA(*(spd_data + 18)) , hdmi_base + S5P_SPD_DATA18); |
| 1022 writel(SET_SPD_DATA(*(spd_data + 19)) , hdmi_base + S5P_SPD_DATA19); |
| 1023 writel(SET_SPD_DATA(*(spd_data + 20)) , hdmi_base + S5P_SPD_DATA20); |
| 1024 writel(SET_SPD_DATA(*(spd_data + 21)) , hdmi_base + S5P_SPD_DATA21); |
| 1025 writel(SET_SPD_DATA(*(spd_data + 22)) , hdmi_base + S5P_SPD_DATA22); |
| 1026 writel(SET_SPD_DATA(*(spd_data + 23)) , hdmi_base + S5P_SPD_DATA23); |
| 1027 writel(SET_SPD_DATA(*(spd_data + 24)) , hdmi_base + S5P_SPD_DATA24); |
| 1028 writel(SET_SPD_DATA(*(spd_data + 25)) , hdmi_base + S5P_SPD_DATA25); |
| 1029 writel(SET_SPD_DATA(*(spd_data + 26)) , hdmi_base + S5P_SPD_DATA26); |
| 1030 writel(SET_SPD_DATA(*(spd_data + 27)) , hdmi_base + S5P_SPD_DATA27); |
| 1031 |
| 1032 HDMIPRINTK("SPD_CON = 0x%08x \n\r", |
| 1033 readl(hdmi_base + S5P_SPD_CON)); |
| 1034 HDMIPRINTK("SPD_HEADER0 = 0x%08x \n\r", |
| 1035 readl(hdmi_base + S5P_SPD_HEADER0)); |
| 1036 HDMIPRINTK("SPD_HEADER1 = 0x%08x \n\r", |
| 1037 readl(hdmi_base + S5P_SPD_HEADER1)); |
| 1038 HDMIPRINTK("SPD_HEADER2 = 0x%08x \n\r", |
| 1039 readl(hdmi_base + S5P_SPD_HEADER2)); |
| 1040 HDMIPRINTK("SPD_DATA0 = 0x%08x \n\r", |
| 1041 readl(hdmi_base + S5P_SPD_DATA0)); |
| 1042 HDMIPRINTK("SPD_DATA1 = 0x%08x \n\r", |
| 1043 readl(hdmi_base + S5P_SPD_DATA1)); |
| 1044 HDMIPRINTK("SPD_DATA2 = 0x%08x \n\r", |
| 1045 readl(hdmi_base + S5P_SPD_DATA2)); |
| 1046 HDMIPRINTK("SPD_DATA3 = 0x%08x \n\r", |
| 1047 readl(hdmi_base + S5P_SPD_DATA3)); |
| 1048 HDMIPRINTK("SPD_DATA4 = 0x%08x \n\r", |
| 1049 readl(hdmi_base + S5P_SPD_DATA4)); |
| 1050 HDMIPRINTK("SPD_DATA5 = 0x%08x \n\r", |
| 1051 readl(hdmi_base + S5P_SPD_DATA5)); |
| 1052 HDMIPRINTK("SPD_DATA6 = 0x%08x \n\r", |
| 1053 readl(hdmi_base + S5P_SPD_DATA6)); |
| 1054 HDMIPRINTK("SPD_DATA7 = 0x%08x \n\r", |
| 1055 readl(hdmi_base + S5P_SPD_DATA7)); |
| 1056 HDMIPRINTK("SPD_DATA8 = 0x%08x \n\r", |
| 1057 readl(hdmi_base + S5P_SPD_DATA8)); |
| 1058 HDMIPRINTK("SPD_DATA9 = 0x%08x \n\r", |
| 1059 readl(hdmi_base + S5P_SPD_DATA9)); |
| 1060 HDMIPRINTK("SPD_DATA10 = 0x%08x \n\r", |
| 1061 readl(hdmi_base + S5P_SPD_DATA10)); |
| 1062 HDMIPRINTK("SPD_DATA11 = 0x%08x \n\r", |
| 1063 readl(hdmi_base + S5P_SPD_DATA11)); |
| 1064 HDMIPRINTK("SPD_DATA12 = 0x%08x \n\r", |
| 1065 readl(hdmi_base + S5P_SPD_DATA12)); |
| 1066 HDMIPRINTK("SPD_DATA13 = 0x%08x \n\r", |
| 1067 readl(hdmi_base + S5P_SPD_DATA13)); |
| 1068 HDMIPRINTK("SPD_DATA14 = 0x%08x \n\r", |
| 1069 readl(hdmi_base + S5P_SPD_DATA14)); |
| 1070 HDMIPRINTK("SPD_DATA15 = 0x%08x \n\r", |
| 1071 readl(hdmi_base + S5P_SPD_DATA15)); |
| 1072 HDMIPRINTK("SPD_DATA16 = 0x%08x \n\r", |
| 1073 readl(hdmi_base + S5P_SPD_DATA16)); |
| 1074 HDMIPRINTK("SPD_DATA17 = 0x%08x \n\r", |
| 1075 readl(hdmi_base + S5P_SPD_DATA17)); |
| 1076 HDMIPRINTK("SPD_DATA18 = 0x%08x \n\r", |
| 1077 readl(hdmi_base + S5P_SPD_DATA18)); |
| 1078 HDMIPRINTK("SPD_DATA19 = 0x%08x \n\r", |
| 1079 readl(hdmi_base + S5P_SPD_DATA19)); |
| 1080 HDMIPRINTK("SPD_DATA20 = 0x%08x \n\r", |
| 1081 readl(hdmi_base + S5P_SPD_DATA20)); |
| 1082 HDMIPRINTK("SPD_DATA21 = 0x%08x \n\r", |
| 1083 readl(hdmi_base + S5P_SPD_DATA21)); |
| 1084 HDMIPRINTK("SPD_DATA22 = 0x%08x \n\r", |
| 1085 readl(hdmi_base + S5P_SPD_DATA22)); |
| 1086 HDMIPRINTK("SPD_DATA23 = 0x%08x \n\r", |
| 1087 readl(hdmi_base + S5P_SPD_DATA23)); |
| 1088 HDMIPRINTK("SPD_DATA24 = 0x%08x \n\r", |
| 1089 readl(hdmi_base + S5P_SPD_DATA24)); |
| 1090 HDMIPRINTK("SPD_DATA25 = 0x%08x \n\r", |
| 1091 readl(hdmi_base + S5P_SPD_DATA25)); |
| 1092 HDMIPRINTK("SPD_DATA26 = 0x%08x \n\r", |
| 1093 readl(hdmi_base + S5P_SPD_DATA26)); |
| 1094 HDMIPRINTK("SPD_DATA27 = 0x%08x \n\r", |
| 1095 readl(hdmi_base + S5P_SPD_DATA27)); |
| 1096 |
| 1097 return HDMI_NO_ERROR; |
| 1098 } |
| 1099 |
| 1100 void tv_hdmi_init_hpd_onoff(bool on_off) |
| 1101 { |
| 1102 HDMIPRINTK("%d\n\r", on_off); |
| 1103 tv_hdmi_set_hpd_onoff(on_off); |
| 1104 HDMIPRINTK("0x%08x\n\r", readl(hdmi_base + S5P_HPD)); |
| 1105 } |
| 1106 |
| 1107 #ifndef CONFIG_SND_S5P_SPDIF |
| 1108 static void tv_hdmi_audio_i2s_config( |
| 1109 enum s5p_tv_audio_codec_type audio_codec, |
| 1110 u32 sample_rate, |
| 1111 u32 bits_per_sample, |
| 1112 u32 frame_size_code) |
| 1113 { |
| 1114 u32 data_num, bit_ch, sample_frq; |
| 1115 |
| 1116 if (bits_per_sample == 20) { |
| 1117 data_num = 2; |
| 1118 bit_ch = 1; |
| 1119 } else if (bits_per_sample == 24) { |
| 1120 data_num = 3; |
| 1121 bit_ch = 1; |
| 1122 } else { /* bits_per_sample == 16 or default */ |
| 1123 data_num = 1; |
| 1124 bit_ch = 0; |
| 1125 } |
| 1126 |
| 1127 sample_frq = (sample_rate == 44100) ? 0 : |
| 1128 (sample_rate == 48000) ? 2 : |
| 1129 (sample_rate == 32000) ? 3 : |
| 1130 (sample_rate == 96000) ? 0xa : 0x0; |
| 1131 |
| 1132 /* readl(hdmi_base + S5P_HDMI_YMAX) */ |
| 1133 writel(0x00, hdmi_base + S5P_HDMI_I2S_CLK_CON); |
| 1134 writel(0x01, hdmi_base + S5P_HDMI_I2S_CLK_CON); |
| 1135 |
| 1136 writel(readl(hdmi_base + S5P_HDMI_I2S_DSD_CON) | 0x01, |
| 1137 hdmi_base + S5P_HDMI_I2S_DSD_CON); |
| 1138 |
| 1139 /* Configuration I2S input ports. Configure I2S_PIN_SEL_0~4 */ |
| 1140 writel((readl(hdmi_base + S5P_HDMI_I2S_PIN_SEL_0) & |
| 1141 ~(7<<4 | 7<<0)) | (5<<4|6<<0), |
| 1142 hdmi_base + S5P_HDMI_I2S_PIN_SEL_0); |
| 1143 writel((readl(hdmi_base + S5P_HDMI_I2S_PIN_SEL_1) & |
| 1144 ~(7<<4 | 7<<0)) | (1<<4|4<<0), |
| 1145 hdmi_base + S5P_HDMI_I2S_PIN_SEL_1); |
| 1146 writel((readl(hdmi_base + S5P_HDMI_I2S_PIN_SEL_2) & |
| 1147 ~(7<<4 | 7<<0)) | (1<<4|2<<0), |
| 1148 hdmi_base + S5P_HDMI_I2S_PIN_SEL_2); |
| 1149 writel((readl(hdmi_base + S5P_HDMI_I2S_PIN_SEL_3) & |
| 1150 ~(7<<0)) | (0<<0), |
| 1151 hdmi_base + S5P_HDMI_I2S_PIN_SEL_3); |
| 1152 |
| 1153 /* I2S_CON_1 & 2 */ |
| 1154 writel((readl(hdmi_base + S5P_HDMI_I2S_CON_1) & |
| 1155 ~(1<<1 | 1<<0)) | (1<<1|0<<0), |
| 1156 hdmi_base + S5P_HDMI_I2S_CON_1); |
| 1157 writel((readl(hdmi_base + S5P_HDMI_I2S_CON_2) & |
| 1158 ~(1<<6 | 3<<4 | 3<<2 | 3<<0)) |
| 1159 | (0<<6 | bit_ch<<4 | data_num<<2 | 0<<0), |
| 1160 hdmi_base + S5P_HDMI_I2S_CON_2); |
| 1161 |
| 1162 /* Configure register related to CUV information */ |
| 1163 writel((readl(hdmi_base + S5P_HDMI_I2S_CH_ST_0) & |
| 1164 ~(3<<6 | 7<<3 | 1<<2 | 1<<1 | 1<<0)) |
| 1165 | (0<<6 | 0<<3 | 0<<2 | 0<<1 | 1<<0), |
| 1166 hdmi_base + S5P_HDMI_I2S_CH_ST_0); |
| 1167 writel((readl(hdmi_base + S5P_HDMI_I2S_CH_ST_1) & |
| 1168 ~(0xff<<0)) | (0<<0), |
| 1169 hdmi_base + S5P_HDMI_I2S_CH_ST_1); |
| 1170 writel((readl(hdmi_base + S5P_HDMI_I2S_CH_ST_2) & |
| 1171 ~(0xff<<0)) | (0<<0), |
| 1172 hdmi_base + S5P_HDMI_I2S_CH_ST_2); |
| 1173 writel((readl(hdmi_base + S5P_HDMI_I2S_CH_ST_3) & |
| 1174 ~(3<<4 | 0xf<<0)) |
| 1175 | (1<<4 | sample_frq<<0), |
| 1176 hdmi_base + S5P_HDMI_I2S_CH_ST_3); |
| 1177 writel((readl(hdmi_base + S5P_HDMI_I2S_CH_ST_4) & |
| 1178 ~(0xf<<4 | 7<<1 | 1<<0)) |
| 1179 | (0xf<<4 | 5<<1 | 1<<0), |
| 1180 hdmi_base + S5P_HDMI_I2S_CH_ST_4); |
| 1181 |
| 1182 writel(0x00, hdmi_base + S5P_HDMI_I2S_CH_ST_SH_0); |
| 1183 writel(0x00, hdmi_base + S5P_HDMI_I2S_CH_ST_SH_1); |
| 1184 writel(0x00, hdmi_base + S5P_HDMI_I2S_CH_ST_SH_2); |
| 1185 writel(0x02, hdmi_base + S5P_HDMI_I2S_CH_ST_SH_3); |
| 1186 writel(0x00, hdmi_base + S5P_HDMI_I2S_CH_ST_SH_4); |
| 1187 |
| 1188 writel((readl(hdmi_base + S5P_HDMI_I2S_CH_ST_CON) & |
| 1189 ~(1<<0)) | (1<<0), |
| 1190 hdmi_base + S5P_HDMI_I2S_CH_ST_CON); |
| 1191 |
| 1192 writel((readl(hdmi_base + S5P_HDMI_I2S_MUX_CON) & |
| 1193 ~(1<<4 | 3<<2 | 1<<1 | 1<<0)) |
| 1194 | (1<<4 | 1<<2 | 1<<1 | 1<<0), |
| 1195 hdmi_base + S5P_HDMI_I2S_MUX_CON); |
| 1196 |
| 1197 writel((readl(hdmi_base + S5P_HDMI_I2S_MUX_CH) & |
| 1198 ~(0xff<<0)) | (0x3f<<0), |
| 1199 hdmi_base + S5P_HDMI_I2S_MUX_CH); |
| 1200 |
| 1201 writel((readl(hdmi_base + S5P_HDMI_I2S_MUX_CUV) & |
| 1202 ~(0x3<<0)) | (0x3<<0), |
| 1203 hdmi_base + S5P_HDMI_I2S_MUX_CUV); |
| 1204 } |
| 1205 #endif |
| 1206 |
| 1207 enum s5p_tv_hdmi_err tv_hdmi_audio_init( |
| 1208 enum s5p_tv_audio_codec_type audio_codec, |
| 1209 u32 sample_rate, u32 bits, |
| 1210 u32 frame_size_code) |
| 1211 { |
| 1212 #ifdef CONFIG_SND_S5P_SPDIF |
| 1213 tv_hdmi_audio_set_config(audio_codec); |
| 1214 tv_hdmi_audio_set_repetition_time(audio_codec, bits, |
| 1215 frame_size_code); |
| 1216 tv_hdmi_audio_irq_enable(IRQ_BUFFER_OVERFLOW_ENABLE); |
| 1217 tv_hdmi_audio_clock_enable(); |
| 1218 #else |
| 1219 tv_hdmi_audio_i2s_config(audio_codec, sample_rate, |
| 1220 bits, frame_size_code); |
| 1221 #endif |
| 1222 tv_hdmi_audio_set_asp(); |
| 1223 tv_hdmi_audio_set_acr(sample_rate); |
| 1224 |
| 1225 tv_hdmi_audio_set_aui(audio_codec, sample_rate, bits); |
| 1226 |
| 1227 return HDMI_NO_ERROR; |
| 1228 } |
| 1229 |
| 1230 enum s5p_tv_hdmi_err tv_hdmi_video_init_display_mode( |
| 1231 enum s5p_tv_disp_mode disp_mode, |
| 1232 enum s5p_tv_o_mode out_mode) |
| 1233 { |
| 1234 enum s5p_hdmi_v_fmt hdmi_v_fmt; |
| 1235 |
| 1236 HDMIPRINTK("disp mode %d, output mode%d\n\r", disp_mode, out_mode); |
| 1237 |
| 1238 switch (disp_mode) { |
| 1239 /* 480p */ |
| 1240 case TVOUT_480P_60_16_9: |
| 1241 case TVOUT_480P_60_4_3: |
| 1242 hdmi_v_fmt = v720x480p_60Hz; |
| 1243 break; |
| 1244 case TVOUT_480P_59: |
| 1245 hdmi_v_fmt = v720x480p_59Hz; |
| 1246 break; |
| 1247 |
| 1248 /* 576p */ |
| 1249 case TVOUT_576P_50_16_9: |
| 1250 case TVOUT_576P_50_4_3: |
| 1251 hdmi_v_fmt = v720x576p_50Hz; |
| 1252 break; |
| 1253 |
| 1254 /* 720p */ |
| 1255 case TVOUT_720P_60: |
| 1256 hdmi_v_fmt = v1280x720p_60Hz; |
| 1257 break; |
| 1258 |
| 1259 case TVOUT_720P_59: |
| 1260 hdmi_v_fmt = v1280x720p_59Hz; |
| 1261 break; |
| 1262 |
| 1263 case TVOUT_720P_50: |
| 1264 hdmi_v_fmt = v1280x720p_50Hz; |
| 1265 break; |
| 1266 |
| 1267 /* 1080p */ |
| 1268 case TVOUT_1080P_30: |
| 1269 hdmi_v_fmt = v1920x1080p_30Hz; |
| 1270 break; |
| 1271 |
| 1272 case TVOUT_1080P_60: |
| 1273 hdmi_v_fmt = v1920x1080p_60Hz; |
| 1274 break; |
| 1275 |
| 1276 case TVOUT_1080P_59: |
| 1277 hdmi_v_fmt = v1920x1080p_59Hz; |
| 1278 break; |
| 1279 |
| 1280 case TVOUT_1080P_50: |
| 1281 hdmi_v_fmt = v1920x1080p_50Hz; |
| 1282 break; |
| 1283 |
| 1284 /* 1080i */ |
| 1285 case TVOUT_1080I_60: |
| 1286 hdmi_v_fmt = v1920x1080i_60Hz; |
| 1287 break; |
| 1288 |
| 1289 case TVOUT_1080I_59: |
| 1290 hdmi_v_fmt = v1920x1080i_59Hz; |
| 1291 break; |
| 1292 |
| 1293 case TVOUT_1080I_50: |
| 1294 hdmi_v_fmt = v1920x1080i_50Hz; |
| 1295 break; |
| 1296 |
| 1297 default: |
| 1298 HDMIPRINTK(" invalid disp_mode parameter(%d)\n\r", disp_mode); |
| 1299 return S5P_TV_HDMI_ERR_INVALID_PARAM; |
| 1300 } |
| 1301 |
| 1302 if (hdmi_phy_config(video_params[hdmi_v_fmt].pixel_clock, |
| 1303 HDMI_CD_24) == EINVAL) { |
| 1304 HDMIPRINTK("[ERR] hdmi_phy_config() failed.\n"); |
| 1305 return EINVAL; |
| 1306 } |
| 1307 |
| 1308 switch (out_mode) { |
| 1309 case TVOUT_OUTPUT_HDMI_RGB: |
| 1310 writel(PX_LMT_CTRL_RGB, hdmi_base + S5P_HDMI_CON_1); |
| 1311 writel(VID_PREAMBLE_EN | GUARD_BAND_EN, |
| 1312 hdmi_base + S5P_HDMI_CON_2); |
| 1313 writel(HDMI_MODE_EN | DVI_MODE_DIS, hdmi_base + S5P_MODE_SEL); |
| 1314 |
| 1315 /* there's no ACP packet api */ |
| 1316 writel(HDMI_DO_NOT_TANS , hdmi_base + S5P_ACP_CON); |
| 1317 writel(HDMI_TRANS_EVERY_SYNC , hdmi_base + S5P_AUI_CON); |
| 1318 break; |
| 1319 |
| 1320 case TVOUT_OUTPUT_HDMI: |
| 1321 writel(PX_LMT_CTRL_BYPASS, hdmi_base + S5P_HDMI_CON_1); |
| 1322 writel(VID_PREAMBLE_EN | GUARD_BAND_EN, |
| 1323 hdmi_base + S5P_HDMI_CON_2); |
| 1324 writel(HDMI_MODE_EN | DVI_MODE_DIS, hdmi_base + S5P_MODE_SEL); |
| 1325 |
| 1326 /* there's no ACP packet api */ |
| 1327 writel(HDMI_DO_NOT_TANS , hdmi_base + S5P_ACP_CON); |
| 1328 writel(HDMI_TRANS_EVERY_SYNC , hdmi_base + S5P_AUI_CON); |
| 1329 break; |
| 1330 |
| 1331 case TVOUT_OUTPUT_DVI: |
| 1332 writel(PX_LMT_CTRL_RGB, hdmi_base + S5P_HDMI_CON_1); |
| 1333 writel(VID_PREAMBLE_DIS | GUARD_BAND_DIS, |
| 1334 hdmi_base + S5P_HDMI_CON_2); |
| 1335 writel(HDMI_MODE_DIS | DVI_MODE_EN, |
| 1336 hdmi_base + S5P_MODE_SEL); |
| 1337 |
| 1338 /* disable ACP & Audio Info.frame packet */ |
| 1339 writel(HDMI_DO_NOT_TANS , hdmi_base + S5P_ACP_CON); |
| 1340 writel(HDMI_DO_NOT_TANS , hdmi_base + S5P_AUI_CON); |
| 1341 break; |
| 1342 |
| 1343 default: |
| 1344 HDMIPRINTK("invalid out_mode parameter(%d)\n\r", out_mode); |
| 1345 return S5P_TV_HDMI_ERR_INVALID_PARAM; |
| 1346 } |
| 1347 |
| 1348 hdmi_set_video_mode(hdmi_v_fmt, HDMI_CD_24, HDMI_PIXEL_RATIO_16_9); |
| 1349 |
| 1350 return HDMI_NO_ERROR; |
| 1351 } |
| 1352 |
| 1353 void tv_hdmi_video_init_bluescreen(bool en, |
| 1354 u8 cb_b, |
| 1355 u8 y_g, |
| 1356 u8 cr_r) |
| 1357 { |
| 1358 tv_hdmi_video_set_bluescreen(en, cb_b, y_g, cr_r); |
| 1359 |
| 1360 } |
| 1361 |
| 1362 void tv_hdmi_video_init_color_range(u8 y_min, |
| 1363 u8 y_max, |
| 1364 u8 c_min, |
| 1365 u8 c_max) |
| 1366 { |
| 1367 HDMIPRINTK("%d,%d,%d,%d\n\r", y_max, y_min, c_max, c_min); |
| 1368 |
| 1369 writel(y_max, hdmi_base + S5P_HDMI_YMAX); |
| 1370 writel(y_min, hdmi_base + S5P_HDMI_YMIN); |
| 1371 writel(c_max, hdmi_base + S5P_HDMI_CMAX); |
| 1372 writel(c_min, hdmi_base + S5P_HDMI_CMIN); |
| 1373 |
| 1374 HDMIPRINTK("HDMI_YMAX = 0x%08x \n\r", |
| 1375 readl(hdmi_base + S5P_HDMI_YMAX)); |
| 1376 HDMIPRINTK("HDMI_YMIN = 0x%08x \n\r", |
| 1377 readl(hdmi_base + S5P_HDMI_YMIN)); |
| 1378 HDMIPRINTK("HDMI_CMAX = 0x%08x \n\r", |
| 1379 readl(hdmi_base + S5P_HDMI_CMAX)); |
| 1380 HDMIPRINTK("HDMI_CMIN = 0x%08x \n\r", |
| 1381 readl(hdmi_base + S5P_HDMI_CMIN)); |
| 1382 } |
| 1383 |
| 1384 enum s5p_tv_hdmi_err tv_hdmi_video_init_csc(enum s5p_tv_hdmi_csc_type csc_type) |
| 1385 { |
| 1386 unsigned short us_csc_coeff[10]; |
| 1387 |
| 1388 HDMIPRINTK("%d)\n\r", csc_type); |
| 1389 |
| 1390 switch (csc_type) { |
| 1391 |
| 1392 case HDMI_CSC_YUV601_TO_RGB_LR: |
| 1393 us_csc_coeff[0] = 0x23; |
| 1394 us_csc_coeff[1] = 256; |
| 1395 us_csc_coeff[2] = 938; |
| 1396 us_csc_coeff[3] = 846; |
| 1397 us_csc_coeff[4] = 256; |
| 1398 us_csc_coeff[5] = 443; |
| 1399 us_csc_coeff[6] = 0; |
| 1400 us_csc_coeff[7] = 256; |
| 1401 us_csc_coeff[8] = 0; |
| 1402 us_csc_coeff[9] = 350; |
| 1403 break; |
| 1404 |
| 1405 case HDMI_CSC_YUV601_TO_RGB_FR: |
| 1406 us_csc_coeff[0] = 0x03; |
| 1407 us_csc_coeff[1] = 298; |
| 1408 us_csc_coeff[2] = 924; |
| 1409 us_csc_coeff[3] = 816; |
| 1410 us_csc_coeff[4] = 298; |
| 1411 us_csc_coeff[5] = 516; |
| 1412 us_csc_coeff[6] = 0; |
| 1413 us_csc_coeff[7] = 298; |
| 1414 us_csc_coeff[8] = 0; |
| 1415 us_csc_coeff[9] = 408; |
| 1416 break; |
| 1417 |
| 1418 case HDMI_CSC_YUV709_TO_RGB_LR: |
| 1419 us_csc_coeff[0] = 0x23; |
| 1420 us_csc_coeff[1] = 256; |
| 1421 us_csc_coeff[2] = 978; |
| 1422 us_csc_coeff[3] = 907; |
| 1423 us_csc_coeff[4] = 256; |
| 1424 us_csc_coeff[5] = 464; |
| 1425 us_csc_coeff[6] = 0; |
| 1426 us_csc_coeff[7] = 256; |
| 1427 us_csc_coeff[8] = 0; |
| 1428 us_csc_coeff[9] = 394; |
| 1429 break; |
| 1430 |
| 1431 case HDMI_CSC_YUV709_TO_RGB_FR: |
| 1432 us_csc_coeff[0] = 0x03; |
| 1433 us_csc_coeff[1] = 298; |
| 1434 us_csc_coeff[2] = 970; |
| 1435 us_csc_coeff[3] = 888; |
| 1436 us_csc_coeff[4] = 298; |
| 1437 us_csc_coeff[5] = 540; |
| 1438 us_csc_coeff[6] = 0; |
| 1439 us_csc_coeff[7] = 298; |
| 1440 us_csc_coeff[8] = 0; |
| 1441 us_csc_coeff[9] = 458; |
| 1442 break; |
| 1443 |
| 1444 case HDMI_CSC_YUV601_TO_YUV709: |
| 1445 us_csc_coeff[0] = 0x33; |
| 1446 us_csc_coeff[1] = 256; |
| 1447 us_csc_coeff[2] = 995; |
| 1448 us_csc_coeff[3] = 971; |
| 1449 us_csc_coeff[4] = 0; |
| 1450 us_csc_coeff[5] = 260; |
| 1451 us_csc_coeff[6] = 29; |
| 1452 us_csc_coeff[7] = 0; |
| 1453 us_csc_coeff[8] = 19; |
| 1454 us_csc_coeff[9] = 262; |
| 1455 break; |
| 1456 |
| 1457 case HDMI_CSC_RGB_FR_TO_RGB_LR: |
| 1458 us_csc_coeff[0] = 0x20; |
| 1459 us_csc_coeff[1] = 220; |
| 1460 us_csc_coeff[2] = 0; |
| 1461 us_csc_coeff[3] = 0; |
| 1462 us_csc_coeff[4] = 0; |
| 1463 us_csc_coeff[5] = 220; |
| 1464 us_csc_coeff[6] = 0; |
| 1465 us_csc_coeff[7] = 0; |
| 1466 us_csc_coeff[8] = 0; |
| 1467 us_csc_coeff[9] = 220; |
| 1468 break; |
| 1469 |
| 1470 case HDMI_CSC_RGB_FR_TO_YUV601: |
| 1471 us_csc_coeff[0] = 0x30; |
| 1472 us_csc_coeff[1] = 129; |
| 1473 us_csc_coeff[2] = 25; |
| 1474 us_csc_coeff[3] = 65; |
| 1475 us_csc_coeff[4] = 950; /* -74 */ |
| 1476 us_csc_coeff[5] = 112; |
| 1477 us_csc_coeff[6] = 986; /* -38 */ |
| 1478 us_csc_coeff[7] = 930; /* -94 */ |
| 1479 us_csc_coeff[8] = 1006; /* -18 */ |
| 1480 us_csc_coeff[9] = 112; |
| 1481 break; |
| 1482 |
| 1483 case HDMI_CSC_RGB_FR_TO_YUV709: |
| 1484 us_csc_coeff[0] = 0x30; |
| 1485 us_csc_coeff[1] = 157; |
| 1486 us_csc_coeff[2] = 16; |
| 1487 us_csc_coeff[3] = 47; |
| 1488 us_csc_coeff[4] = 937; /* -87 */ |
| 1489 us_csc_coeff[5] = 112; |
| 1490 us_csc_coeff[6] = 999; /* -25 */ |
| 1491 us_csc_coeff[7] = 922; /* -102 */ |
| 1492 us_csc_coeff[8] = 1014; /* -10 */ |
| 1493 us_csc_coeff[9] = 112; |
| 1494 break; |
| 1495 |
| 1496 case HDMI_BYPASS: |
| 1497 us_csc_coeff[0] = 0x33; |
| 1498 us_csc_coeff[1] = 256; |
| 1499 us_csc_coeff[2] = 0; |
| 1500 us_csc_coeff[3] = 0; |
| 1501 us_csc_coeff[4] = 0; |
| 1502 us_csc_coeff[5] = 256; |
| 1503 us_csc_coeff[6] = 0; |
| 1504 us_csc_coeff[7] = 0; |
| 1505 us_csc_coeff[8] = 0; |
| 1506 us_csc_coeff[9] = 256; |
| 1507 break; |
| 1508 |
| 1509 default: |
| 1510 HDMIPRINTK("invalid out_mode parameter(%d)\n\r", csc_type); |
| 1511 return S5P_TV_HDMI_ERR_INVALID_PARAM; |
| 1512 } |
| 1513 |
| 1514 return HDMI_NO_ERROR; |
| 1515 } |
| 1516 |
| 1517 enum s5p_tv_hdmi_err tv_hdmi_video_init_avi_infoframe( |
| 1518 enum s5p_hdmi_transmit trans_type, |
| 1519 u8 check_sum, |
| 1520 u8 *avi_data) |
| 1521 { |
| 1522 HDMIPRINTK("%d,%d,%d\n\r", |
| 1523 (u32)trans_type, (u32)check_sum, (u32)avi_data); |
| 1524 |
| 1525 switch (trans_type) { |
| 1526 |
| 1527 case HDMI_DO_NOT_TANS: |
| 1528 writel(AVI_TX_CON_NO_TRANS, hdmi_base + S5P_AVI_CON); |
| 1529 break; |
| 1530 |
| 1531 case HDMI_TRANS_ONCE: |
| 1532 writel(AVI_TX_CON_TRANS_ONCE, hdmi_base + S5P_AVI_CON); |
| 1533 break; |
| 1534 |
| 1535 case HDMI_TRANS_EVERY_SYNC: |
| 1536 writel(AVI_TX_CON_TRANS_EVERY_VSYNC, hdmi_base + S5P_AVI_CON); |
| 1537 break; |
| 1538 |
| 1539 default: |
| 1540 HDMIPRINTK(" invalid out_mode parameter(%d)\n\r", trans_type); |
| 1541 return S5P_TV_HDMI_ERR_INVALID_PARAM; |
| 1542 } |
| 1543 |
| 1544 writel(SET_AVI_CHECK_SUM(check_sum), hdmi_base + S5P_AVI_CHECK_SUM); |
| 1545 |
| 1546 writel(SET_AVI_BYTE(*(avi_data)), hdmi_base + S5P_AVI_BYTE1); |
| 1547 writel(SET_AVI_BYTE(*(avi_data + 1)), hdmi_base + S5P_AVI_BYTE2); |
| 1548 writel(SET_AVI_BYTE(*(avi_data + 2)), hdmi_base + S5P_AVI_BYTE3); |
| 1549 writel(SET_AVI_BYTE(*(avi_data + 3)), hdmi_base + S5P_AVI_BYTE4); |
| 1550 writel(SET_AVI_BYTE(*(avi_data + 4)), hdmi_base + S5P_AVI_BYTE5); |
| 1551 writel(SET_AVI_BYTE(*(avi_data + 5)), hdmi_base + S5P_AVI_BYTE6); |
| 1552 writel(SET_AVI_BYTE(*(avi_data + 6)), hdmi_base + S5P_AVI_BYTE7); |
| 1553 writel(SET_AVI_BYTE(*(avi_data + 7)), hdmi_base + S5P_AVI_BYTE8); |
| 1554 writel(SET_AVI_BYTE(*(avi_data + 8)), hdmi_base + S5P_AVI_BYTE9); |
| 1555 writel(SET_AVI_BYTE(*(avi_data + 9)), hdmi_base + S5P_AVI_BYTE10); |
| 1556 writel(SET_AVI_BYTE(*(avi_data + 10)), hdmi_base + S5P_AVI_BYTE11); |
| 1557 writel(SET_AVI_BYTE(*(avi_data + 11)), hdmi_base + S5P_AVI_BYTE12); |
| 1558 writel(SET_AVI_BYTE(*(avi_data + 12)), hdmi_base + S5P_AVI_BYTE13); |
| 1559 |
| 1560 HDMIPRINTK("AVI_CON = 0x%08x \n\r", readl(hdmi_base + S5P_AVI_CON)); |
| 1561 HDMIPRINTK("AVI_CHECK_SUM = 0x%08x \n\r", |
| 1562 readl(hdmi_base + S5P_AVI_CHECK_SUM)); |
| 1563 HDMIPRINTK("AVI_BYTE1 = 0x%08x \n\r", |
| 1564 readl(hdmi_base + S5P_AVI_BYTE1)); |
| 1565 HDMIPRINTK("AVI_BYTE2 = 0x%08x \n\r", |
| 1566 readl(hdmi_base + S5P_AVI_BYTE2)); |
| 1567 HDMIPRINTK("AVI_BYTE3 = 0x%08x \n\r", |
| 1568 readl(hdmi_base + S5P_AVI_BYTE3)); |
| 1569 HDMIPRINTK("AVI_BYTE4 = 0x%08x \n\r", |
| 1570 readl(hdmi_base + S5P_AVI_BYTE4)); |
| 1571 HDMIPRINTK("AVI_BYTE5 = 0x%08x \n\r", |
| 1572 readl(hdmi_base + S5P_AVI_BYTE5)); |
| 1573 HDMIPRINTK("AVI_BYTE6 = 0x%08x \n\r", |
| 1574 readl(hdmi_base + S5P_AVI_BYTE6)); |
| 1575 HDMIPRINTK("AVI_BYTE7 = 0x%08x \n\r", |
| 1576 readl(hdmi_base + S5P_AVI_BYTE7)); |
| 1577 HDMIPRINTK("AVI_BYTE8 = 0x%08x \n\r", |
| 1578 readl(hdmi_base + S5P_AVI_BYTE8)); |
| 1579 HDMIPRINTK("AVI_BYTE9 = 0x%08x \n\r", |
| 1580 readl(hdmi_base + S5P_AVI_BYTE9)); |
| 1581 HDMIPRINTK("AVI_BYTE10 = 0x%08x \n\r", |
| 1582 readl(hdmi_base + S5P_AVI_BYTE10)); |
| 1583 HDMIPRINTK("AVI_BYTE11 = 0x%08x \n\r", |
| 1584 readl(hdmi_base + S5P_AVI_BYTE11)); |
| 1585 HDMIPRINTK("AVI_BYTE12 = 0x%08x \n\r", |
| 1586 readl(hdmi_base + S5P_AVI_BYTE12)); |
| 1587 HDMIPRINTK("AVI_BYTE13 = 0x%08x \n\r", |
| 1588 readl(hdmi_base + S5P_AVI_BYTE13)); |
| 1589 |
| 1590 return HDMI_NO_ERROR; |
| 1591 } |
| 1592 |
| 1593 enum s5p_tv_hdmi_err tv_hdmi_video_init_mpg_infoframe( |
| 1594 enum s5p_hdmi_transmit trans_type, |
| 1595 u8 check_sum, |
| 1596 u8 *mpg_data) |
| 1597 { |
| 1598 HDMIPRINTK("trans_type : %d,%d,%d\n\r", (u32)trans_type, |
| 1599 (u32)check_sum, (u32)mpg_data); |
| 1600 |
| 1601 switch (trans_type) { |
| 1602 |
| 1603 case HDMI_DO_NOT_TANS: |
| 1604 writel(MPG_TX_CON_NO_TRANS, |
| 1605 hdmi_base + S5P_MPG_CON); |
| 1606 break; |
| 1607 |
| 1608 case HDMI_TRANS_ONCE: |
| 1609 writel(MPG_TX_CON_TRANS_ONCE, |
| 1610 hdmi_base + S5P_MPG_CON); |
| 1611 break; |
| 1612 |
| 1613 case HDMI_TRANS_EVERY_SYNC: |
| 1614 writel(MPG_TX_CON_TRANS_EVERY_VSYNC, |
| 1615 hdmi_base + S5P_MPG_CON); |
| 1616 break; |
| 1617 |
| 1618 default: |
| 1619 HDMIPRINTK("invalid out_mode parameter(%d)\n\r", |
| 1620 trans_type); |
| 1621 return S5P_TV_HDMI_ERR_INVALID_PARAM; |
| 1622 } |
| 1623 |
| 1624 writel(SET_MPG_CHECK_SUM(check_sum), |
| 1625 |
| 1626 hdmi_base + S5P_MPG_CHECK_SUM); |
| 1627 |
| 1628 writel(SET_MPG_BYTE(*(mpg_data)), |
| 1629 hdmi_base + S5P_MPEG_BYTE1); |
| 1630 writel(SET_MPG_BYTE(*(mpg_data + 1)), |
| 1631 hdmi_base + S5P_MPEG_BYTE2); |
| 1632 writel(SET_MPG_BYTE(*(mpg_data + 2)), |
| 1633 hdmi_base + S5P_MPEG_BYTE3); |
| 1634 writel(SET_MPG_BYTE(*(mpg_data + 3)), |
| 1635 hdmi_base + S5P_MPEG_BYTE4); |
| 1636 writel(SET_MPG_BYTE(*(mpg_data + 4)), |
| 1637 hdmi_base + S5P_MPEG_BYTE5); |
| 1638 |
| 1639 HDMIPRINTK("MPG_CON = 0x%08x \n\r", |
| 1640 readl(hdmi_base + S5P_MPG_CON)); |
| 1641 HDMIPRINTK("MPG_CHECK_SUM = 0x%08x \n\r", |
| 1642 readl(hdmi_base + S5P_MPG_CHECK_SUM)); |
| 1643 HDMIPRINTK("MPEG_BYTE1 = 0x%08x \n\r", |
| 1644 readl(hdmi_base + S5P_MPEG_BYTE1)); |
| 1645 HDMIPRINTK("MPEG_BYTE2 = 0x%08x \n\r", |
| 1646 readl(hdmi_base + S5P_MPEG_BYTE2)); |
| 1647 HDMIPRINTK("MPEG_BYTE3 = 0x%08x \n\r", |
| 1648 readl(hdmi_base + S5P_MPEG_BYTE3)); |
| 1649 HDMIPRINTK("MPEG_BYTE4 = 0x%08x \n\r", |
| 1650 readl(hdmi_base + S5P_MPEG_BYTE4)); |
| 1651 HDMIPRINTK("MPEG_BYTE5 = 0x%08x \n\r", |
| 1652 readl(hdmi_base + S5P_MPEG_BYTE5)); |
| 1653 |
| 1654 return HDMI_NO_ERROR; |
| 1655 } |
| 1656 |
| 1657 void tv_hdmi_video_init_tg_cmd(bool time_c_e, |
| 1658 bool bt656_sync_en, |
| 1659 bool tg_en) |
| 1660 { |
| 1661 u32 temp_reg = 0; |
| 1662 |
| 1663 temp_reg = readl(hdmi_base + S5P_TG_CMD); |
| 1664 |
| 1665 if (time_c_e) |
| 1666 temp_reg |= GETSYNC_TYPE_EN; |
| 1667 else |
| 1668 temp_reg &= GETSYNC_TYPE_DIS; |
| 1669 |
| 1670 if (bt656_sync_en) |
| 1671 temp_reg |= GETSYNC_EN; |
| 1672 else |
| 1673 temp_reg &= GETSYNC_DIS; |
| 1674 |
| 1675 if (tg_en) |
| 1676 temp_reg |= TG_EN; |
| 1677 else |
| 1678 temp_reg &= TG_DIS; |
| 1679 |
| 1680 writel(temp_reg, hdmi_base + S5P_TG_CMD); |
| 1681 |
| 1682 HDMIPRINTK("TG_CMD = 0x%08x \n\r", readl(hdmi_base + S5P_TG_CMD)); |
| 1683 } |
| 1684 |
| 1685 |
| 1686 bool tv_hdmi_start(enum s5p_hdmi_audio_type hdmi_audio_type, |
| 1687 bool hdcp_en, |
| 1688 struct i2c_client *ddc_port) |
| 1689 { |
| 1690 u32 temp_reg = HDMI_EN; |
| 1691 |
| 1692 HDMIPRINTK("aud type : %d, hdcp enable : %d\n\r", |
| 1693 hdmi_audio_type, hdcp_en); |
| 1694 |
| 1695 switch (hdmi_audio_type) { |
| 1696 |
| 1697 case HDMI_AUDIO_PCM: |
| 1698 temp_reg |= ASP_EN; |
| 1699 break; |
| 1700 |
| 1701 case HDMI_AUDIO_NO: |
| 1702 break; |
| 1703 |
| 1704 default: |
| 1705 HDMIPRINTK(" invalid hdmi_audio_type(%d)\n\r", |
| 1706 hdmi_audio_type); |
| 1707 return false; |
| 1708 } |
| 1709 |
| 1710 writel(readl(hdmi_base + S5P_HDMI_CON_0) | temp_reg, |
| 1711 hdmi_base + S5P_HDMI_CON_0); |
| 1712 |
| 1713 if (hdcp_en) { |
| 1714 if (!tv_start_hdcp()) |
| 1715 HDMIPRINTK("HDCP start failed\n"); |
| 1716 } |
| 1717 |
| 1718 HDMIPRINTK("HPD : 0x%08x, HDMI_CON_0 : 0x%08x\n\r", |
| 1719 readl(hdmi_base + S5P_HPD), |
| 1720 readl(hdmi_base + S5P_HDMI_CON_0)); |
| 1721 |
| 1722 return true; |
| 1723 } |
| 1724 |
| 1725 |
| 1726 |
| 1727 /* |
| 1728 * stop - stop functions are only called under running HDMI |
| 1729 */ |
| 1730 void tv_hdmi_stop(void) |
| 1731 { |
| 1732 u32 temp = 0, result = 0; |
| 1733 HDMIPRINTK("\n\r"); |
| 1734 |
| 1735 tv_stop_hdcp(); |
| 1736 |
| 1737 /* |
| 1738 * Before stopping hdmi, stop the hdcp first. However, |
| 1739 * if there's no delay between hdcp stop & hdmi stop, |
| 1740 * re-opening would be failed. |
| 1741 */ |
| 1742 mdelay(100); |
| 1743 |
| 1744 temp = readl(hdmi_base + S5P_HDMI_CON_0); |
| 1745 result = temp & HDMI_EN; |
| 1746 |
| 1747 if (result) |
| 1748 writel(temp & ~(HDMI_EN | ASP_EN), |
| 1749 hdmi_base + S5P_HDMI_CON_0); |
| 1750 |
| 1751 do { |
| 1752 temp = readl(hdmi_base + S5P_HDMI_CON_0); |
| 1753 } while (temp & HDMI_EN); |
| 1754 |
| 1755 HDMIPRINTK("HPD 0x%08x,HDMI_CON_0 0x%08x\n\r", |
| 1756 readl(hdmi_base + S5P_HPD), |
| 1757 readl(hdmi_base + S5P_HDMI_CON_0)); |
| 1758 } |
| 1759 |
| 1760 int __init tv_hdmi_probe(struct platform_device *pdev, |
| 1761 u32 res_num, u32 res_num2) |
| 1762 { |
| 1763 struct resource *res; |
| 1764 size_t size; |
| 1765 u32 reg; |
| 1766 |
| 1767 spin_lock_init(&lock_hdmi); |
| 1768 |
| 1769 res = platform_get_resource(pdev, IORESOURCE_MEM, res_num); |
| 1770 |
| 1771 if (res == NULL) { |
| 1772 dev_err(&pdev->dev, |
| 1773 "failed to get memory region resource\n"); |
| 1774 goto error; |
| 1775 } |
| 1776 |
| 1777 size = (res->end - res->start) + 1; |
| 1778 |
| 1779 hdmi_mem = request_mem_region(res->start, size, pdev->name); |
| 1780 |
| 1781 if (hdmi_mem == NULL) { |
| 1782 dev_err(&pdev->dev, |
| 1783 "failed to get memory region\n"); |
| 1784 goto error; |
| 1785 } |
| 1786 |
| 1787 hdmi_base = ioremap(res->start, size); |
| 1788 |
| 1789 if (hdmi_base == NULL) { |
| 1790 dev_err(&pdev->dev, |
| 1791 "failed to ioremap address region\n"); |
| 1792 goto error; |
| 1793 } |
| 1794 |
| 1795 res = platform_get_resource(pdev, IORESOURCE_MEM, res_num2); |
| 1796 |
| 1797 if (res == NULL) { |
| 1798 dev_err(&pdev->dev, |
| 1799 "failed to get memory region resource\n"); |
| 1800 goto error; |
| 1801 } |
| 1802 |
| 1803 size = (res->end - res->start) + 1; |
| 1804 |
| 1805 i2c_hdmi_phy_mem = request_mem_region(res->start, size, pdev->name); |
| 1806 |
| 1807 if (i2c_hdmi_phy_mem == NULL) { |
| 1808 dev_err(&pdev->dev, |
| 1809 "failed to get memory region\n"); |
| 1810 goto error; |
| 1811 } |
| 1812 |
| 1813 i2c_hdmi_phy_base = ioremap(res->start, size); |
| 1814 |
| 1815 if (i2c_hdmi_phy_base == NULL) { |
| 1816 dev_err(&pdev->dev, |
| 1817 "failed to ioremap address region\n"); |
| 1818 goto error; |
| 1819 } |
| 1820 |
| 1821 /* PMU Block : HDMI PHY Enable */ |
| 1822 reg = readl(S3C_VA_SYS+0xE804); |
| 1823 reg |= (1<<0); |
| 1824 writel(reg, S3C_VA_SYS+0xE804); |
| 1825 |
| 1826 /* i2c_hdmi init - set i2c filtering */ |
| 1827 writeb(0x5, i2c_hdmi_phy_base + I2C_HDMI_LC); |
| 1828 |
| 1829 /* temp for test - hdmi intr. global enable */ |
| 1830 reg = readb(hdmi_base+S5P_HDMI_CTRL_INTC_CON); |
| 1831 writeb(reg | (1<<HDMI_IRQ_GLOBAL), hdmi_base+S5P_HDMI_CTRL_INTC_CON); |
| 1832 |
| 1833 return 0; |
| 1834 error: |
| 1835 return -ENOENT; |
| 1836 |
| 1837 } |
| 1838 |
| 1839 int __init tv_hdmi_release(struct platform_device *pdev) |
| 1840 { |
| 1841 iounmap(hdmi_base); |
| 1842 |
| 1843 /* remove memory region */ |
| 1844 if (hdmi_mem != NULL) { |
| 1845 if (release_resource(hdmi_mem)) |
| 1846 dev_err(&pdev->dev, |
| 1847 "Can't remove tvout drv !!\n"); |
| 1848 |
| 1849 kfree(hdmi_mem); |
| 1850 |
| 1851 hdmi_mem = NULL; |
| 1852 } |
| 1853 |
| 1854 return 0; |
| 1855 } |
| 1856 |
| 1857 /* |
| 1858 * HDCP ISR. |
| 1859 * If HDCP IRQ occurs, set hdcp_event and wake up the waitqueue. |
| 1860 */ |
| 1861 |
| 1862 #define HDMI_IRQ_TOTAL_NUM 6 |
| 1863 |
| 1864 hdmi_isr hdmi_isr_ftn[HDMI_IRQ_TOTAL_NUM]; |
| 1865 |
| 1866 int s5p_hdmi_register_isr(hdmi_isr isr, u8 irq_num) |
| 1867 { |
| 1868 HDMIPRINTK("Try to register ISR for IRQ number (%d)\n", irq_num); |
| 1869 |
| 1870 if (isr == NULL) { |
| 1871 HDMIPRINTK("Invaild ISR\n"); |
| 1872 return -EINVAL; |
| 1873 } |
| 1874 |
| 1875 /* check IRQ number */ |
| 1876 if (irq_num > HDMI_IRQ_TOTAL_NUM) { |
| 1877 HDMIPRINTK("irq_num exceeds allowed IRQ number(%d)\n", |
| 1878 HDMI_IRQ_TOTAL_NUM); |
| 1879 return -EINVAL; |
| 1880 } |
| 1881 |
| 1882 /* check if is the number already registered? */ |
| 1883 if (hdmi_isr_ftn[irq_num]) { |
| 1884 HDMIPRINTK("the %d th ISR is already registered\n", |
| 1885 irq_num); |
| 1886 } |
| 1887 |
| 1888 hdmi_isr_ftn[irq_num] = isr; |
| 1889 |
| 1890 HDMIPRINTK("Success to register ISR for IRQ number (%d)\n", |
| 1891 irq_num); |
| 1892 |
| 1893 return 0; |
| 1894 } |
| 1895 |
| 1896 irqreturn_t tv_hdmi_irq(int irq, void *dev_id) |
| 1897 { |
| 1898 u8 irq_state, irq_num; |
| 1899 |
| 1900 spin_lock_irq(&lock_hdmi); |
| 1901 |
| 1902 irq_state = readb(hdmi_base+S5P_HDMI_CTRL_INTC_FLAG); |
| 1903 |
| 1904 HDMIPRINTK("S5P_HDMI_CTRL_INTC_FLAG = 0x%02x\n", irq_state); |
| 1905 |
| 1906 /* Check interrupt happened */ |
| 1907 /* Priority of Interrupt HDCP> I2C > Audio > CEC ( Not implemented) */ |
| 1908 |
| 1909 if (irq_state) { |
| 1910 /* HDCP IRQ*/ |
| 1911 irq_num = 0; |
| 1912 /* check if ISR is null or not */ |
| 1913 while (irq_num < HDMI_IRQ_TOTAL_NUM) { |
| 1914 if (irq_state & (1<<irq_num)) { |
| 1915 if (hdmi_isr_ftn[irq_num] != NULL) { |
| 1916 (hdmi_isr_ftn[irq_num])(irq_num); |
| 1917 } else { |
| 1918 HDMIPRINTK( |
| 1919 "No registered ISR for IRQ[%d]\n", |
| 1920 irq_num); |
| 1921 } |
| 1922 } |
| 1923 ++irq_num; |
| 1924 } |
| 1925 |
| 1926 } else { |
| 1927 HDMIPRINTK("Undefined IRQ happened[%x]\n", irq_state); |
| 1928 } |
| 1929 |
| 1930 spin_unlock_irq(&lock_hdmi); |
| 1931 |
| 1932 /* Because of HW Problem, |
| 1933 after processing INT we should INT enable again. |
| 1934 HdmiOutp8( |
| 1935 S5P_HDMI_INTC_CON, 1 << HDMI_IRQ_HDCP | 1 << HDMI_IRQ_GLOBAL ); |
| 1936 INTC_ClearVectAddr(); */ |
| 1937 |
| 1938 return IRQ_HANDLED; |
| 1939 } |
| 1940 |
| 1941 void s5p_hdmi_enable_interrupts(enum s5p_tv_hdmi_interrrupt intr) |
| 1942 { |
| 1943 u8 reg; |
| 1944 reg = readb(hdmi_base+S5P_HDMI_CTRL_INTC_CON); |
| 1945 writeb(reg | (1<<intr) | (1<<HDMI_IRQ_GLOBAL), |
| 1946 hdmi_base+S5P_HDMI_CTRL_INTC_CON); |
| 1947 } |
| 1948 |
| 1949 void s5p_hdmi_disable_interrupts(enum s5p_tv_hdmi_interrrupt intr) |
| 1950 { |
| 1951 u8 reg; |
| 1952 reg = readb(hdmi_base+S5P_HDMI_CTRL_INTC_CON); |
| 1953 writeb(reg & ~(1<<intr), hdmi_base+S5P_HDMI_CTRL_INTC_CON); |
| 1954 } |
| 1955 |
| 1956 void s5p_hdmi_clear_pending(enum s5p_tv_hdmi_interrrupt intr) |
| 1957 { |
| 1958 u8 reg; |
| 1959 reg = readb(hdmi_base+S5P_HDMI_CTRL_INTC_FLAG); |
| 1960 writeb(reg | (1<<intr), hdmi_base+S5P_HDMI_CTRL_INTC_FLAG); |
| 1961 } |
| 1962 |
| 1963 u8 s5p_hdmi_get_interrupts(void) |
| 1964 { |
| 1965 u8 reg; |
| 1966 reg = readb(hdmi_base+S5P_HDMI_CTRL_INTC_FLAG); |
| 1967 return reg; |
| 1968 } |
| 1969 |
| 1970 u8 s5p_hdmi_get_swhpd_status(void) |
| 1971 { |
| 1972 u8 reg; |
| 1973 reg = readb(hdmi_base+S5P_HPD) & HPD_SW_ENABLE; |
| 1974 return reg; |
| 1975 } |
| 1976 |
| 1977 u8 s5p_hdmi_get_hpd_status(void) |
| 1978 { |
| 1979 u8 reg; |
| 1980 reg = readb(hdmi_base+S5P_HDMI_CTRL_HPD); |
| 1981 return reg; |
| 1982 } |
| 1983 |
| 1984 void s5p_hdmi_swhpd_disable(void) |
| 1985 { |
| 1986 u8 reg; |
| 1987 reg = writeb(HPD_SW_DISABLE, hdmi_base+S5P_HPD); |
| 1988 } |
| 1989 |
| 1990 void s5p_hdmi_hpd_gen(void) |
| 1991 { |
| 1992 writeb(0xFF, hdmi_base+S5P_HDMI_HPD_GEN); |
| 1993 } |
| 1994 |
OLD | NEW |