hdmi.c 23.7 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
/*
 * hdmi.c
 *
 * HDMI interface DSS driver setting for TI's OMAP4 family of processor.
 * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/
 * Authors: Yong Zhi
 *	Mythri pk <mythripk@ti.com>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 as published by
 * the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#define DSS_SUBSYS_NAME "HDMI"

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/interrupt.h>
#include <linux/mutex.h>
#include <linux/delay.h>
#include <linux/string.h>
32
#include <linux/platform_device.h>
33 34
#include <linux/pm_runtime.h>
#include <linux/clk.h>
35
#include <linux/gpio.h>
36
#include <linux/regulator/consumer.h>
37
#include <video/omapdss.h>
38

39
#include "ti_hdmi.h"
40
#include "dss.h"
41
#include "dss_features.h"
42

43 44 45 46 47 48
#define HDMI_WP			0x0
#define HDMI_CORE_SYS		0x400
#define HDMI_CORE_AV		0x900
#define HDMI_PLLCTRL		0x200
#define HDMI_PHY		0x300

49 50 51 52 53 54 55 56
/* HDMI EDID Length move this */
#define HDMI_EDID_MAX_LENGTH			256
#define EDID_TIMING_DESCRIPTOR_SIZE		0x12
#define EDID_DESCRIPTOR_BLOCK0_ADDRESS		0x36
#define EDID_DESCRIPTOR_BLOCK1_ADDRESS		0x80
#define EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR	4
#define EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR	4

57
#define HDMI_DEFAULT_REGN 16
58 59
#define HDMI_DEFAULT_REGM2 1

60 61 62
static struct {
	struct mutex lock;
	struct platform_device *pdev;
63
	struct hdmi_ip_data ip_data;
64 65

	struct clk *sys_clk;
66
	struct regulator *vdda_hdmi_dac_reg;
67 68 69 70

	int ct_cp_hpd_gpio;
	int ls_oe_gpio;
	int hpd_gpio;
71 72

	struct omap_dss_output output;
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
} hdmi;

/*
 * Logic for the below structure :
 * user enters the CEA or VESA timings by specifying the HDMI/DVI code.
 * There is a correspondence between CEA/VESA timing and code, please
 * refer to section 6.3 in HDMI 1.3 specification for timing code.
 *
 * In the below structure, cea_vesa_timings corresponds to all OMAP4
 * supported CEA and VESA timing values.code_cea corresponds to the CEA
 * code, It is used to get the timing from cea_vesa_timing array.Similarly
 * with code_vesa. Code_index is used for back mapping, that is once EDID
 * is read from the TV, EDID is parsed to find the timing values and then
 * map it to corresponding CEA or VESA index.
 */

89
static const struct hdmi_config cea_timings[] = {
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
	{
		{ 640, 480, 25200, 96, 16, 48, 2, 10, 33,
			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
			false, },
		{ 1, HDMI_HDMI },
	},
	{
		{ 720, 480, 27027, 62, 16, 60, 6, 9, 30,
			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
			false, },
		{ 2, HDMI_HDMI },
	},
	{
		{ 1280, 720, 74250, 40, 110, 220, 5, 5, 20,
			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
			false, },
		{ 4, HDMI_HDMI },
	},
	{
		{ 1920, 540, 74250, 44, 88, 148, 5, 2, 15,
			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
			true, },
		{ 5, HDMI_HDMI },
	},
	{
		{ 1440, 240, 27027, 124, 38, 114, 3, 4, 15,
			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
			true, },
		{ 6, HDMI_HDMI },
	},
	{
		{ 1920, 1080, 148500, 44, 88, 148, 5, 4, 36,
			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
			false, },
		{ 16, HDMI_HDMI },
	},
	{
		{ 720, 576, 27000, 64, 12, 68, 5, 5, 39,
			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
			false, },
		{ 17, HDMI_HDMI },
	},
	{
		{ 1280, 720, 74250, 40, 440, 220, 5, 5, 20,
			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
			false, },
		{ 19, HDMI_HDMI },
	},
	{
		{ 1920, 540, 74250, 44, 528, 148, 5, 2, 15,
			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
			true, },
		{ 20, HDMI_HDMI },
	},
	{
		{ 1440, 288, 27000, 126, 24, 138, 3, 2, 19,
			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
			true, },
		{ 21, HDMI_HDMI },
	},
	{
		{ 1440, 576, 54000, 128, 24, 136, 5, 5, 39,
			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
			false, },
		{ 29, HDMI_HDMI },
	},
	{
		{ 1920, 1080, 148500, 44, 528, 148, 5, 4, 36,
			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
			false, },
		{ 31, HDMI_HDMI },
	},
	{
		{ 1920, 1080, 74250, 44, 638, 148, 5, 4, 36,
			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
			false, },
		{ 32, HDMI_HDMI },
	},
	{
		{ 2880, 480, 108108, 248, 64, 240, 6, 9, 30,
			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
			false, },
		{ 35, HDMI_HDMI },
	},
	{
		{ 2880, 576, 108000, 256, 48, 272, 5, 5, 39,
			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
			false, },
		{ 37, HDMI_HDMI },
	},
180
};
181

