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