linux/drivers/video/omap2/dss/hdmi.c
<<
>>
Prefs
   1/*
   2 * hdmi.c
   3 *
   4 * HDMI interface DSS driver setting for TI's OMAP4 family of processor.
   5 * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/
   6 * Authors: Yong Zhi
   7 *      Mythri pk <mythripk@ti.com>
   8 *
   9 * This program is free software; you can redistribute it and/or modify it
  10 * under the terms of the GNU General Public License version 2 as published by
  11 * the Free Software Foundation.
  12 *
  13 * This program is distributed in the hope that it will be useful, but WITHOUT
  14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  15 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  16 * more details.
  17 *
  18 * You should have received a copy of the GNU General Public License along with
  19 * this program.  If not, see <http://www.gnu.org/licenses/>.
  20 */
  21
  22#define DSS_SUBSYS_NAME "HDMI"
  23
  24#include <linux/kernel.h>
  25#include <linux/module.h>
  26#include <linux/err.h>
  27#include <linux/io.h>
  28#include <linux/interrupt.h>
  29#include <linux/mutex.h>
  30#include <linux/delay.h>
  31#include <linux/string.h>
  32#include <linux/platform_device.h>
  33#include <linux/pm_runtime.h>
  34#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#define HDMI_WP                 0x0
  44#define HDMI_CORE_SYS           0x400
  45#define HDMI_CORE_AV            0x900
  46#define HDMI_PLLCTRL            0x200
  47#define HDMI_PHY                0x300
  48
  49/* HDMI EDID Length move this */
  50#define HDMI_EDID_MAX_LENGTH                    256
  51#define EDID_TIMING_DESCRIPTOR_SIZE             0x12
  52#define EDID_DESCRIPTOR_BLOCK0_ADDRESS          0x36
  53#define EDID_DESCRIPTOR_BLOCK1_ADDRESS          0x80
  54#define EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR      4
  55#define EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR      4
  56
  57#define HDMI_DEFAULT_REGN 16
  58#define HDMI_DEFAULT_REGM2 1
  59
  60static struct {
  61        struct mutex lock;
  62        struct platform_device *pdev;
  63
  64        struct hdmi_ip_data ip_data;
  65
  66        struct clk *sys_clk;
  67        struct regulator *vdda_hdmi_dac_reg;
  68
  69        int ct_cp_hpd_gpio;
  70        int ls_oe_gpio;
  71        int hpd_gpio;
  72
  73        struct omap_dss_output output;
  74} hdmi;
  75
  76/*
  77 * Logic for the below structure :
  78 * user enters the CEA or VESA timings by specifying the HDMI/DVI code.
  79 * There is a correspondence between CEA/VESA timing and code, please
  80 * refer to section 6.3 in HDMI 1.3 specification for timing code.
  81 *
  82 * In the below structure, cea_vesa_timings corresponds to all OMAP4
  83 * supported CEA and VESA timing values.code_cea corresponds to the CEA
  84 * code, It is used to get the timing from cea_vesa_timing array.Similarly
  85 * with code_vesa. Code_index is used for back mapping, that is once EDID
  86 * is read from the TV, EDID is parsed to find the timing values and then
  87 * map it to corresponding CEA or VESA index.
  88 */
  89
  90static const struct hdmi_config cea_timings[] = {
  91        {
  92                { 640, 480, 25200, 96, 16, 48, 2, 10, 33,
  93                        OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
  94                        false, },
  95                { 1, HDMI_HDMI },
  96        },
  97        {
  98                { 720, 480, 27027, 62, 16, 60, 6, 9, 30,
  99                        OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
 100                        false, },
 101                { 2, HDMI_HDMI },
 102        },
 103        {
 104                { 1280, 720, 74250, 40, 110, 220, 5, 5, 20,
 105                        OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
 106                        false, },
 107                { 4, HDMI_HDMI },
 108        },
 109        {
 110                { 1920, 540, 74250, 44, 88, 148, 5, 2, 15,
 111                        OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
 112                        true, },
 113                { 5, HDMI_HDMI },
 114        },
 115        {
 116                { 1440, 240, 27027, 124, 38, 114, 3, 4, 15,
 117                        OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
 118                        true, },
 119                { 6, HDMI_HDMI },
 120        },
 121        {
 122                { 1920, 1080, 148500, 44, 88, 148, 5, 4, 36,
 123                        OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
 124                        false, },
 125                { 16, HDMI_HDMI },
 126        },
 127        {
 128                { 720, 576, 27000, 64, 12, 68, 5, 5, 39,
 129                        OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
 130                        false, },
 131                { 17, HDMI_HDMI },
 132        },
 133        {
 134                { 1280, 720, 74250, 40, 440, 220, 5, 5, 20,
 135                        OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
 136                        false, },
 137                { 19, HDMI_HDMI },
 138        },
 139        {
 140                { 1920, 540, 74250, 44, 528, 148, 5, 2, 15,
 141                        OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
 142                        true, },
 143                { 20, HDMI_HDMI },
 144        },
 145        {
 146                { 1440, 288, 27000, 126, 24, 138, 3, 2, 19,
 147                        OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
 148                        true, },
 149                { 21, HDMI_HDMI },
 150        },
 151        {
 152                { 1440, 576, 54000, 128, 24, 136, 5, 5, 39,
 153                        OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
 154                        false, },
 155                { 29, HDMI_HDMI },
 156        },
 157        {
 158                { 1920, 1080, 148500, 44, 528, 148, 5, 4, 36,
 159                        OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
 160                        false, },
 161                { 31, HDMI_HDMI },
 162        },
 163        {
 164                { 1920, 1080, 74250, 44, 638, 148, 5, 4, 36,
 165                        OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
 166                        false, },
 167                { 32, HDMI_HDMI },
 168        },
 169        {
 170                { 2880, 480, 108108, 248, 64, 240, 6, 9, 30,
 171                        OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
 172                        false, },
 173                { 35, HDMI_HDMI },
 174        },
 175        {
 176                { 2880, 576, 108000, 256, 48, 272, 5, 5, 39,
 177                        OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
 178                        false, },
 179                { 37, HDMI_HDMI },
 180        },
 181};
 182
 183static const struct hdmi_config vesa_timings[] = {
 184/* VESA From Here */
 185        {
 186                { 640, 480, 25175, 96, 16, 48, 2, 11, 31,
 187                        OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
 188                        false, },
 189                { 4, HDMI_DVI },
 190        },
 191        {
 192                { 800, 600, 40000, 128, 40, 88, 4, 1, 23,
 193                        OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
 194                        false, },
 195                { 9, HDMI_DVI },
 196        },
 197        {
 198                { 848, 480, 33750, 112, 16, 112, 8, 6, 23,
 199                        OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
 200                        false, },
 201                { 0xE, HDMI_DVI },
 202        },
 203        {
 204                { 1280, 768, 79500, 128, 64, 192, 7, 3, 20,
 205                        OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
 206                        false, },
 207                { 0x17, HDMI_DVI },
 208        },
 209        {
 210                { 1280, 800, 83500, 128, 72, 200, 6, 3, 22,
 211                        OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
 212                        false, },
 213                { 0x1C, HDMI_DVI },
 214        },
 215        {
 216                { 1360, 768, 85500, 112, 64, 256, 6, 3, 18,
 217                        OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
 218                        false, },
 219                { 0x27, HDMI_DVI },
 220        },
 221        {
 222                { 1280, 960, 108000, 112, 96, 312, 3, 1, 36,
 223                        OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
 224                        false, },
 225                { 0x20, HDMI_DVI },
 226        },
 227        {
 228                { 1280, 1024, 108000, 112, 48, 248, 3, 1, 38,
 229                        OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
 230                        false, },
 231                { 0x23, HDMI_DVI },
 232        },
 233        {
 234                { 1024, 768, 65000, 136, 24, 160, 6, 3, 29,
 235                        OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
 236                        false, },
 237                { 0x10, HDMI_DVI },
 238        },
 239        {
 240                { 1400, 1050, 121750, 144, 88, 232, 4, 3, 32,
 241                        OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
 242                        false, },
 243                { 0x2A, HDMI_DVI },
 244        },
 245        {
 246                { 1440, 900, 106500, 152, 80, 232, 6, 3, 25,
 247                        OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
 248                        false, },
 249                { 0x2F, HDMI_DVI },
 250        },
 251        {
 252                { 1680, 1050, 146250, 176 , 104, 280, 6, 3, 30,
 253                        OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
 254                        false, },
 255                { 0x3A, HDMI_DVI },
 256        },
 257        {
 258                { 1366, 768, 85500, 143, 70, 213, 3, 3, 24,
 259                        OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
 260                        false, },
 261                { 0x51, HDMI_DVI },
 262        },
 263        {
 264                { 1920, 1080, 148500, 44, 148, 80, 5, 4, 36,
 265                        OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
 266                        false, },
 267                { 0x52, HDMI_DVI },
 268        },
 269        {
 270                { 1280, 768, 68250, 32, 48, 80, 7, 3, 12,
 271                        OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
 272                        false, },
 273                { 0x16, HDMI_DVI },
 274        },
 275        {
 276                { 1400, 1050, 101000, 32, 48, 80, 4, 3, 23,
 277                        OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
 278                        false, },
 279                { 0x29, HDMI_DVI },
 280        },
 281        {
 282                { 1680, 1050, 119000, 32, 48, 80, 6, 3, 21,
 283                        OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
 284                        false, },
 285                { 0x39, HDMI_DVI },
 286        },
 287        {
 288                { 1280, 800, 79500, 32, 48, 80, 6, 3, 14,
 289                        OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
 290                        false, },
 291                { 0x1B, HDMI_DVI },
 292        },
 293        {
 294                { 1280, 720, 74250, 40, 110, 220, 5, 5, 20,
 295                        OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
 296                        false, },
 297                { 0x55, HDMI_DVI },
 298        },
 299        {
 300                { 1920, 1200, 154000, 32, 48, 80, 6, 3, 26,
 301                        OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
 302                        false, },
 303                { 0x44, HDMI_DVI },
 304        },
 305};
 306
 307static int hdmi_runtime_get(void)
 308{
 309        int r;
 310
 311        DSSDBG("hdmi_runtime_get\n");
 312
 313        r = pm_runtime_get_sync(&hdmi.pdev->dev);
 314        WARN_ON(r < 0);
 315        if (r < 0)
 316                return r;
 317
 318        return 0;
 319}
 320
 321static void hdmi_runtime_put(void)
 322{
 323        int r;
 324
 325        DSSDBG("hdmi_runtime_put\n");
 326
 327        r = pm_runtime_put_sync(&hdmi.pdev->dev);
 328        WARN_ON(r < 0 && r != -ENOSYS);
 329}
 330
 331static int hdmi_init_display(struct omap_dss_device *dssdev)
 332{
 333        int r;
 334
 335        struct gpio gpios[] = {
 336                { hdmi.ct_cp_hpd_gpio, GPIOF_OUT_INIT_LOW, "hdmi_ct_cp_hpd" },
 337                { hdmi.ls_oe_gpio, GPIOF_OUT_INIT_LOW, "hdmi_ls_oe" },
 338                { hdmi.hpd_gpio, GPIOF_DIR_IN, "hdmi_hpd" },
 339        };
 340
 341        DSSDBG("init_display\n");
 342
 343        dss_init_hdmi_ip_ops(&hdmi.ip_data, omapdss_get_version());
 344
 345        if (hdmi.vdda_hdmi_dac_reg == NULL) {
 346                struct regulator *reg;
 347
 348                reg = devm_regulator_get(&hdmi.pdev->dev, "vdda_hdmi_dac");
 349
 350                /* DT HACK: try VDAC to make omapdss work for o4 sdp/panda */
 351                if (IS_ERR(reg))
 352                        reg = devm_regulator_get(&hdmi.pdev->dev, "VDAC");
 353
 354                if (IS_ERR(reg)) {
 355                        DSSERR("can't get VDDA_HDMI_DAC regulator\n");
 356                        return PTR_ERR(reg);
 357                }
 358
 359                hdmi.vdda_hdmi_dac_reg = reg;
 360        }
 361
 362        r = gpio_request_array(gpios, ARRAY_SIZE(gpios));
 363        if (r)
 364                return r;
 365
 366        return 0;
 367}
 368
 369static void hdmi_uninit_display(struct omap_dss_device *dssdev)
 370{
 371        DSSDBG("uninit_display\n");
 372
 373        gpio_free(hdmi.ct_cp_hpd_gpio);
 374        gpio_free(hdmi.ls_oe_gpio);
 375        gpio_free(hdmi.hpd_gpio);
 376}
 377
 378static const struct hdmi_config *hdmi_find_timing(
 379                                        const struct hdmi_config *timings_arr,
 380                                        int len)
 381{
 382        int i;
 383
 384        for (i = 0; i < len; i++) {
 385                if (timings_arr[i].cm.code == hdmi.ip_data.cfg.cm.code)
 386                        return &timings_arr[i];
 387        }
 388        return NULL;
 389}
 390
 391static const struct hdmi_config *hdmi_get_timings(void)
 392{
 393       const struct hdmi_config *arr;
 394       int len;
 395
 396       if (hdmi.ip_data.cfg.cm.mode == HDMI_DVI) {
 397               arr = vesa_timings;
 398               len = ARRAY_SIZE(vesa_timings);
 399       } else {
 400               arr = cea_timings;
 401               len = ARRAY_SIZE(cea_timings);
 402       }
 403
 404       return hdmi_find_timing(arr, len);
 405}
 406
 407static bool hdmi_timings_compare(struct omap_video_timings *timing1,
 408                                const struct omap_video_timings *timing2)
 409{
 410        int timing1_vsync, timing1_hsync, timing2_vsync, timing2_hsync;
 411
 412        if ((DIV_ROUND_CLOSEST(timing2->pixel_clock, 1000) ==
 413                        DIV_ROUND_CLOSEST(timing1->pixel_clock, 1000)) &&
 414                (timing2->x_res == timing1->x_res) &&
 415                (timing2->y_res == timing1->y_res)) {
 416
 417                timing2_hsync = timing2->hfp + timing2->hsw + timing2->hbp;
 418                timing1_hsync = timing1->hfp + timing1->hsw + timing1->hbp;
 419                timing2_vsync = timing2->vfp + timing2->vsw + timing2->vbp;
 420                timing1_vsync = timing2->vfp + timing2->vsw + timing2->vbp;
 421
 422                DSSDBG("timing1_hsync = %d timing1_vsync = %d"\
 423                        "timing2_hsync = %d timing2_vsync = %d\n",
 424                        timing1_hsync, timing1_vsync,
 425                        timing2_hsync, timing2_vsync);
 426
 427                if ((timing1_hsync == timing2_hsync) &&
 428                        (timing1_vsync == timing2_vsync)) {
 429                        return true;
 430                }
 431        }
 432        return false;
 433}
 434
 435static struct hdmi_cm hdmi_get_code(struct omap_video_timings *timing)
 436{
 437        int i;
 438        struct hdmi_cm cm = {-1};
 439        DSSDBG("hdmi_get_code\n");
 440
 441        for (i = 0; i < ARRAY_SIZE(cea_timings); i++) {
 442                if (hdmi_timings_compare(timing, &cea_timings[i].timings)) {
 443                        cm = cea_timings[i].cm;
 444                        goto end;
 445                }
 446        }
 447        for (i = 0; i < ARRAY_SIZE(vesa_timings); i++) {
 448                if (hdmi_timings_compare(timing, &vesa_timings[i].timings)) {
 449                        cm = vesa_timings[i].cm;
 450                        goto end;
 451                }
 452        }
 453
 454end:    return cm;
 455
 456}
 457
 458unsigned long hdmi_get_pixel_clock(void)
 459{
 460        /* HDMI Pixel Clock in Mhz */
 461        return hdmi.ip_data.cfg.timings.pixel_clock * 1000;
 462}
 463
 464static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,
 465                struct hdmi_pll_info *pi)
 466{
 467        unsigned long clkin, refclk;
 468        u32 mf;
 469
 470        clkin = clk_get_rate(hdmi.sys_clk) / 10000;
 471        /*
 472         * Input clock is predivided by N + 1
 473         * out put of which is reference clk
 474         */
 475
 476        pi->regn = HDMI_DEFAULT_REGN;
 477
 478        refclk = clkin / pi->regn;
 479
 480        pi->regm2 = HDMI_DEFAULT_REGM2;
 481
 482        /*
 483         * multiplier is pixel_clk/ref_clk
 484         * Multiplying by 100 to avoid fractional part removal
 485         */
 486        pi->regm = phy * pi->regm2 / refclk;
 487
 488        /*
 489         * fractional multiplier is remainder of the difference between
 490         * multiplier and actual phy(required pixel clock thus should be
 491         * multiplied by 2^18(262144) divided by the reference clock
 492         */
 493        mf = (phy - pi->regm / pi->regm2 * refclk) * 262144;
 494        pi->regmf = pi->regm2 * mf / refclk;
 495
 496        /*
 497         * Dcofreq should be set to 1 if required pixel clock
 498         * is greater than 1000MHz
 499         */
 500        pi->dcofreq = phy > 1000 * 100;
 501        pi->regsd = ((pi->regm * clkin / 10) / (pi->regn * 250) + 5) / 10;
 502
 503        /* Set the reference clock to sysclk reference */
 504        pi->refsel = HDMI_REFSEL_SYSCLK;
 505
 506        DSSDBG("M = %d Mf = %d\n", pi->regm, pi->regmf);
 507        DSSDBG("range = %d sd = %d\n", pi->dcofreq, pi->regsd);
 508}
 509
 510static int hdmi_power_on_core(struct omap_dss_device *dssdev)
 511{
 512        int r;
 513
 514        gpio_set_value(hdmi.ct_cp_hpd_gpio, 1);
 515        gpio_set_value(hdmi.ls_oe_gpio, 1);
 516
 517        /* wait 300us after CT_CP_HPD for the 5V power output to reach 90% */
 518        udelay(300);
 519
 520        r = regulator_enable(hdmi.vdda_hdmi_dac_reg);
 521        if (r)
 522                goto err_vdac_enable;
 523
 524        r = hdmi_runtime_get();
 525        if (r)
 526                goto err_runtime_get;
 527
 528        /* Make selection of HDMI in DSS */
 529        dss_select_hdmi_venc_clk_source(DSS_HDMI_M_PCLK);
 530
 531        return 0;
 532
 533err_runtime_get:
 534        regulator_disable(hdmi.vdda_hdmi_dac_reg);
 535err_vdac_enable:
 536        gpio_set_value(hdmi.ct_cp_hpd_gpio, 0);
 537        gpio_set_value(hdmi.ls_oe_gpio, 0);
 538        return r;
 539}
 540
 541static void hdmi_power_off_core(struct omap_dss_device *dssdev)
 542{
 543        hdmi_runtime_put();
 544        regulator_disable(hdmi.vdda_hdmi_dac_reg);
 545        gpio_set_value(hdmi.ct_cp_hpd_gpio, 0);
 546        gpio_set_value(hdmi.ls_oe_gpio, 0);
 547}
 548
 549static int hdmi_power_on_full(struct omap_dss_device *dssdev)
 550{
 551        int r;
 552        struct omap_video_timings *p;
 553        struct omap_overlay_manager *mgr = dssdev->output->manager;
 554        unsigned long phy;
 555
 556        r = hdmi_power_on_core(dssdev);
 557        if (r)
 558                return r;
 559
 560        dss_mgr_disable(mgr);
 561
 562        p = &hdmi.ip_data.cfg.timings;
 563
 564        DSSDBG("hdmi_power_on x_res= %d y_res = %d\n", p->x_res, p->y_res);
 565
 566        phy = p->pixel_clock;
 567
 568        hdmi_compute_pll(dssdev, phy, &hdmi.ip_data.pll_data);
 569
 570        hdmi.ip_data.ops->video_disable(&hdmi.ip_data);
 571
 572        /* config the PLL and PHY hdmi_set_pll_pwrfirst */
 573        r = hdmi.ip_data.ops->pll_enable(&hdmi.ip_data);
 574        if (r) {
 575                DSSDBG("Failed to lock PLL\n");
 576                goto err_pll_enable;
 577        }
 578
 579        r = hdmi.ip_data.ops->phy_enable(&hdmi.ip_data);
 580        if (r) {
 581                DSSDBG("Failed to start PHY\n");
 582                goto err_phy_enable;
 583        }
 584
 585        hdmi.ip_data.ops->video_configure(&hdmi.ip_data);
 586
 587        /* bypass TV gamma table */
 588        dispc_enable_gamma_table(0);
 589
 590        /* tv size */
 591        dss_mgr_set_timings(mgr, p);
 592
 593        r = hdmi.ip_data.ops->video_enable(&hdmi.ip_data);
 594        if (r)
 595                goto err_vid_enable;
 596
 597        r = dss_mgr_enable(mgr);
 598        if (r)
 599                goto err_mgr_enable;
 600
 601        return 0;
 602
 603err_mgr_enable:
 604        hdmi.ip_data.ops->video_disable(&hdmi.ip_data);
 605err_vid_enable:
 606        hdmi.ip_data.ops->phy_disable(&hdmi.ip_data);
 607err_phy_enable:
 608        hdmi.ip_data.ops->pll_disable(&hdmi.ip_data);
 609err_pll_enable:
 610        hdmi_power_off_core(dssdev);
 611        return -EIO;
 612}
 613
 614static void hdmi_power_off_full(struct omap_dss_device *dssdev)
 615{
 616        struct omap_overlay_manager *mgr = dssdev->output->manager;
 617
 618        dss_mgr_disable(mgr);
 619
 620        hdmi.ip_data.ops->video_disable(&hdmi.ip_data);
 621        hdmi.ip_data.ops->phy_disable(&hdmi.ip_data);
 622        hdmi.ip_data.ops->pll_disable(&hdmi.ip_data);
 623
 624        hdmi_power_off_core(dssdev);
 625}
 626
 627int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
 628                                        struct omap_video_timings *timings)
 629{
 630        struct hdmi_cm cm;
 631
 632        cm = hdmi_get_code(timings);
 633        if (cm.code == -1) {
 634                return -EINVAL;
 635        }
 636
 637        return 0;
 638
 639}
 640
 641void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev,
 642                struct omap_video_timings *timings)
 643{
 644        struct hdmi_cm cm;
 645        const struct hdmi_config *t;
 646
 647        mutex_lock(&hdmi.lock);
 648
 649        cm = hdmi_get_code(timings);
 650        hdmi.ip_data.cfg.cm = cm;
 651
 652        t = hdmi_get_timings();
 653        if (t != NULL)
 654                hdmi.ip_data.cfg = *t;
 655
 656        mutex_unlock(&hdmi.lock);
 657}
 658
 659static void hdmi_dump_regs(struct seq_file *s)
 660{
 661        mutex_lock(&hdmi.lock);
 662
 663        if (hdmi_runtime_get()) {
 664                mutex_unlock(&hdmi.lock);
 665                return;
 666        }
 667
 668        hdmi.ip_data.ops->dump_wrapper(&hdmi.ip_data, s);
 669        hdmi.ip_data.ops->dump_pll(&hdmi.ip_data, s);
 670        hdmi.ip_data.ops->dump_phy(&hdmi.ip_data, s);
 671        hdmi.ip_data.ops->dump_core(&hdmi.ip_data, s);
 672
 673        hdmi_runtime_put();
 674        mutex_unlock(&hdmi.lock);
 675}
 676
 677int omapdss_hdmi_read_edid(u8 *buf, int len)
 678{
 679        int r;
 680
 681        mutex_lock(&hdmi.lock);
 682
 683        r = hdmi_runtime_get();
 684        BUG_ON(r);
 685
 686        r = hdmi.ip_data.ops->read_edid(&hdmi.ip_data, buf, len);
 687
 688        hdmi_runtime_put();
 689        mutex_unlock(&hdmi.lock);
 690
 691        return r;
 692}
 693
 694bool omapdss_hdmi_detect(void)
 695{
 696        int r;
 697
 698        mutex_lock(&hdmi.lock);
 699
 700        r = hdmi_runtime_get();
 701        BUG_ON(r);
 702
 703        r = hdmi.ip_data.ops->detect(&hdmi.ip_data);
 704
 705        hdmi_runtime_put();
 706        mutex_unlock(&hdmi.lock);
 707
 708        return r == 1;
 709}
 710
 711int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev)
 712{
 713        struct omap_dss_output *out = dssdev->output;
 714        int r = 0;
 715
 716        DSSDBG("ENTER hdmi_display_enable\n");
 717
 718        mutex_lock(&hdmi.lock);
 719
 720        if (out == NULL || out->manager == NULL) {
 721                DSSERR("failed to enable display: no output/manager\n");
 722                r = -ENODEV;
 723                goto err0;
 724        }
 725
 726        hdmi.ip_data.hpd_gpio = hdmi.hpd_gpio;
 727
 728        r = omap_dss_start_device(dssdev);
 729        if (r) {
 730                DSSERR("failed to start device\n");
 731                goto err0;
 732        }
 733
 734        r = hdmi_power_on_full(dssdev);
 735        if (r) {
 736                DSSERR("failed to power on device\n");
 737                goto err1;
 738        }
 739
 740        mutex_unlock(&hdmi.lock);
 741        return 0;
 742
 743err1:
 744        omap_dss_stop_device(dssdev);
 745err0:
 746        mutex_unlock(&hdmi.lock);
 747        return r;
 748}
 749
 750void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev)
 751{
 752        DSSDBG("Enter hdmi_display_disable\n");
 753
 754        mutex_lock(&hdmi.lock);
 755
 756        hdmi_power_off_full(dssdev);
 757
 758        omap_dss_stop_device(dssdev);
 759
 760        mutex_unlock(&hdmi.lock);
 761}
 762
 763int omapdss_hdmi_core_enable(struct omap_dss_device *dssdev)
 764{
 765        int r = 0;
 766
 767        DSSDBG("ENTER omapdss_hdmi_core_enable\n");
 768
 769        mutex_lock(&hdmi.lock);
 770
 771        hdmi.ip_data.hpd_gpio = hdmi.hpd_gpio;
 772
 773        r = hdmi_power_on_core(dssdev);
 774        if (r) {
 775                DSSERR("failed to power on device\n");
 776                goto err0;
 777        }
 778
 779        mutex_unlock(&hdmi.lock);
 780        return 0;
 781
 782err0:
 783        mutex_unlock(&hdmi.lock);
 784        return r;
 785}
 786
 787void omapdss_hdmi_core_disable(struct omap_dss_device *dssdev)
 788{
 789        DSSDBG("Enter omapdss_hdmi_core_disable\n");
 790
 791        mutex_lock(&hdmi.lock);
 792
 793        hdmi_power_off_core(dssdev);
 794
 795        mutex_unlock(&hdmi.lock);
 796}
 797
 798static int hdmi_get_clocks(struct platform_device *pdev)
 799{
 800        struct clk *clk;
 801
 802        clk = devm_clk_get(&pdev->dev, "sys_clk");
 803        if (IS_ERR(clk)) {
 804                DSSERR("can't get sys_clk\n");
 805                return PTR_ERR(clk);
 806        }
 807
 808        hdmi.sys_clk = clk;
 809
 810        return 0;
 811}
 812
 813#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
 814int hdmi_compute_acr(u32 sample_freq, u32 *n, u32 *cts)
 815{
 816        u32 deep_color;
 817        bool deep_color_correct = false;
 818        u32 pclk = hdmi.ip_data.cfg.timings.pixel_clock;
 819
 820        if (n == NULL || cts == NULL)
 821                return -EINVAL;
 822
 823        /* TODO: When implemented, query deep color mode here. */
 824        deep_color = 100;
 825
 826        /*
 827         * When using deep color, the default N value (as in the HDMI
 828         * specification) yields to an non-integer CTS. Hence, we
 829         * modify it while keeping the restrictions described in
 830         * section 7.2.1 of the HDMI 1.4a specification.
 831         */
 832        switch (sample_freq) {
 833        case 32000:
 834        case 48000:
 835        case 96000:
 836        case 192000:
 837                if (deep_color == 125)
 838                        if (pclk == 27027 || pclk == 74250)
 839                                deep_color_correct = true;
 840                if (deep_color == 150)
 841                        if (pclk == 27027)
 842                                deep_color_correct = true;
 843                break;
 844        case 44100:
 845        case 88200:
 846        case 176400:
 847                if (deep_color == 125)
 848                        if (pclk == 27027)
 849                                deep_color_correct = true;
 850                break;
 851        default:
 852                return -EINVAL;
 853        }
 854
 855        if (deep_color_correct) {
 856                switch (sample_freq) {
 857                case 32000:
 858                        *n = 8192;
 859                        break;
 860                case 44100:
 861                        *n = 12544;
 862                        break;
 863                case 48000:
 864                        *n = 8192;
 865                        break;
 866                case 88200:
 867                        *n = 25088;
 868                        break;
 869                case 96000:
 870                        *n = 16384;
 871                        break;
 872                case 176400:
 873                        *n = 50176;
 874                        break;
 875                case 192000:
 876                        *n = 32768;
 877                        break;
 878                default:
 879                        return -EINVAL;
 880                }
 881        } else {
 882                switch (sample_freq) {
 883                case 32000:
 884                        *n = 4096;
 885                        break;
 886                case 44100:
 887                        *n = 6272;
 888                        break;
 889                case 48000:
 890                        *n = 6144;
 891                        break;
 892                case 88200:
 893                        *n = 12544;
 894                        break;
 895                case 96000:
 896                        *n = 12288;
 897                        break;
 898                case 176400:
 899                        *n = 25088;
 900                        break;
 901                case 192000:
 902                        *n = 24576;
 903                        break;
 904                default:
 905                        return -EINVAL;
 906                }
 907        }
 908        /* Calculate CTS. See HDMI 1.3a or 1.4a specifications */
 909        *cts = pclk * (*n / 128) * deep_color / (sample_freq / 10);
 910
 911        return 0;
 912}
 913
 914int hdmi_audio_enable(void)
 915{
 916        DSSDBG("audio_enable\n");
 917
 918        return hdmi.ip_data.ops->audio_enable(&hdmi.ip_data);
 919}
 920
 921void hdmi_audio_disable(void)
 922{
 923        DSSDBG("audio_disable\n");
 924
 925        hdmi.ip_data.ops->audio_disable(&hdmi.ip_data);
 926}
 927
 928int hdmi_audio_start(void)
 929{
 930        DSSDBG("audio_start\n");
 931
 932        return hdmi.ip_data.ops->audio_start(&hdmi.ip_data);
 933}
 934
 935void hdmi_audio_stop(void)
 936{
 937        DSSDBG("audio_stop\n");
 938
 939        hdmi.ip_data.ops->audio_stop(&hdmi.ip_data);
 940}
 941
 942bool hdmi_mode_has_audio(void)
 943{
 944        if (hdmi.ip_data.cfg.cm.mode == HDMI_HDMI)
 945                return true;
 946        else
 947                return false;
 948}
 949
 950int hdmi_audio_config(struct omap_dss_audio *audio)
 951{
 952        return hdmi.ip_data.ops->audio_config(&hdmi.ip_data, audio);
 953}
 954
 955#endif
 956
 957static struct omap_dss_device *hdmi_find_dssdev(struct platform_device *pdev)
 958{
 959        struct omap_dss_board_info *pdata = pdev->dev.platform_data;
 960        const char *def_disp_name = omapdss_get_default_display_name();
 961        struct omap_dss_device *def_dssdev;
 962        int i;
 963
 964        def_dssdev = NULL;
 965
 966        for (i = 0; i < pdata->num_devices; ++i) {
 967                struct omap_dss_device *dssdev = pdata->devices[i];
 968
 969                if (dssdev->type != OMAP_DISPLAY_TYPE_HDMI)
 970                        continue;
 971
 972                if (def_dssdev == NULL)
 973                        def_dssdev = dssdev;
 974
 975                if (def_disp_name != NULL &&
 976                                strcmp(dssdev->name, def_disp_name) == 0) {
 977                        def_dssdev = dssdev;
 978                        break;
 979                }
 980        }
 981
 982        return def_dssdev;
 983}
 984
 985static int hdmi_probe_pdata(struct platform_device *pdev)
 986{
 987        struct omap_dss_device *plat_dssdev;
 988        struct omap_dss_device *dssdev;
 989        struct omap_dss_hdmi_data *priv;
 990        int r;
 991
 992        plat_dssdev = hdmi_find_dssdev(pdev);
 993
 994        if (!plat_dssdev)
 995                return 0;
 996
 997        dssdev = dss_alloc_and_init_device(&pdev->dev);
 998        if (!dssdev)
 999                return -ENOMEM;
1000
1001        dss_copy_device_pdata(dssdev, plat_dssdev);
1002
1003        priv = dssdev->data;
1004
1005        hdmi.ct_cp_hpd_gpio = priv->ct_cp_hpd_gpio;
1006        hdmi.ls_oe_gpio = priv->ls_oe_gpio;
1007        hdmi.hpd_gpio = priv->hpd_gpio;
1008
1009        r = hdmi_init_display(dssdev);
1010        if (r) {
1011                DSSERR("device %s init failed: %d\n", dssdev->name, r);
1012                dss_put_device(dssdev);
1013                return r;
1014        }
1015
1016        r = omapdss_output_set_device(&hdmi.output, dssdev);
1017        if (r) {
1018                DSSERR("failed to connect output to new device: %s\n",
1019                                dssdev->name);
1020                dss_put_device(dssdev);
1021                return r;
1022        }
1023
1024        r = dss_add_device(dssdev);
1025        if (r) {
1026                DSSERR("device %s register failed: %d\n", dssdev->name, r);
1027                omapdss_output_unset_device(&hdmi.output);
1028                hdmi_uninit_display(dssdev);
1029                dss_put_device(dssdev);
1030                return r;
1031        }
1032
1033        return 0;
1034}
1035
1036static void hdmi_init_output(struct platform_device *pdev)
1037{
1038        struct omap_dss_output *out = &hdmi.output;
1039
1040        out->pdev = pdev;
1041        out->id = OMAP_DSS_OUTPUT_HDMI;
1042        out->type = OMAP_DISPLAY_TYPE_HDMI;
1043        out->name = "hdmi.0";
1044        out->dispc_channel = OMAP_DSS_CHANNEL_DIGIT;
1045
1046        dss_register_output(out);
1047}
1048
1049static void __exit hdmi_uninit_output(struct platform_device *pdev)
1050{
1051        struct omap_dss_output *out = &hdmi.output;
1052
1053        dss_unregister_output(out);
1054}
1055
1056/* HDMI HW IP initialisation */
1057static int omapdss_hdmihw_probe(struct platform_device *pdev)
1058{
1059        struct resource *res;
1060        int r;
1061
1062        hdmi.pdev = pdev;
1063
1064        mutex_init(&hdmi.lock);
1065        mutex_init(&hdmi.ip_data.lock);
1066
1067        res = platform_get_resource(hdmi.pdev, IORESOURCE_MEM, 0);
1068
1069        /* Base address taken from platform */
1070        hdmi.ip_data.base_wp = devm_ioremap_resource(&pdev->dev, res);
1071        if (IS_ERR(hdmi.ip_data.base_wp))
1072                return PTR_ERR(hdmi.ip_data.base_wp);
1073
1074        r = hdmi_get_clocks(pdev);
1075        if (r) {
1076                DSSERR("can't get clocks\n");
1077                return r;
1078        }
1079
1080        pm_runtime_enable(&pdev->dev);
1081
1082        hdmi.ip_data.core_sys_offset = HDMI_CORE_SYS;
1083        hdmi.ip_data.core_av_offset = HDMI_CORE_AV;
1084        hdmi.ip_data.pll_offset = HDMI_PLLCTRL;
1085        hdmi.ip_data.phy_offset = HDMI_PHY;
1086
1087        hdmi_init_output(pdev);
1088
1089        r = hdmi_panel_init();
1090        if (r) {
1091                DSSERR("can't init panel\n");
1092                return r;
1093        }
1094
1095        dss_debugfs_create_file("hdmi", hdmi_dump_regs);
1096
1097        r = hdmi_probe_pdata(pdev);
1098        if (r) {
1099                hdmi_panel_exit();
1100                hdmi_uninit_output(pdev);
1101                pm_runtime_disable(&pdev->dev);
1102                return r;
1103        }
1104
1105        return 0;
1106}
1107
1108static int __exit hdmi_remove_child(struct device *dev, void *data)
1109{
1110        struct omap_dss_device *dssdev = to_dss_device(dev);
1111        hdmi_uninit_display(dssdev);
1112        return 0;
1113}
1114
1115static int __exit omapdss_hdmihw_remove(struct platform_device *pdev)
1116{
1117        device_for_each_child(&pdev->dev, NULL, hdmi_remove_child);
1118
1119        dss_unregister_child_devices(&pdev->dev);
1120
1121        hdmi_panel_exit();
1122
1123        hdmi_uninit_output(pdev);
1124
1125        pm_runtime_disable(&pdev->dev);
1126
1127        return 0;
1128}
1129
1130static int hdmi_runtime_suspend(struct device *dev)
1131{
1132        clk_disable_unprepare(hdmi.sys_clk);
1133
1134        dispc_runtime_put();
1135
1136        return 0;
1137}
1138
1139static int hdmi_runtime_resume(struct device *dev)
1140{
1141        int r;
1142
1143        r = dispc_runtime_get();
1144        if (r < 0)
1145                return r;
1146
1147        clk_prepare_enable(hdmi.sys_clk);
1148
1149        return 0;
1150}
1151
1152static const struct dev_pm_ops hdmi_pm_ops = {
1153        .runtime_suspend = hdmi_runtime_suspend,
1154        .runtime_resume = hdmi_runtime_resume,
1155};
1156
1157static struct platform_driver omapdss_hdmihw_driver = {
1158        .probe          = omapdss_hdmihw_probe,
1159        .remove         = __exit_p(omapdss_hdmihw_remove),
1160        .driver         = {
1161                .name   = "omapdss_hdmi",
1162                .owner  = THIS_MODULE,
1163                .pm     = &hdmi_pm_ops,
1164        },
1165};
1166
1167int __init hdmi_init_platform_driver(void)
1168{
1169        return platform_driver_register(&omapdss_hdmihw_driver);
1170}
1171
1172void __exit hdmi_uninit_platform_driver(void)
1173{
1174        platform_driver_unregister(&omapdss_hdmihw_driver);
1175}
1176