182
static const struct hdmi_config vesa_timings[] = {
183
/* VESA From Here */
184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297
	{
		{ 640, 480, 25175, 96, 16, 48, 2, 11, 31,
			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
			false, },
		{ 4, HDMI_DVI },
	},
	{
		{ 800, 600, 40000, 128, 40, 88, 4, 1, 23,
			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
			false, },
		{ 9, HDMI_DVI },
	},
	{
		{ 848, 480, 33750, 112, 16, 112, 8, 6, 23,
			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
			false, },
		{ 0xE, HDMI_DVI },
	},
	{
		{ 1280, 768, 79500, 128, 64, 192, 7, 3, 20,
			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
			false, },
		{ 0x17, HDMI_DVI },
	},
	{
		{ 1280, 800, 83500, 128, 72, 200, 6, 3, 22,
			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
			false, },
		{ 0x1C, HDMI_DVI },
	},
	{
		{ 1360, 768, 85500, 112, 64, 256, 6, 3, 18,
			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
			false, },
		{ 0x27, HDMI_DVI },
	},
	{
		{ 1280, 960, 108000, 112, 96, 312, 3, 1, 36,
			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
			false, },
		{ 0x20, HDMI_DVI },
	},
	{
		{ 1280, 1024, 108000, 112, 48, 248, 3, 1, 38,
			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
			false, },
		{ 0x23, HDMI_DVI },
	},
	{
		{ 1024, 768, 65000, 136, 24, 160, 6, 3, 29,
			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
			false, },
		{ 0x10, HDMI_DVI },
	},
	{
		{ 1400, 1050, 121750, 144, 88, 232, 4, 3, 32,
			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
			false, },
		{ 0x2A, HDMI_DVI },
	},
	{
		{ 1440, 900, 106500, 152, 80, 232, 6, 3, 25,
			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
			false, },
		{ 0x2F, HDMI_DVI },
	},
	{
		{ 1680, 1050, 146250, 176 , 104, 280, 6, 3, 30,
			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
			false, },
		{ 0x3A, HDMI_DVI },
	},
	{
		{ 1366, 768, 85500, 143, 70, 213, 3, 3, 24,
			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
			false, },
		{ 0x51, HDMI_DVI },
	},
	{
		{ 1920, 1080, 148500, 44, 148, 80, 5, 4, 36,
			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
			false, },
		{ 0x52, HDMI_DVI },
	},
	{
		{ 1280, 768, 68250, 32, 48, 80, 7, 3, 12,
			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
			false, },
		{ 0x16, HDMI_DVI },
	},
	{
		{ 1400, 1050, 101000, 32, 48, 80, 4, 3, 23,
			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
			false, },
		{ 0x29, HDMI_DVI },
	},
	{
		{ 1680, 1050, 119000, 32, 48, 80, 6, 3, 21,
			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
			false, },
		{ 0x39, HDMI_DVI },
	},
	{
		{ 1280, 800, 79500, 32, 48, 80, 6, 3, 14,
			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
			false, },
		{ 0x1B, HDMI_DVI },
	},
	{
		{ 1280, 720, 74250, 40, 110, 220, 5, 5, 20,
			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
			false, },
		{ 0x55, HDMI_DVI },
	},
298 299
};

300 301 302 303 304 305 306 307
static int hdmi_runtime_get(void)
{
	int r;

	DSSDBG("hdmi_runtime_get\n");

	r = pm_runtime_get_sync(&hdmi.pdev->dev);
	WARN_ON(r < 0);
308
	if (r < 0)
309
		return r;
310 311

	return 0;
312 313 314 315 316 317 318 319
}

static void hdmi_runtime_put(void)
{
	int r;

	DSSDBG("hdmi_runtime_put\n");

320
	r = pm_runtime_put_sync(&hdmi.pdev->dev);
321
	WARN_ON(r < 0 && r != -ENOSYS);
322 323
}

324
static int __init hdmi_init_display(struct omap_dss_device *dssdev)
325
{
326 327 328 329 330 331 332 333
	int r;

	struct gpio gpios[] = {
		{ hdmi.ct_cp_hpd_gpio, GPIOF_OUT_INIT_LOW, "hdmi_ct_cp_hpd" },
		{ hdmi.ls_oe_gpio, GPIOF_OUT_INIT_LOW, "hdmi_ls_oe" },
		{ hdmi.hpd_gpio, GPIOF_DIR_IN, "hdmi_hpd" },
	};

334 335
	DSSDBG("init_display\n");

336
	dss_init_hdmi_ip_ops(&hdmi.ip_data, omapdss_get_version());
337

338 339 340 341 342 343 344 345 346 347 348 349 350
	if (hdmi.vdda_hdmi_dac_reg == NULL) {
		struct regulator *reg;

		reg = devm_regulator_get(&hdmi.pdev->dev, "vdda_hdmi_dac");

		if (IS_ERR(reg)) {
			DSSERR("can't get VDDA_HDMI_DAC regulator\n");
			return PTR_ERR(reg);
		}

		hdmi.vdda_hdmi_dac_reg = reg;
	}

351 352 353 354
	r = gpio_request_array(gpios, ARRAY_SIZE(gpios));
	if (r)
		return r;

355 356 357
	return 0;
}

358 359 360 361 362 363 364 365 366
static void __exit hdmi_uninit_display(struct omap_dss_device *dssdev)
{
	DSSDBG("uninit_display\n");

	gpio_free(hdmi.ct_cp_hpd_gpio);
	gpio_free(hdmi.ls_oe_gpio);
	gpio_free(hdmi.hpd_gpio);
}

367 368 369
static const struct hdmi_config *hdmi_find_timing(
					const struct hdmi_config *timings_arr,
					int len)
370
{
371
	int i;
372

373
	for (i = 0; i < len; i++) {
374
		if (timings_arr[i].cm.code == hdmi.ip_data.cfg.cm.code)
375 376 377 378
			return &timings_arr[i];
	}
	return NULL;
}
379

380 381 382 383 384
static const struct hdmi_config *hdmi_get_timings(void)
{
       const struct hdmi_config *arr;
       int len;

385
       if (hdmi.ip_data.cfg.cm.mode == HDMI_DVI) {
386 387 388 389 390 391 392 393 394 395 396
               arr = vesa_timings;
               len = ARRAY_SIZE(vesa_timings);
       } else {
               arr = cea_timings;
               len = ARRAY_SIZE(cea_timings);
       }

       return hdmi_find_timing(arr, len);
}

static bool hdmi_timings_compare(struct omap_video_timings *timing1,
397
				const struct omap_video_timings *timing2)
398 399 400 401 402 403
{
	int timing1_vsync, timing1_hsync, timing2_vsync, timing2_hsync;

	if ((timing2->pixel_clock == timing1->pixel_clock) &&
		(timing2->x_res == timing1->x_res) &&
		(timing2->y_res == timing1->y_res)) {
404

405 406 407 408 409 410 411 412 413 414 415 416 417 418
		timing2_hsync = timing2->hfp + timing2->hsw + timing2->hbp;
		timing1_hsync = timing1->hfp + timing1->hsw + timing1->hbp;
		timing2_vsync = timing2->vfp + timing2->vsw + timing2->vbp;
		timing1_vsync = timing2->vfp + timing2->vsw + timing2->vbp;

		DSSDBG("timing1_hsync = %d timing1_vsync = %d"\
			"timing2_hsync = %d timing2_vsync = %d\n",
			timing1_hsync, timing1_vsync,
			timing2_hsync, timing2_vsync);

		if ((timing1_hsync == timing2_hsync) &&
			(timing1_vsync == timing2_vsync)) {
			return true;
		}
419
	}
420
	return false;
421 422 423 424
}

static struct hdmi_cm hdmi_get_code(struct omap_video_timings *timing)
{
425
	int i;
426 427 428
	struct hdmi_cm cm = {-1};
	DSSDBG("hdmi_get_code\n");

429 430 431 432 433 434 435 436 437 438
	for (i = 0; i < ARRAY_SIZE(cea_timings); i++) {
		if (hdmi_timings_compare(timing, &cea_timings[i].timings)) {
			cm = cea_timings[i].cm;
			goto end;
		}
	}
	for (i = 0; i < ARRAY_SIZE(vesa_timings); i++) {
		if (hdmi_timings_compare(timing, &vesa_timings[i].timings)) {
			cm = vesa_timings[i].cm;
			goto end;
439 440 441
		}
	}

442
end:	return cm;
443 444 445

}

446 447 448
unsigned long hdmi_get_pixel_clock(void)
{
	/* HDMI Pixel Clock in Mhz */
449
	return hdmi.ip_data.cfg.timings.pixel_clock * 1000;
450 451
}

452 453
static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,
		struct hdmi_pll_info *pi)
454
{
455
	unsigned long clkin, refclk;
456 457
	u32 mf;

458
	clkin = clk_get_rate(hdmi.sys_clk) / 10000;
459 460 461 462
	/*
	 * Input clock is predivided by N + 1
	 * out put of which is reference clk
	 */
463 464 465 466 467
	if (dssdev->clocks.hdmi.regn == 0)
		pi->regn = HDMI_DEFAULT_REGN;
	else
		pi->regn = dssdev->clocks.hdmi.regn;

468
	refclk = clkin / pi->regn;
469

470 471 472 473
	if (dssdev->clocks.hdmi.regm2 == 0)
		pi->regm2 = HDMI_DEFAULT_REGM2;
	else
		pi->regm2 = dssdev->clocks.hdmi.regm2;
474

475 476 477 478 479 480
	/*
	 * multiplier is pixel_clk/ref_clk
	 * Multiplying by 100 to avoid fractional part removal
	 */
	pi->regm = phy * pi->regm2 / refclk;

481 482 483 484 485
	/*
	 * fractional multiplier is remainder of the difference between
	 * multiplier and actual phy(required pixel clock thus should be
	 * multiplied by 2^18(262144) divided by the reference clock
	 */
486 487
	mf = (phy - pi->regm / pi->regm2 * refclk) * 262144;
	pi->regmf = pi->regm2 * mf / refclk;
488 489 490 491 492 493

	/*
	 * Dcofreq should be set to 1 if required pixel clock
	 * is greater than 1000MHz
	 */
	pi->dcofreq = phy > 1000 * 100;
494
	pi->regsd = ((pi->regm * clkin / 10) / (pi->regn * 250) + 5) / 10;
495

496 497 498
	/* Set the reference clock to sysclk reference */
	pi->refsel = HDMI_REFSEL_SYSCLK;

499 500 501 502 503 504
	DSSDBG("M = %d Mf = %d\n", pi->regm, pi->regmf);
	DSSDBG("range = %d sd = %d\n", pi->dcofreq, pi->regsd);
}

static int hdmi_power_on(struct omap_dss_device *dssdev)
{
505
	int r;
506
	struct omap_video_timings *p;
507
	struct omap_overlay_manager *mgr = dssdev->output->manager;
508
	unsigned long phy;
509

510 511 512
	gpio_set_value(hdmi.ct_cp_hpd_gpio, 1);
	gpio_set_value(hdmi.ls_oe_gpio, 1);

513 514 515
	/* wait 300us after CT_CP_HPD for the 5V power output to reach 90% */
	udelay(300);

516 517 518 519
	r = regulator_enable(hdmi.vdda_hdmi_dac_reg);
	if (r)
		goto err_vdac_enable;

520 521
	r = hdmi_runtime_get();
	if (r)
522
		goto err_runtime_get;
523

524
	dss_mgr_disable(mgr);
525

526
	p = &hdmi.ip_data.cfg.timings;
527

528
	DSSDBG("hdmi_power_on x_res= %d y_res = %d\n", p->x_res, p->y_res);
529 530 531

	phy = p->pixel_clock;

532
	hdmi_compute_pll(dssdev, phy, &hdmi.ip_data.pll_data);
533

534
	hdmi.ip_data.ops->video_disable(&hdmi.ip_data);
535

536
	/* config the PLL and PHY hdmi_set_pll_pwrfirst */
537
	r = hdmi.ip_data.ops->pll_enable(&hdmi.ip_data);
538 539
	if (r) {
		DSSDBG("Failed to lock PLL\n");
540
		goto err_pll_enable;
541 542
	}

543
	r = hdmi.ip_data.ops->phy_enable(&hdmi.ip_data);
544 545
	if (r) {
		DSSDBG("Failed to start PHY\n");
546
		goto err_phy_enable;
547 548
	}

549
	hdmi.ip_data.ops->video_configure(&hdmi.ip_data);
550 551 552 553 554 555 556 557 558 559

	/* Make selection of HDMI in DSS */
	dss_select_hdmi_venc_clk_source(DSS_HDMI_M_PCLK);

	/* Select the dispc clock source as PRCM clock, to ensure that it is not
	 * DSI PLL source as the clock selected by DSI PLL might not be
	 * sufficient for the resolution selected / that can be changed
	 * dynamically by user. This can be moved to single location , say
	 * Boardfile.
	 */
560
	dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src);
561 562 563 564 565

	/* bypass TV gamma table */
	dispc_enable_gamma_table(0);

	/* tv size */
566
	dss_mgr_set_timings(mgr, p);
567

568 569 570
	r = hdmi.ip_data.ops->video_enable(&hdmi.ip_data);
	if (r)
		goto err_vid_enable;
571

572
	r = dss_mgr_enable(mgr);
573 574
	if (r)
		goto err_mgr_enable;
575

576
	return 0;
577 578

err_mgr_enable:
579 580
	hdmi.ip_data.ops->video_disable(&hdmi.ip_data);
err_vid_enable:
581
	hdmi.ip_data.ops->phy_disable(&hdmi.ip_data);
582
err_phy_enable:
583
	hdmi.ip_data.ops->pll_disable(&hdmi.ip_data);
584
err_pll_enable:
585
	hdmi_runtime_put();
586
err_runtime_get:
587 588
	regulator_disable(hdmi.vdda_hdmi_dac_reg);
err_vdac_enable:
589 590
	gpio_set_value(hdmi.ct_cp_hpd_gpio, 0);
	gpio_set_value(hdmi.ls_oe_gpio, 0);
591 592 593 594 595
	return -EIO;
}

static void hdmi_power_off(struct omap_dss_device *dssdev)
{
596 597 598
	struct omap_overlay_manager *mgr = dssdev->output->manager;

	dss_mgr_disable(mgr);
599

600
	hdmi.ip_data.ops->video_disable(&hdmi.ip_data);
601 602
	hdmi.ip_data.ops->phy_disable(&hdmi.ip_data);
	hdmi.ip_data.ops->pll_disable(&hdmi.ip_data);
603
	hdmi_runtime_put();
604

605 606
	regulator_disable(hdmi.vdda_hdmi_dac_reg);

607 608
	gpio_set_value(hdmi.ct_cp_hpd_gpio, 0);
	gpio_set_value(hdmi.ls_oe_gpio, 0);
609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624
}

int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
					struct omap_video_timings *timings)
{
	struct hdmi_cm cm;

	cm = hdmi_get_code(timings);
	if (cm.code == -1) {
		return -EINVAL;
	}

	return 0;

}

625 626
void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev,
		struct omap_video_timings *timings)
627 628
{
	struct hdmi_cm cm;
629
	const struct hdmi_config *t;
630

631 632
	mutex_lock(&hdmi.lock);

633 634 635 636 637 638
	cm = hdmi_get_code(timings);
	hdmi.ip_data.cfg.cm = cm;

	t = hdmi_get_timings();
	if (t != NULL)
		hdmi.ip_data.cfg = *t;
639

640
	mutex_unlock(&hdmi.lock);
641 642
}

643
static void hdmi_dump_regs(struct seq_file *s)
644 645 646 647 648 649 650 651 652 653 654 655 656 657 658
{
	mutex_lock(&hdmi.lock);

	if (hdmi_runtime_get())
		return;

	hdmi.ip_data.ops->dump_wrapper(&hdmi.ip_data, s);
	hdmi.ip_data.ops->dump_pll(&hdmi.ip_data, s);
	hdmi.ip_data.ops->dump_phy(&hdmi.ip_data, s);
	hdmi.ip_data.ops->dump_core(&hdmi.ip_data, s);

	hdmi_runtime_put();
	mutex_unlock(&hdmi.lock);
}

659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675
int omapdss_hdmi_read_edid(u8 *buf, int len)
{
	int r;

	mutex_lock(&hdmi.lock);

	r = hdmi_runtime_get();
	BUG_ON(r);

	r = hdmi.ip_data.ops->read_edid(&hdmi.ip_data, buf, len);

	hdmi_runtime_put();
	mutex_unlock(&hdmi.lock);

	return r;
}

676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692
bool omapdss_hdmi_detect(void)
{
	int r;

	mutex_lock(&hdmi.lock);

	r = hdmi_runtime_get();
	BUG_ON(r);

	r = hdmi.ip_data.ops->detect(&hdmi.ip_data);

	hdmi_runtime_put();
	mutex_unlock(&hdmi.lock);

	return r == 1;
}

693 694
int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev)
{
695
	struct omap_dss_output *out = dssdev->output;
696 697 698 699 700 701
	int r = 0;

	DSSDBG("ENTER hdmi_display_enable\n");

	mutex_lock(&hdmi.lock);

702 703
	if (out == NULL || out->manager == NULL) {
		DSSERR("failed to enable display: no output/manager\n");
704 705 706 707
		r = -ENODEV;
		goto err0;
	}

708
	hdmi.ip_data.hpd_gpio = hdmi.hpd_gpio;
T
Tomi Valkeinen 已提交
709

710 711 712 713 714 715 716 717 718
	r = omap_dss_start_device(dssdev);
	if (r) {
		DSSERR("failed to start device\n");
		goto err0;
	}

	r = hdmi_power_on(dssdev);
	if (r) {
		DSSERR("failed to power on device\n");
719
		goto err1;
720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744
	}

	mutex_unlock(&hdmi.lock);
	return 0;

err1:
	omap_dss_stop_device(dssdev);
err0:
	mutex_unlock(&hdmi.lock);
	return r;
}

void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev)
{
	DSSDBG("Enter hdmi_display_disable\n");

	mutex_lock(&hdmi.lock);

	hdmi_power_off(dssdev);

	omap_dss_stop_device(dssdev);

	mutex_unlock(&hdmi.lock);
}

745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765
static int hdmi_get_clocks(struct platform_device *pdev)
{
	struct clk *clk;

	clk = clk_get(&pdev->dev, "sys_clk");
	if (IS_ERR(clk)) {
		DSSERR("can't get sys_clk\n");
		return PTR_ERR(clk);
	}

	hdmi.sys_clk = clk;

	return 0;
}

static void hdmi_put_clocks(void)
{
	if (hdmi.sys_clk)
		clk_put(hdmi.sys_clk);
}

766 767 768 769
#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
int hdmi_compute_acr(u32 sample_freq, u32 *n, u32 *cts)
{
	u32 deep_color;
770
	bool deep_color_correct = false;
771 772 773 774 775 776 777 778
	u32 pclk = hdmi.ip_data.cfg.timings.pixel_clock;

	if (n == NULL || cts == NULL)
		return -EINVAL;

	/* TODO: When implemented, query deep color mode here. */
	deep_color = 100;

779 780 781 782 783 784
	/*
	 * When using deep color, the default N value (as in the HDMI
	 * specification) yields to an non-integer CTS. Hence, we
	 * modify it while keeping the restrictions described in
	 * section 7.2.1 of the HDMI 1.4a specification.
	 */
785 786
	switch (sample_freq) {
	case 32000:
787 788 789 790 791 792 793 794 795
	case 48000:
	case 96000:
	case 192000:
		if (deep_color == 125)
			if (pclk == 27027 || pclk == 74250)
				deep_color_correct = true;
		if (deep_color == 150)
			if (pclk == 27027)
				deep_color_correct = true;
796 797
		break;
	case 44100:
798 799 800 801 802
	case 88200:
	case 176400:
		if (deep_color == 125)
			if (pclk == 27027)
				deep_color_correct = true;
803 804 805 806 807
		break;
	default:
		return -EINVAL;
	}

808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860
	if (deep_color_correct) {
		switch (sample_freq) {
		case 32000:
			*n = 8192;
			break;
		case 44100:
			*n = 12544;
			break;
		case 48000:
			*n = 8192;
			break;
		case 88200:
			*n = 25088;
			break;
		case 96000:
			*n = 16384;
			break;
		case 176400:
			*n = 50176;
			break;
		case 192000:
			*n = 32768;
			break;
		default:
			return -EINVAL;
		}
	} else {
		switch (sample_freq) {
		case 32000:
			*n = 4096;
			break;
		case 44100:
			*n = 6272;
			break;
		case 48000:
			*n = 6144;
			break;
		case 88200:
			*n = 12544;
			break;
		case 96000:
			*n = 12288;
			break;
		case 176400:
			*n = 25088;
			break;
		case 192000:
			*n = 24576;
			break;
		default:
			return -EINVAL;
		}
	}
861 862 863 864 865
	/* Calculate CTS. See HDMI 1.3a or 1.4a specifications */
	*cts = pclk * (*n / 128) * deep_color / (sample_freq / 10);

	return 0;
}
866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907

int hdmi_audio_enable(void)
{
	DSSDBG("audio_enable\n");

	return hdmi.ip_data.ops->audio_enable(&hdmi.ip_data);
}

void hdmi_audio_disable(void)
{
	DSSDBG("audio_disable\n");

	hdmi.ip_data.ops->audio_disable(&hdmi.ip_data);
}

int hdmi_audio_start(void)
{
	DSSDBG("audio_start\n");

	return hdmi.ip_data.ops->audio_start(&hdmi.ip_data);
}

void hdmi_audio_stop(void)
{
	DSSDBG("audio_stop\n");

	hdmi.ip_data.ops->audio_stop(&hdmi.ip_data);
}

bool hdmi_mode_has_audio(void)
{
	if (hdmi.ip_data.cfg.cm.mode == HDMI_HDMI)
		return true;
	else
		return false;
}

int hdmi_audio_config(struct omap_dss_audio *audio)
{
	return hdmi.ip_data.ops->audio_config(&hdmi.ip_data, audio);
}

908 909
#endif

910
static struct omap_dss_device * __init hdmi_find_dssdev(struct platform_device *pdev)
911 912
{
	struct omap_dss_board_info *pdata = pdev->dev.platform_data;
913
	const char *def_disp_name = omapdss_get_default_display_name();
914 915 916 917
	struct omap_dss_device *def_dssdev;
	int i;

	def_dssdev = NULL;
918 919 920 921 922 923 924

	for (i = 0; i < pdata->num_devices; ++i) {
		struct omap_dss_device *dssdev = pdata->devices[i];

		if (dssdev->type != OMAP_DISPLAY_TYPE_HDMI)
			continue;

925 926
		if (def_dssdev == NULL)
			def_dssdev = dssdev;
927

928 929 930 931
		if (def_disp_name != NULL &&
				strcmp(dssdev->name, def_disp_name) == 0) {
			def_dssdev = dssdev;
			break;
932
		}
933 934 935 936 937 938 939
	}

	return def_dssdev;
}

static void __init hdmi_probe_pdata(struct platform_device *pdev)
{
940
	struct omap_dss_device *plat_dssdev;
941 942 943
	struct omap_dss_device *dssdev;
	struct omap_dss_hdmi_data *priv;
	int r;
944

945
	plat_dssdev = hdmi_find_dssdev(pdev);
946

947 948 949 950
	if (!plat_dssdev)
		return;

	dssdev = dss_alloc_and_init_device(&pdev->dev);
951 952 953
	if (!dssdev)
		return;

954 955
	dss_copy_device_pdata(dssdev, plat_dssdev);

956 957 958 959 960 961
	priv = dssdev->data;

	hdmi.ct_cp_hpd_gpio = priv->ct_cp_hpd_gpio;
	hdmi.ls_oe_gpio = priv->ls_oe_gpio;
	hdmi.hpd_gpio = priv->hpd_gpio;

962 963
	dssdev->channel = OMAP_DSS_CHANNEL_DIGIT;

964 965 966
	r = hdmi_init_display(dssdev);
	if (r) {
		DSSERR("device %s init failed: %d\n", dssdev->name, r);
967
		dss_put_device(dssdev);
968 969 970
		return;
	}

971
	r = dss_add_device(dssdev);
972 973
	if (r) {
		DSSERR("device %s register failed: %d\n", dssdev->name, r);
974
		dss_put_device(dssdev);
975
		return;
976 977 978
	}
}

979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996
static void __init hdmi_init_output(struct platform_device *pdev)
{
	struct omap_dss_output *out = &hdmi.output;

	out->pdev = pdev;
	out->id = OMAP_DSS_OUTPUT_HDMI;
	out->type = OMAP_DISPLAY_TYPE_HDMI;

	dss_register_output(out);
}

static void __exit hdmi_uninit_output(struct platform_device *pdev)
{
	struct omap_dss_output *out = &hdmi.output;

	dss_unregister_output(out);
}

997
/* HDMI HW IP initialisation */
T
Tomi Valkeinen 已提交
998
static int __init omapdss_hdmihw_probe(struct platform_device *pdev)
999 1000
{
	struct resource *hdmi_mem;
1001
	int r;
1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013

	hdmi.pdev = pdev;

	mutex_init(&hdmi.lock);

	hdmi_mem = platform_get_resource(hdmi.pdev, IORESOURCE_MEM, 0);
	if (!hdmi_mem) {
		DSSERR("can't get IORESOURCE_MEM HDMI\n");
		return -EINVAL;
	}

	/* Base address taken from platform */
1014 1015 1016
	hdmi.ip_data.base_wp = ioremap(hdmi_mem->start,
						resource_size(hdmi_mem));
	if (!hdmi.ip_data.base_wp) {
1017 1018 1019 1020
		DSSERR("can't ioremap WP\n");
		return -ENOMEM;
	}

1021 1022
	r = hdmi_get_clocks(pdev);
	if (r) {
1023
		iounmap(hdmi.ip_data.base_wp);
1024 1025 1026 1027 1028
		return r;
	}

	pm_runtime_enable(&pdev->dev);

1029 1030 1031 1032
	hdmi.ip_data.core_sys_offset = HDMI_CORE_SYS;
	hdmi.ip_data.core_av_offset = HDMI_CORE_AV;
	hdmi.ip_data.pll_offset = HDMI_PLLCTRL;
	hdmi.ip_data.phy_offset = HDMI_PHY;
1033

1034
	mutex_init(&hdmi.ip_data.lock);
1035

1036 1037
	hdmi_panel_init();

1038 1039
	dss_debugfs_create_file("hdmi", hdmi_dump_regs);

1040 1041
	hdmi_init_output(pdev);

1042
	hdmi_probe_pdata(pdev);
1043

1044 1045 1046
	return 0;
}

1047 1048 1049 1050 1051 1052 1053
static int __exit hdmi_remove_child(struct device *dev, void *data)
{
	struct omap_dss_device *dssdev = to_dss_device(dev);
	hdmi_uninit_display(dssdev);
	return 0;
}

T
Tomi Valkeinen 已提交
1054
static int __exit omapdss_hdmihw_remove(struct platform_device *pdev)
1055
{
1056 1057
	device_for_each_child(&pdev->dev, NULL, hdmi_remove_child);

1058
	dss_unregister_child_devices(&pdev->dev);
1059

1060 1061
	hdmi_panel_exit();

1062 1063
	hdmi_uninit_output(pdev);

1064 1065 1066 1067
	pm_runtime_disable(&pdev->dev);

	hdmi_put_clocks();

1068
	iounmap(hdmi.ip_data.base_wp);
1069 1070 1071 1072

	return 0;
}

1073 1074
static int hdmi_runtime_suspend(struct device *dev)
{
1075
	clk_disable_unprepare(hdmi.sys_clk);
1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087

	dispc_runtime_put();

	return 0;
}

static int hdmi_runtime_resume(struct device *dev)
{
	int r;

	r = dispc_runtime_get();
	if (r < 0)
1088
		return r;
1089

1090
	clk_prepare_enable(hdmi.sys_clk);
1091 1092 1093 1094 1095 1096 1097 1098 1099

	return 0;
}

static const struct dev_pm_ops hdmi_pm_ops = {
	.runtime_suspend = hdmi_runtime_suspend,
	.runtime_resume = hdmi_runtime_resume,
};

1100
static struct platform_driver omapdss_hdmihw_driver = {
T
Tomi Valkeinen 已提交
1101
	.remove         = __exit_p(omapdss_hdmihw_remove),
1102 1103 1104
	.driver         = {
		.name   = "omapdss_hdmi",
		.owner  = THIS_MODULE,
1105
		.pm	= &hdmi_pm_ops,
1106 1107 1108
	},
};

T
Tomi Valkeinen 已提交
1109
int __init hdmi_init_platform_driver(void)
1110
{
1111
	return platform_driver_probe(&omapdss_hdmihw_driver, omapdss_hdmihw_probe);
1112 1113
}

T
Tomi Valkeinen 已提交
1114
void __exit hdmi_uninit_platform_driver(void)
1115
{
1116
	platform_driver_unregister(&omapdss_hdmihw_driver);
1117
}