linux/drivers/gpu/drm/exynos/exynos_hdmi.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2011 Samsung Electronics Co.Ltd
   3 * Authors:
   4 * Seung-Woo Kim <sw0312.kim@samsung.com>
   5 *      Inki Dae <inki.dae@samsung.com>
   6 *      Joonyoung Shim <jy0922.shim@samsung.com>
   7 *
   8 * Based on drivers/media/video/s5p-tv/hdmi_drv.c
   9 *
  10 * This program is free software; you can redistribute it and/or modify it
  11 * under the terms of the GNU General Public License as published by the
  12 * Free Software Foundation; either version 2 of the License, or (at your
  13 * option) any later version.
  14 *
  15 */
  16
  17#include <drm/drmP.h>
  18#include <drm/drm_atomic_helper.h>
  19#include <drm/drm_edid.h>
  20#include <drm/drm_probe_helper.h>
  21
  22#include "regs-hdmi.h"
  23
  24#include <linux/kernel.h>
  25#include <linux/wait.h>
  26#include <linux/i2c.h>
  27#include <linux/platform_device.h>
  28#include <linux/interrupt.h>
  29#include <linux/irq.h>
  30#include <linux/delay.h>
  31#include <linux/pm_runtime.h>
  32#include <linux/clk.h>
  33#include <linux/gpio/consumer.h>
  34#include <linux/regulator/consumer.h>
  35#include <linux/io.h>
  36#include <linux/of_address.h>
  37#include <linux/of_device.h>
  38#include <linux/of_graph.h>
  39#include <linux/hdmi.h>
  40#include <linux/component.h>
  41#include <linux/mfd/syscon.h>
  42#include <linux/regmap.h>
  43#include <sound/hdmi-codec.h>
  44#include <drm/exynos_drm.h>
  45
  46#include <media/cec-notifier.h>
  47
  48#include "exynos_drm_crtc.h"
  49
  50#define HOTPLUG_DEBOUNCE_MS             1100
  51
  52enum hdmi_type {
  53        HDMI_TYPE13,
  54        HDMI_TYPE14,
  55        HDMI_TYPE_COUNT
  56};
  57
  58#define HDMI_MAPPED_BASE 0xffff0000
  59
  60enum hdmi_mapped_regs {
  61        HDMI_PHY_STATUS = HDMI_MAPPED_BASE,
  62        HDMI_PHY_RSTOUT,
  63        HDMI_ACR_CON,
  64        HDMI_ACR_MCTS0,
  65        HDMI_ACR_CTS0,
  66        HDMI_ACR_N0
  67};
  68
  69static const u32 hdmi_reg_map[][HDMI_TYPE_COUNT] = {
  70        { HDMI_V13_PHY_STATUS, HDMI_PHY_STATUS_0 },
  71        { HDMI_V13_PHY_RSTOUT, HDMI_V14_PHY_RSTOUT },
  72        { HDMI_V13_ACR_CON, HDMI_V14_ACR_CON },
  73        { HDMI_V13_ACR_MCTS0, HDMI_V14_ACR_MCTS0 },
  74        { HDMI_V13_ACR_CTS0, HDMI_V14_ACR_CTS0 },
  75        { HDMI_V13_ACR_N0, HDMI_V14_ACR_N0 },
  76};
  77
  78static const char * const supply[] = {
  79        "vdd",
  80        "vdd_osc",
  81        "vdd_pll",
  82};
  83
  84struct hdmiphy_config {
  85        int pixel_clock;
  86        u8 conf[32];
  87};
  88
  89struct hdmiphy_configs {
  90        int count;
  91        const struct hdmiphy_config *data;
  92};
  93
  94struct string_array_spec {
  95        int count;
  96        const char * const *data;
  97};
  98
  99#define INIT_ARRAY_SPEC(a) { .count = ARRAY_SIZE(a), .data = a }
 100
 101struct hdmi_driver_data {
 102        unsigned int type;
 103        unsigned int is_apb_phy:1;
 104        unsigned int has_sysreg:1;
 105        struct hdmiphy_configs phy_confs;
 106        struct string_array_spec clk_gates;
 107        /*
 108         * Array of triplets (p_off, p_on, clock), where p_off and p_on are
 109         * required parents of clock when HDMI-PHY is respectively off or on.
 110         */
 111        struct string_array_spec clk_muxes;
 112};
 113
 114struct hdmi_audio {
 115        struct platform_device          *pdev;
 116        struct hdmi_audio_infoframe     infoframe;
 117        struct hdmi_codec_params        params;
 118        bool                            mute;
 119};
 120
 121struct hdmi_context {
 122        struct drm_encoder              encoder;
 123        struct device                   *dev;
 124        struct drm_device               *drm_dev;
 125        struct drm_connector            connector;
 126        bool                            dvi_mode;
 127        struct delayed_work             hotplug_work;
 128        struct cec_notifier             *notifier;
 129        const struct hdmi_driver_data   *drv_data;
 130
 131        void __iomem                    *regs;
 132        void __iomem                    *regs_hdmiphy;
 133        struct i2c_client               *hdmiphy_port;
 134        struct i2c_adapter              *ddc_adpt;
 135        struct gpio_desc                *hpd_gpio;
 136        int                             irq;
 137        struct regmap                   *pmureg;
 138        struct regmap                   *sysreg;
 139        struct clk                      **clk_gates;
 140        struct clk                      **clk_muxes;
 141        struct regulator_bulk_data      regul_bulk[ARRAY_SIZE(supply)];
 142        struct regulator                *reg_hdmi_en;
 143        struct exynos_drm_clk           phy_clk;
 144        struct drm_bridge               *bridge;
 145
 146        /* mutex protecting subsequent fields below */
 147        struct mutex                    mutex;
 148        struct hdmi_audio               audio;
 149        bool                            powered;
 150};
 151
 152static inline struct hdmi_context *encoder_to_hdmi(struct drm_encoder *e)
 153{
 154        return container_of(e, struct hdmi_context, encoder);
 155}
 156
 157static inline struct hdmi_context *connector_to_hdmi(struct drm_connector *c)
 158{
 159        return container_of(c, struct hdmi_context, connector);
 160}
 161
 162static const struct hdmiphy_config hdmiphy_v13_configs[] = {
 163        {
 164                .pixel_clock = 27000000,
 165                .conf = {
 166                        0x01, 0x05, 0x00, 0xD8, 0x10, 0x1C, 0x30, 0x40,
 167                        0x6B, 0x10, 0x02, 0x51, 0xDF, 0xF2, 0x54, 0x87,
 168                        0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
 169                        0x22, 0x40, 0xE3, 0x26, 0x00, 0x00, 0x00, 0x80,
 170                },
 171        },
 172        {
 173                .pixel_clock = 27027000,
 174                .conf = {
 175                        0x01, 0x05, 0x00, 0xD4, 0x10, 0x9C, 0x09, 0x64,
 176                        0x6B, 0x10, 0x02, 0x51, 0xDF, 0xF2, 0x54, 0x87,
 177                        0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
 178                        0x22, 0x40, 0xE3, 0x26, 0x00, 0x00, 0x00, 0x80,
 179                },
 180        },
 181        {
 182                .pixel_clock = 74176000,
 183                .conf = {
 184                        0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xef, 0x5B,
 185                        0x6D, 0x10, 0x01, 0x51, 0xef, 0xF3, 0x54, 0xb9,
 186                        0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
 187                        0x22, 0x40, 0xa5, 0x26, 0x01, 0x00, 0x00, 0x80,
 188                },
 189        },
 190        {
 191                .pixel_clock = 74250000,
 192                .conf = {
 193                        0x01, 0x05, 0x00, 0xd8, 0x10, 0x9c, 0xf8, 0x40,
 194                        0x6a, 0x10, 0x01, 0x51, 0xff, 0xf1, 0x54, 0xba,
 195                        0x84, 0x00, 0x10, 0x38, 0x00, 0x08, 0x10, 0xe0,
 196                        0x22, 0x40, 0xa4, 0x26, 0x01, 0x00, 0x00, 0x80,
 197                },
 198        },
 199        {
 200                .pixel_clock = 148500000,
 201                .conf = {
 202                        0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xf8, 0x40,
 203                        0x6A, 0x18, 0x00, 0x51, 0xff, 0xF1, 0x54, 0xba,
 204                        0x84, 0x00, 0x10, 0x38, 0x00, 0x08, 0x10, 0xE0,
 205                        0x22, 0x40, 0xa4, 0x26, 0x02, 0x00, 0x00, 0x80,
 206                },
 207        },
 208};
 209
 210static const struct hdmiphy_config hdmiphy_v14_configs[] = {
 211        {
 212                .pixel_clock = 25200000,
 213                .conf = {
 214                        0x01, 0x51, 0x2A, 0x75, 0x40, 0x01, 0x00, 0x08,
 215                        0x82, 0x80, 0xfc, 0xd8, 0x45, 0xa0, 0xac, 0x80,
 216                        0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
 217                        0x54, 0xf4, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
 218                },
 219        },
 220        {
 221                .pixel_clock = 27000000,
 222                .conf = {
 223                        0x01, 0xd1, 0x22, 0x51, 0x40, 0x08, 0xfc, 0x20,
 224                        0x98, 0xa0, 0xcb, 0xd8, 0x45, 0xa0, 0xac, 0x80,
 225                        0x06, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
 226                        0x54, 0xe4, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
 227                },
 228        },
 229        {
 230                .pixel_clock = 27027000,
 231                .conf = {
 232                        0x01, 0xd1, 0x2d, 0x72, 0x40, 0x64, 0x12, 0x08,
 233                        0x43, 0xa0, 0x0e, 0xd9, 0x45, 0xa0, 0xac, 0x80,
 234                        0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
 235                        0x54, 0xe3, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
 236                },
 237        },
 238        {
 239                .pixel_clock = 36000000,
 240                .conf = {
 241                        0x01, 0x51, 0x2d, 0x55, 0x40, 0x01, 0x00, 0x08,
 242                        0x82, 0x80, 0x0e, 0xd9, 0x45, 0xa0, 0xac, 0x80,
 243                        0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
 244                        0x54, 0xab, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
 245                },
 246        },
 247        {
 248                .pixel_clock = 40000000,
 249                .conf = {
 250                        0x01, 0x51, 0x32, 0x55, 0x40, 0x01, 0x00, 0x08,
 251                        0x82, 0x80, 0x2c, 0xd9, 0x45, 0xa0, 0xac, 0x80,
 252                        0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
 253                        0x54, 0x9a, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
 254                },
 255        },
 256        {
 257                .pixel_clock = 65000000,
 258                .conf = {
 259                        0x01, 0xd1, 0x36, 0x34, 0x40, 0x1e, 0x0a, 0x08,
 260                        0x82, 0xa0, 0x45, 0xd9, 0x45, 0xa0, 0xac, 0x80,
 261                        0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
 262                        0x54, 0xbd, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
 263                },
 264        },
 265        {
 266                .pixel_clock = 71000000,
 267                .conf = {
 268                        0x01, 0xd1, 0x3b, 0x35, 0x40, 0x0c, 0x04, 0x08,
 269                        0x85, 0xa0, 0x63, 0xd9, 0x45, 0xa0, 0xac, 0x80,
 270                        0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
 271                        0x54, 0xad, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
 272                },
 273        },
 274        {
 275                .pixel_clock = 73250000,
 276                .conf = {
 277                        0x01, 0xd1, 0x3d, 0x35, 0x40, 0x18, 0x02, 0x08,
 278                        0x83, 0xa0, 0x6e, 0xd9, 0x45, 0xa0, 0xac, 0x80,
 279                        0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
 280                        0x54, 0xa8, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
 281                },
 282        },
 283        {
 284                .pixel_clock = 74176000,
 285                .conf = {
 286                        0x01, 0xd1, 0x3e, 0x35, 0x40, 0x5b, 0xde, 0x08,
 287                        0x82, 0xa0, 0x73, 0xd9, 0x45, 0xa0, 0xac, 0x80,
 288                        0x56, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
 289                        0x54, 0xa6, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
 290                },
 291        },
 292        {
 293                .pixel_clock = 74250000,
 294                .conf = {
 295                        0x01, 0xd1, 0x1f, 0x10, 0x40, 0x40, 0xf8, 0x08,
 296                        0x81, 0xa0, 0xba, 0xd8, 0x45, 0xa0, 0xac, 0x80,
 297                        0x3c, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
 298                        0x54, 0xa5, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
 299                },
 300        },
 301        {
 302                .pixel_clock = 83500000,
 303                .conf = {
 304                        0x01, 0xd1, 0x23, 0x11, 0x40, 0x0c, 0xfb, 0x08,
 305                        0x85, 0xa0, 0xd1, 0xd8, 0x45, 0xa0, 0xac, 0x80,
 306                        0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
 307                        0x54, 0x93, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
 308                },
 309        },
 310        {
 311                .pixel_clock = 85500000,
 312                .conf = {
 313                        0x01, 0xd1, 0x24, 0x11, 0x40, 0x40, 0xd0, 0x08,
 314                        0x84, 0xa0, 0xd6, 0xd8, 0x45, 0xa0, 0xac, 0x80,
 315                        0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
 316                        0x54, 0x90, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
 317                },
 318        },
 319        {
 320                .pixel_clock = 106500000,
 321                .conf = {
 322                        0x01, 0xd1, 0x2c, 0x12, 0x40, 0x0c, 0x09, 0x08,
 323                        0x84, 0xa0, 0x0a, 0xd9, 0x45, 0xa0, 0xac, 0x80,
 324                        0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
 325                        0x54, 0x73, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
 326                },
 327        },
 328        {
 329                .pixel_clock = 108000000,
 330                .conf = {
 331                        0x01, 0x51, 0x2d, 0x15, 0x40, 0x01, 0x00, 0x08,
 332                        0x82, 0x80, 0x0e, 0xd9, 0x45, 0xa0, 0xac, 0x80,
 333                        0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
 334                        0x54, 0xc7, 0x25, 0x03, 0x00, 0x00, 0x01, 0x80,
 335                },
 336        },
 337        {
 338                .pixel_clock = 115500000,
 339                .conf = {
 340                        0x01, 0xd1, 0x30, 0x12, 0x40, 0x40, 0x10, 0x08,
 341                        0x80, 0x80, 0x21, 0xd9, 0x45, 0xa0, 0xac, 0x80,
 342                        0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
 343                        0x54, 0xaa, 0x25, 0x03, 0x00, 0x00, 0x01, 0x80,
 344                },
 345        },
 346        {
 347                .pixel_clock = 119000000,
 348                .conf = {
 349                        0x01, 0xd1, 0x32, 0x1a, 0x40, 0x30, 0xd8, 0x08,
 350                        0x04, 0xa0, 0x2a, 0xd9, 0x45, 0xa0, 0xac, 0x80,
 351                        0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
 352                        0x54, 0x9d, 0x25, 0x03, 0x00, 0x00, 0x01, 0x80,
 353                },
 354        },
 355        {
 356                .pixel_clock = 146250000,
 357                .conf = {
 358                        0x01, 0xd1, 0x3d, 0x15, 0x40, 0x18, 0xfd, 0x08,
 359                        0x83, 0xa0, 0x6e, 0xd9, 0x45, 0xa0, 0xac, 0x80,
 360                        0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
 361                        0x54, 0x50, 0x25, 0x03, 0x00, 0x00, 0x01, 0x80,
 362                },
 363        },
 364        {
 365                .pixel_clock = 148500000,
 366                .conf = {
 367                        0x01, 0xd1, 0x1f, 0x00, 0x40, 0x40, 0xf8, 0x08,
 368                        0x81, 0xa0, 0xba, 0xd8, 0x45, 0xa0, 0xac, 0x80,
 369                        0x3c, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
 370                        0x54, 0x4b, 0x25, 0x03, 0x00, 0x00, 0x01, 0x80,
 371                },
 372        },
 373};
 374
 375static const struct hdmiphy_config hdmiphy_5420_configs[] = {
 376        {
 377                .pixel_clock = 25200000,
 378                .conf = {
 379                        0x01, 0x52, 0x3F, 0x55, 0x40, 0x01, 0x00, 0xC8,
 380                        0x82, 0xC8, 0xBD, 0xD8, 0x45, 0xA0, 0xAC, 0x80,
 381                        0x06, 0x80, 0x01, 0x84, 0x05, 0x02, 0x24, 0x66,
 382                        0x54, 0xF4, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
 383                },
 384        },
 385        {
 386                .pixel_clock = 27000000,
 387                .conf = {
 388                        0x01, 0xD1, 0x22, 0x51, 0x40, 0x08, 0xFC, 0xE0,
 389                        0x98, 0xE8, 0xCB, 0xD8, 0x45, 0xA0, 0xAC, 0x80,
 390                        0x06, 0x80, 0x09, 0x84, 0x05, 0x02, 0x24, 0x66,
 391                        0x54, 0xE4, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
 392                },
 393        },
 394        {
 395                .pixel_clock = 27027000,
 396                .conf = {
 397                        0x01, 0xD1, 0x2D, 0x72, 0x40, 0x64, 0x12, 0xC8,
 398                        0x43, 0xE8, 0x0E, 0xD9, 0x45, 0xA0, 0xAC, 0x80,
 399                        0x26, 0x80, 0x09, 0x84, 0x05, 0x02, 0x24, 0x66,
 400                        0x54, 0xE3, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
 401                },
 402        },
 403        {
 404                .pixel_clock = 36000000,
 405                .conf = {
 406                        0x01, 0x51, 0x2D, 0x55, 0x40, 0x40, 0x00, 0xC8,
 407                        0x02, 0xC8, 0x0E, 0xD9, 0x45, 0xA0, 0xAC, 0x80,
 408                        0x08, 0x80, 0x09, 0x84, 0x05, 0x02, 0x24, 0x66,
 409                        0x54, 0xAB, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
 410                },
 411        },
 412        {
 413                .pixel_clock = 40000000,
 414                .conf = {
 415                        0x01, 0xD1, 0x21, 0x31, 0x40, 0x3C, 0x28, 0xC8,
 416                        0x87, 0xE8, 0xC8, 0xD8, 0x45, 0xA0, 0xAC, 0x80,
 417                        0x08, 0x80, 0x09, 0x84, 0x05, 0x02, 0x24, 0x66,
 418                        0x54, 0x9A, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
 419                },
 420        },
 421        {
 422                .pixel_clock = 65000000,
 423                .conf = {
 424                        0x01, 0xD1, 0x36, 0x34, 0x40, 0x0C, 0x04, 0xC8,
 425                        0x82, 0xE8, 0x45, 0xD9, 0x45, 0xA0, 0xAC, 0x80,
 426                        0x08, 0x80, 0x09, 0x84, 0x05, 0x02, 0x24, 0x66,
 427                        0x54, 0xBD, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
 428                },
 429        },
 430        {
 431                .pixel_clock = 71000000,
 432                .conf = {
 433                        0x01, 0xD1, 0x3B, 0x35, 0x40, 0x0C, 0x04, 0xC8,
 434                        0x85, 0xE8, 0x63, 0xD9, 0x45, 0xA0, 0xAC, 0x80,
 435                        0x08, 0x80, 0x09, 0x84, 0x05, 0x02, 0x24, 0x66,
 436                        0x54, 0x57, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
 437                },
 438        },
 439        {
 440                .pixel_clock = 73250000,
 441                .conf = {
 442                        0x01, 0xD1, 0x1F, 0x10, 0x40, 0x78, 0x8D, 0xC8,
 443                        0x81, 0xE8, 0xB7, 0xD8, 0x45, 0xA0, 0xAC, 0x80,
 444                        0x56, 0x80, 0x09, 0x84, 0x05, 0x02, 0x24, 0x66,
 445                        0x54, 0xA8, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
 446                },
 447        },
 448        {
 449                .pixel_clock = 74176000,
 450                .conf = {
 451                        0x01, 0xD1, 0x1F, 0x10, 0x40, 0x5B, 0xEF, 0xC8,
 452                        0x81, 0xE8, 0xB9, 0xD8, 0x45, 0xA0, 0xAC, 0x80,
 453                        0x56, 0x80, 0x09, 0x84, 0x05, 0x02, 0x24, 0x66,
 454                        0x54, 0xA6, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
 455                },
 456        },
 457        {
 458                .pixel_clock = 74250000,
 459                .conf = {
 460                        0x01, 0xD1, 0x1F, 0x10, 0x40, 0x40, 0xF8, 0x08,
 461                        0x81, 0xE8, 0xBA, 0xD8, 0x45, 0xA0, 0xAC, 0x80,
 462                        0x26, 0x80, 0x09, 0x84, 0x05, 0x22, 0x24, 0x66,
 463                        0x54, 0xA5, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
 464                },
 465        },
 466        {
 467                .pixel_clock = 83500000,
 468                .conf = {
 469                        0x01, 0xD1, 0x23, 0x11, 0x40, 0x0C, 0xFB, 0xC8,
 470                        0x85, 0xE8, 0xD1, 0xD8, 0x45, 0xA0, 0xAC, 0x80,
 471                        0x08, 0x80, 0x09, 0x84, 0x05, 0x02, 0x24, 0x66,
 472                        0x54, 0x4A, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
 473                },
 474        },
 475        {
 476                .pixel_clock = 88750000,
 477                .conf = {
 478                        0x01, 0xD1, 0x25, 0x11, 0x40, 0x18, 0xFF, 0xC8,
 479                        0x83, 0xE8, 0xDE, 0xD8, 0x45, 0xA0, 0xAC, 0x80,
 480                        0x08, 0x80, 0x09, 0x84, 0x05, 0x02, 0x24, 0x66,
 481                        0x54, 0x45, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
 482                },
 483        },
 484        {
 485                .pixel_clock = 106500000,
 486                .conf = {
 487                        0x01, 0xD1, 0x2C, 0x12, 0x40, 0x0C, 0x09, 0xC8,
 488                        0x84, 0xE8, 0x0A, 0xD9, 0x45, 0xA0, 0xAC, 0x80,
 489                        0x08, 0x80, 0x09, 0x84, 0x05, 0x02, 0x24, 0x66,
 490                        0x54, 0x73, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
 491                },
 492        },
 493        {
 494                .pixel_clock = 108000000,
 495                .conf = {
 496                        0x01, 0x51, 0x2D, 0x15, 0x40, 0x01, 0x00, 0xC8,
 497                        0x82, 0xC8, 0x0E, 0xD9, 0x45, 0xA0, 0xAC, 0x80,
 498                        0x08, 0x80, 0x09, 0x84, 0x05, 0x02, 0x24, 0x66,
 499                        0x54, 0xC7, 0x25, 0x03, 0x00, 0x00, 0x01, 0x80,
 500                },
 501        },
 502        {
 503                .pixel_clock = 115500000,
 504                .conf = {
 505                        0x01, 0xD1, 0x30, 0x14, 0x40, 0x0C, 0x03, 0xC8,
 506                        0x88, 0xE8, 0x21, 0xD9, 0x45, 0xA0, 0xAC, 0x80,
 507                        0x08, 0x80, 0x09, 0x84, 0x05, 0x02, 0x24, 0x66,
 508                        0x54, 0x6A, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
 509                },
 510        },
 511        {
 512                .pixel_clock = 146250000,
 513                .conf = {
 514                        0x01, 0xD1, 0x3D, 0x15, 0x40, 0x18, 0xFD, 0xC8,
 515                        0x83, 0xE8, 0x6E, 0xD9, 0x45, 0xA0, 0xAC, 0x80,
 516                        0x08, 0x80, 0x09, 0x84, 0x05, 0x02, 0x24, 0x66,
 517                        0x54, 0x54, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
 518                },
 519        },
 520        {
 521                .pixel_clock = 148500000,
 522                .conf = {
 523                        0x01, 0xD1, 0x1F, 0x00, 0x40, 0x40, 0xF8, 0x08,
 524                        0x81, 0xE8, 0xBA, 0xD8, 0x45, 0xA0, 0xAC, 0x80,
 525                        0x26, 0x80, 0x09, 0x84, 0x05, 0x22, 0x24, 0x66,
 526                        0x54, 0x4B, 0x25, 0x03, 0x00, 0x80, 0x01, 0x80,
 527                },
 528        },
 529};
 530
 531static const struct hdmiphy_config hdmiphy_5433_configs[] = {
 532        {
 533                .pixel_clock = 27000000,
 534                .conf = {
 535                        0x01, 0x51, 0x2d, 0x75, 0x01, 0x00, 0x88, 0x02,
 536                        0x72, 0x50, 0x44, 0x8c, 0x27, 0x00, 0x7c, 0xac,
 537                        0xd6, 0x2b, 0x67, 0x00, 0x00, 0x04, 0x00, 0x30,
 538                        0x08, 0x10, 0x01, 0x01, 0x48, 0x40, 0x00, 0x40,
 539                },
 540        },
 541        {
 542                .pixel_clock = 27027000,
 543                .conf = {
 544                        0x01, 0x51, 0x2d, 0x72, 0x64, 0x09, 0x88, 0xc3,
 545                        0x71, 0x50, 0x44, 0x8c, 0x27, 0x00, 0x7c, 0xac,
 546                        0xd6, 0x2b, 0x67, 0x00, 0x00, 0x04, 0x00, 0x30,
 547                        0x08, 0x10, 0x01, 0x01, 0x48, 0x40, 0x00, 0x40,
 548                },
 549        },
 550        {
 551                .pixel_clock = 40000000,
 552                .conf = {
 553                        0x01, 0x51, 0x32, 0x55, 0x01, 0x00, 0x88, 0x02,
 554                        0x4d, 0x50, 0x44, 0x8C, 0x27, 0x00, 0x7C, 0xAC,
 555                        0xD6, 0x2B, 0x67, 0x00, 0x00, 0x04, 0x00, 0x30,
 556                        0x08, 0x10, 0x01, 0x01, 0x48, 0x40, 0x00, 0x40,
 557                },
 558        },
 559        {
 560                .pixel_clock = 50000000,
 561                .conf = {
 562                        0x01, 0x51, 0x34, 0x40, 0x64, 0x09, 0x88, 0xc3,
 563                        0x3d, 0x50, 0x44, 0x8C, 0x27, 0x00, 0x7C, 0xAC,
 564                        0xD6, 0x2B, 0x67, 0x00, 0x00, 0x04, 0x00, 0x30,
 565                        0x08, 0x10, 0x01, 0x01, 0x48, 0x40, 0x00, 0x40,
 566                },
 567        },
 568        {
 569                .pixel_clock = 65000000,
 570                .conf = {
 571                        0x01, 0x51, 0x36, 0x31, 0x40, 0x10, 0x04, 0xc6,
 572                        0x2e, 0xe8, 0x44, 0x8C, 0x27, 0x00, 0x7C, 0xAC,
 573                        0xD6, 0x2B, 0x67, 0x00, 0x00, 0x04, 0x00, 0x30,
 574                        0x08, 0x10, 0x01, 0x01, 0x48, 0x40, 0x00, 0x40,
 575                },
 576        },
 577        {
 578                .pixel_clock = 74176000,
 579                .conf = {
 580                        0x01, 0x51, 0x3E, 0x35, 0x5B, 0xDE, 0x88, 0x42,
 581                        0x53, 0x51, 0x44, 0x8C, 0x27, 0x00, 0x7C, 0xAC,
 582                        0xD6, 0x2B, 0x67, 0x00, 0x00, 0x04, 0x00, 0x30,
 583                        0x08, 0x10, 0x01, 0x01, 0x48, 0x40, 0x00, 0x40,
 584                },
 585        },
 586        {
 587                .pixel_clock = 74250000,
 588                .conf = {
 589                        0x01, 0x51, 0x3E, 0x35, 0x40, 0xF0, 0x88, 0xC2,
 590                        0x52, 0x51, 0x44, 0x8C, 0x27, 0x00, 0x7C, 0xAC,
 591                        0xD6, 0x2B, 0x67, 0x00, 0x00, 0x04, 0x00, 0x30,
 592                        0x08, 0x10, 0x01, 0x01, 0x48, 0x40, 0x00, 0x40,
 593                },
 594        },
 595        {
 596                .pixel_clock = 108000000,
 597                .conf = {
 598                        0x01, 0x51, 0x2d, 0x15, 0x01, 0x00, 0x88, 0x02,
 599                        0x72, 0x52, 0x44, 0x8C, 0x27, 0x00, 0x7C, 0xAC,
 600                        0xD6, 0x2B, 0x67, 0x00, 0x00, 0x04, 0x00, 0x30,
 601                        0x08, 0x10, 0x01, 0x01, 0x48, 0x40, 0x00, 0x40,
 602                },
 603        },
 604        {
 605                .pixel_clock = 148500000,
 606                .conf = {
 607                        0x01, 0x51, 0x1f, 0x00, 0x40, 0xf8, 0x88, 0xc1,
 608                        0x52, 0x52, 0x24, 0x0c, 0x24, 0x0f, 0x7c, 0xa5,
 609                        0xd4, 0x2b, 0x87, 0x00, 0x00, 0x04, 0x00, 0x30,
 610                        0x08, 0x10, 0x01, 0x01, 0x48, 0x4a, 0x00, 0x40,
 611                },
 612        },
 613        {
 614                .pixel_clock = 297000000,
 615                .conf = {
 616                        0x01, 0x51, 0x3E, 0x05, 0x40, 0xF0, 0x88, 0xC2,
 617                        0x52, 0x53, 0x44, 0x8C, 0x27, 0x00, 0x7C, 0xAC,
 618                        0xD6, 0x2B, 0x67, 0x00, 0x00, 0x04, 0x00, 0x30,
 619                        0x08, 0x10, 0x01, 0x01, 0x48, 0x40, 0x00, 0x40,
 620                },
 621        },
 622};
 623
 624static const char * const hdmi_clk_gates4[] = {
 625        "hdmi", "sclk_hdmi"
 626};
 627
 628static const char * const hdmi_clk_muxes4[] = {
 629        "sclk_pixel", "sclk_hdmiphy", "mout_hdmi"
 630};
 631
 632static const char * const hdmi_clk_gates5433[] = {
 633        "hdmi_pclk", "hdmi_i_pclk", "i_tmds_clk", "i_pixel_clk", "i_spdif_clk"
 634};
 635
 636static const char * const hdmi_clk_muxes5433[] = {
 637        "oscclk", "tmds_clko", "tmds_clko_user",
 638        "oscclk", "pixel_clko", "pixel_clko_user"
 639};
 640
 641static const struct hdmi_driver_data exynos4210_hdmi_driver_data = {
 642        .type           = HDMI_TYPE13,
 643        .phy_confs      = INIT_ARRAY_SPEC(hdmiphy_v13_configs),
 644        .clk_gates      = INIT_ARRAY_SPEC(hdmi_clk_gates4),
 645        .clk_muxes      = INIT_ARRAY_SPEC(hdmi_clk_muxes4),
 646};
 647
 648static const struct hdmi_driver_data exynos4212_hdmi_driver_data = {
 649        .type           = HDMI_TYPE14,
 650        .phy_confs      = INIT_ARRAY_SPEC(hdmiphy_v14_configs),
 651        .clk_gates      = INIT_ARRAY_SPEC(hdmi_clk_gates4),
 652        .clk_muxes      = INIT_ARRAY_SPEC(hdmi_clk_muxes4),
 653};
 654
 655static const struct hdmi_driver_data exynos5420_hdmi_driver_data = {
 656        .type           = HDMI_TYPE14,
 657        .is_apb_phy     = 1,
 658        .phy_confs      = INIT_ARRAY_SPEC(hdmiphy_5420_configs),
 659        .clk_gates      = INIT_ARRAY_SPEC(hdmi_clk_gates4),
 660        .clk_muxes      = INIT_ARRAY_SPEC(hdmi_clk_muxes4),
 661};
 662
 663static const struct hdmi_driver_data exynos5433_hdmi_driver_data = {
 664        .type           = HDMI_TYPE14,
 665        .is_apb_phy     = 1,
 666        .has_sysreg     = 1,
 667        .phy_confs      = INIT_ARRAY_SPEC(hdmiphy_5433_configs),
 668        .clk_gates      = INIT_ARRAY_SPEC(hdmi_clk_gates5433),
 669        .clk_muxes      = INIT_ARRAY_SPEC(hdmi_clk_muxes5433),
 670};
 671
 672static inline u32 hdmi_map_reg(struct hdmi_context *hdata, u32 reg_id)
 673{
 674        if ((reg_id & 0xffff0000) == HDMI_MAPPED_BASE)
 675                return hdmi_reg_map[reg_id & 0xffff][hdata->drv_data->type];
 676        return reg_id;
 677}
 678
 679static inline u32 hdmi_reg_read(struct hdmi_context *hdata, u32 reg_id)
 680{
 681        return readl(hdata->regs + hdmi_map_reg(hdata, reg_id));
 682}
 683
 684static inline void hdmi_reg_writeb(struct hdmi_context *hdata,
 685                                 u32 reg_id, u8 value)
 686{
 687        writel(value, hdata->regs + hdmi_map_reg(hdata, reg_id));
 688}
 689
 690static inline void hdmi_reg_writev(struct hdmi_context *hdata, u32 reg_id,
 691                                   int bytes, u32 val)
 692{
 693        reg_id = hdmi_map_reg(hdata, reg_id);
 694
 695        while (--bytes >= 0) {
 696                writel(val & 0xff, hdata->regs + reg_id);
 697                val >>= 8;
 698                reg_id += 4;
 699        }
 700}
 701
 702static inline void hdmi_reg_write_buf(struct hdmi_context *hdata, u32 reg_id,
 703                                      u8 *buf, int size)
 704{
 705        for (reg_id = hdmi_map_reg(hdata, reg_id); size; --size, reg_id += 4)
 706                writel(*buf++, hdata->regs + reg_id);
 707}
 708
 709static inline void hdmi_reg_writemask(struct hdmi_context *hdata,
 710                                 u32 reg_id, u32 value, u32 mask)
 711{
 712        u32 old;
 713
 714        reg_id = hdmi_map_reg(hdata, reg_id);
 715        old = readl(hdata->regs + reg_id);
 716        value = (value & mask) | (old & ~mask);
 717        writel(value, hdata->regs + reg_id);
 718}
 719
 720static int hdmiphy_reg_write_buf(struct hdmi_context *hdata,
 721                        u32 reg_offset, const u8 *buf, u32 len)
 722{
 723        if ((reg_offset + len) > 32)
 724                return -EINVAL;
 725
 726        if (hdata->hdmiphy_port) {
 727                int ret;
 728
 729                ret = i2c_master_send(hdata->hdmiphy_port, buf, len);
 730                if (ret == len)
 731                        return 0;
 732                return ret;
 733        } else {
 734                int i;
 735                for (i = 0; i < len; i++)
 736                        writel(buf[i], hdata->regs_hdmiphy +
 737                                ((reg_offset + i)<<2));
 738                return 0;
 739        }
 740}
 741
 742static int hdmi_clk_enable_gates(struct hdmi_context *hdata)
 743{
 744        int i, ret;
 745
 746        for (i = 0; i < hdata->drv_data->clk_gates.count; ++i) {
 747                ret = clk_prepare_enable(hdata->clk_gates[i]);
 748                if (!ret)
 749                        continue;
 750
 751                dev_err(hdata->dev, "Cannot enable clock '%s', %d\n",
 752                        hdata->drv_data->clk_gates.data[i], ret);
 753                while (i--)
 754                        clk_disable_unprepare(hdata->clk_gates[i]);
 755                return ret;
 756        }
 757
 758        return 0;
 759}
 760
 761static void hdmi_clk_disable_gates(struct hdmi_context *hdata)
 762{
 763        int i = hdata->drv_data->clk_gates.count;
 764
 765        while (i--)
 766                clk_disable_unprepare(hdata->clk_gates[i]);
 767}
 768
 769static int hdmi_clk_set_parents(struct hdmi_context *hdata, bool to_phy)
 770{
 771        struct device *dev = hdata->dev;
 772        int ret = 0;
 773        int i;
 774
 775        for (i = 0; i < hdata->drv_data->clk_muxes.count; i += 3) {
 776                struct clk **c = &hdata->clk_muxes[i];
 777
 778                ret = clk_set_parent(c[2], c[to_phy]);
 779                if (!ret)
 780                        continue;
 781
 782                dev_err(dev, "Cannot set clock parent of '%s' to '%s', %d\n",
 783                        hdata->drv_data->clk_muxes.data[i + 2],
 784                        hdata->drv_data->clk_muxes.data[i + to_phy], ret);
 785        }
 786
 787        return ret;
 788}
 789
 790static int hdmi_audio_infoframe_apply(struct hdmi_context *hdata)
 791{
 792        struct hdmi_audio_infoframe *infoframe = &hdata->audio.infoframe;
 793        u8 buf[HDMI_INFOFRAME_SIZE(AUDIO)];
 794        int len;
 795
 796        len = hdmi_audio_infoframe_pack(infoframe, buf, sizeof(buf));
 797        if (len < 0)
 798                return len;
 799
 800        hdmi_reg_writeb(hdata, HDMI_AUI_CON, HDMI_AUI_CON_EVERY_VSYNC);
 801        hdmi_reg_write_buf(hdata, HDMI_AUI_HEADER0, buf, len);
 802
 803        return 0;
 804}
 805
 806static void hdmi_reg_infoframes(struct hdmi_context *hdata)
 807{
 808        struct drm_display_mode *m = &hdata->encoder.crtc->state->mode;
 809        union hdmi_infoframe frm;
 810        u8 buf[25];
 811        int ret;
 812
 813        if (hdata->dvi_mode) {
 814                hdmi_reg_writeb(hdata, HDMI_AVI_CON,
 815                                HDMI_AVI_CON_DO_NOT_TRANSMIT);
 816                hdmi_reg_writeb(hdata, HDMI_VSI_CON,
 817                                HDMI_VSI_CON_DO_NOT_TRANSMIT);
 818                hdmi_reg_writeb(hdata, HDMI_AUI_CON, HDMI_AUI_CON_NO_TRAN);
 819                return;
 820        }
 821
 822        ret = drm_hdmi_avi_infoframe_from_display_mode(&frm.avi,
 823                                                       &hdata->connector, m);
 824        if (!ret)
 825                ret = hdmi_avi_infoframe_pack(&frm.avi, buf, sizeof(buf));
 826        if (ret > 0) {
 827                hdmi_reg_writeb(hdata, HDMI_AVI_CON, HDMI_AVI_CON_EVERY_VSYNC);
 828                hdmi_reg_write_buf(hdata, HDMI_AVI_HEADER0, buf, ret);
 829        } else {
 830                DRM_INFO("%s: invalid AVI infoframe (%d)\n", __func__, ret);
 831        }
 832
 833        ret = drm_hdmi_vendor_infoframe_from_display_mode(&frm.vendor.hdmi,
 834                                                          &hdata->connector, m);
 835        if (!ret)
 836                ret = hdmi_vendor_infoframe_pack(&frm.vendor.hdmi, buf,
 837                                sizeof(buf));
 838        if (ret > 0) {
 839                hdmi_reg_writeb(hdata, HDMI_VSI_CON, HDMI_VSI_CON_EVERY_VSYNC);
 840                hdmi_reg_write_buf(hdata, HDMI_VSI_HEADER0, buf, 3);
 841                hdmi_reg_write_buf(hdata, HDMI_VSI_DATA(0), buf + 3, ret - 3);
 842        }
 843
 844        hdmi_audio_infoframe_apply(hdata);
 845}
 846
 847static enum drm_connector_status hdmi_detect(struct drm_connector *connector,
 848                                bool force)
 849{
 850        struct hdmi_context *hdata = connector_to_hdmi(connector);
 851
 852        if (gpiod_get_value(hdata->hpd_gpio))
 853                return connector_status_connected;
 854
 855        cec_notifier_set_phys_addr(hdata->notifier, CEC_PHYS_ADDR_INVALID);
 856        return connector_status_disconnected;
 857}
 858
 859static void hdmi_connector_destroy(struct drm_connector *connector)
 860{
 861        drm_connector_unregister(connector);
 862        drm_connector_cleanup(connector);
 863}
 864
 865static const struct drm_connector_funcs hdmi_connector_funcs = {
 866        .fill_modes = drm_helper_probe_single_connector_modes,
 867        .detect = hdmi_detect,
 868        .destroy = hdmi_connector_destroy,
 869        .reset = drm_atomic_helper_connector_reset,
 870        .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
 871        .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
 872};
 873
 874static int hdmi_get_modes(struct drm_connector *connector)
 875{
 876        struct hdmi_context *hdata = connector_to_hdmi(connector);
 877        struct edid *edid;
 878        int ret;
 879
 880        if (!hdata->ddc_adpt)
 881                return -ENODEV;
 882
 883        edid = drm_get_edid(connector, hdata->ddc_adpt);
 884        if (!edid)
 885                return -ENODEV;
 886
 887        hdata->dvi_mode = !drm_detect_hdmi_monitor(edid);
 888        DRM_DEBUG_KMS("%s : width[%d] x height[%d]\n",
 889                (hdata->dvi_mode ? "dvi monitor" : "hdmi monitor"),
 890                edid->width_cm, edid->height_cm);
 891
 892        drm_connector_update_edid_property(connector, edid);
 893        cec_notifier_set_phys_addr_from_edid(hdata->notifier, edid);
 894
 895        ret = drm_add_edid_modes(connector, edid);
 896
 897        kfree(edid);
 898
 899        return ret;
 900}
 901
 902static int hdmi_find_phy_conf(struct hdmi_context *hdata, u32 pixel_clock)
 903{
 904        const struct hdmiphy_configs *confs = &hdata->drv_data->phy_confs;
 905        int i;
 906
 907        for (i = 0; i < confs->count; i++)
 908                if (confs->data[i].pixel_clock == pixel_clock)
 909                        return i;
 910
 911        DRM_DEBUG_KMS("Could not find phy config for %d\n", pixel_clock);
 912        return -EINVAL;
 913}
 914
 915static int hdmi_mode_valid(struct drm_connector *connector,
 916                        struct drm_display_mode *mode)
 917{
 918        struct hdmi_context *hdata = connector_to_hdmi(connector);
 919        int ret;
 920
 921        DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%d clock=%d\n",
 922                mode->hdisplay, mode->vdisplay, mode->vrefresh,
 923                (mode->flags & DRM_MODE_FLAG_INTERLACE) ? true :
 924                false, mode->clock * 1000);
 925
 926        ret = hdmi_find_phy_conf(hdata, mode->clock * 1000);
 927        if (ret < 0)
 928                return MODE_BAD;
 929
 930        return MODE_OK;
 931}
 932
 933static const struct drm_connector_helper_funcs hdmi_connector_helper_funcs = {
 934        .get_modes = hdmi_get_modes,
 935        .mode_valid = hdmi_mode_valid,
 936};
 937
 938static int hdmi_create_connector(struct drm_encoder *encoder)
 939{
 940        struct hdmi_context *hdata = encoder_to_hdmi(encoder);
 941        struct drm_connector *connector = &hdata->connector;
 942        int ret;
 943
 944        connector->interlace_allowed = true;
 945        connector->polled = DRM_CONNECTOR_POLL_HPD;
 946
 947        ret = drm_connector_init(hdata->drm_dev, connector,
 948                        &hdmi_connector_funcs, DRM_MODE_CONNECTOR_HDMIA);
 949        if (ret) {
 950                DRM_ERROR("Failed to initialize connector with drm\n");
 951                return ret;
 952        }
 953
 954        drm_connector_helper_add(connector, &hdmi_connector_helper_funcs);
 955        drm_connector_attach_encoder(connector, encoder);
 956
 957        if (hdata->bridge) {
 958                ret = drm_bridge_attach(encoder, hdata->bridge, NULL);
 959                if (ret)
 960                        DRM_ERROR("Failed to attach bridge\n");
 961        }
 962
 963        return ret;
 964}
 965
 966static bool hdmi_mode_fixup(struct drm_encoder *encoder,
 967                            const struct drm_display_mode *mode,
 968                            struct drm_display_mode *adjusted_mode)
 969{
 970        struct drm_device *dev = encoder->dev;
 971        struct drm_connector *connector;
 972        struct drm_display_mode *m;
 973        struct drm_connector_list_iter conn_iter;
 974        int mode_ok;
 975
 976        drm_mode_set_crtcinfo(adjusted_mode, 0);
 977
 978        drm_connector_list_iter_begin(dev, &conn_iter);
 979        drm_for_each_connector_iter(connector, &conn_iter) {
 980                if (connector->encoder == encoder)
 981                        break;
 982        }
 983        if (connector)
 984                drm_connector_get(connector);
 985        drm_connector_list_iter_end(&conn_iter);
 986
 987        if (!connector)
 988                return true;
 989
 990        mode_ok = hdmi_mode_valid(connector, adjusted_mode);
 991
 992        if (mode_ok == MODE_OK)
 993                goto cleanup;
 994
 995        /*
 996         * Find the most suitable mode and copy it to adjusted_mode.
 997         */
 998        list_for_each_entry(m, &connector->modes, head) {
 999                mode_ok = hdmi_mode_valid(connector, m);
1000
1001                if (mode_ok == MODE_OK) {
1002                        DRM_INFO("desired mode doesn't exist so\n");
1003                        DRM_INFO("use the most suitable mode among modes.\n");
1004
1005                        DRM_DEBUG_KMS("Adjusted Mode: [%d]x[%d] [%d]Hz\n",
1006                                m->hdisplay, m->vdisplay, m->vrefresh);
1007
1008                        drm_mode_copy(adjusted_mode, m);
1009                        break;
1010                }
1011        }
1012
1013cleanup:
1014        drm_connector_put(connector);
1015
1016        return true;
1017}
1018
1019static void hdmi_reg_acr(struct hdmi_context *hdata, u32 freq)
1020{
1021        u32 n, cts;
1022
1023        cts = (freq % 9) ? 27000 : 30000;
1024        n = 128 * freq / (27000000 / cts);
1025
1026        hdmi_reg_writev(hdata, HDMI_ACR_N0, 3, n);
1027        hdmi_reg_writev(hdata, HDMI_ACR_MCTS0, 3, cts);
1028        hdmi_reg_writev(hdata, HDMI_ACR_CTS0, 3, cts);
1029        hdmi_reg_writeb(hdata, HDMI_ACR_CON, 4);
1030}
1031
1032static void hdmi_audio_config(struct hdmi_context *hdata)
1033{
1034        u32 bit_ch = 1;
1035        u32 data_num, val;
1036        int i;
1037
1038        switch (hdata->audio.params.sample_width) {
1039        case 20:
1040                data_num = 2;
1041                break;
1042        case 24:
1043                data_num = 3;
1044                break;
1045        default:
1046                data_num = 1;
1047                bit_ch = 0;
1048                break;
1049        }
1050
1051        hdmi_reg_acr(hdata, hdata->audio.params.sample_rate);
1052
1053        hdmi_reg_writeb(hdata, HDMI_I2S_MUX_CON, HDMI_I2S_IN_DISABLE
1054                                | HDMI_I2S_AUD_I2S | HDMI_I2S_CUV_I2S_ENABLE
1055                                | HDMI_I2S_MUX_ENABLE);
1056
1057        hdmi_reg_writeb(hdata, HDMI_I2S_MUX_CH, HDMI_I2S_CH0_EN
1058                        | HDMI_I2S_CH1_EN | HDMI_I2S_CH2_EN);
1059
1060        hdmi_reg_writeb(hdata, HDMI_I2S_MUX_CUV, HDMI_I2S_CUV_RL_EN);
1061        hdmi_reg_writeb(hdata, HDMI_I2S_CLK_CON, HDMI_I2S_CLK_DIS);
1062        hdmi_reg_writeb(hdata, HDMI_I2S_CLK_CON, HDMI_I2S_CLK_EN);
1063
1064        val = hdmi_reg_read(hdata, HDMI_I2S_DSD_CON) | 0x01;
1065        hdmi_reg_writeb(hdata, HDMI_I2S_DSD_CON, val);
1066
1067        /* Configuration I2S input ports. Configure I2S_PIN_SEL_0~4 */
1068        hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_0, HDMI_I2S_SEL_SCLK(5)
1069                        | HDMI_I2S_SEL_LRCK(6));
1070
1071        hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_1, HDMI_I2S_SEL_SDATA1(3)
1072                        | HDMI_I2S_SEL_SDATA0(4));
1073
1074        hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_2, HDMI_I2S_SEL_SDATA3(1)
1075                        | HDMI_I2S_SEL_SDATA2(2));
1076
1077        hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_3, HDMI_I2S_SEL_DSD(0));
1078
1079        /* I2S_CON_1 & 2 */
1080        hdmi_reg_writeb(hdata, HDMI_I2S_CON_1, HDMI_I2S_SCLK_FALLING_EDGE
1081                        | HDMI_I2S_L_CH_LOW_POL);
1082        hdmi_reg_writeb(hdata, HDMI_I2S_CON_2, HDMI_I2S_MSB_FIRST_MODE
1083                        | HDMI_I2S_SET_BIT_CH(bit_ch)
1084                        | HDMI_I2S_SET_SDATA_BIT(data_num)
1085                        | HDMI_I2S_BASIC_FORMAT);
1086
1087        /* Configuration of the audio channel status registers */
1088        for (i = 0; i < HDMI_I2S_CH_ST_MAXNUM; i++)
1089                hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST(i),
1090                                hdata->audio.params.iec.status[i]);
1091
1092        hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_CON, HDMI_I2S_CH_STATUS_RELOAD);
1093}
1094
1095static void hdmi_audio_control(struct hdmi_context *hdata)
1096{
1097        bool enable = !hdata->audio.mute;
1098
1099        if (hdata->dvi_mode)
1100                return;
1101
1102        hdmi_reg_writeb(hdata, HDMI_AUI_CON, enable ?
1103                        HDMI_AVI_CON_EVERY_VSYNC : HDMI_AUI_CON_NO_TRAN);
1104        hdmi_reg_writemask(hdata, HDMI_CON_0, enable ?
1105                        HDMI_ASP_EN : HDMI_ASP_DIS, HDMI_ASP_MASK);
1106}
1107
1108static void hdmi_start(struct hdmi_context *hdata, bool start)
1109{
1110        struct drm_display_mode *m = &hdata->encoder.crtc->state->mode;
1111        u32 val = start ? HDMI_TG_EN : 0;
1112
1113        if (m->flags & DRM_MODE_FLAG_INTERLACE)
1114                val |= HDMI_FIELD_EN;
1115
1116        hdmi_reg_writemask(hdata, HDMI_CON_0, val, HDMI_EN);
1117        hdmi_reg_writemask(hdata, HDMI_TG_CMD, val, HDMI_TG_EN | HDMI_FIELD_EN);
1118}
1119
1120static void hdmi_conf_init(struct hdmi_context *hdata)
1121{
1122        /* disable HPD interrupts from HDMI IP block, use GPIO instead */
1123        hdmi_reg_writemask(hdata, HDMI_INTC_CON, 0, HDMI_INTC_EN_GLOBAL |
1124                HDMI_INTC_EN_HPD_PLUG | HDMI_INTC_EN_HPD_UNPLUG);
1125
1126        /* choose HDMI mode */
1127        hdmi_reg_writemask(hdata, HDMI_MODE_SEL,
1128                HDMI_MODE_HDMI_EN, HDMI_MODE_MASK);
1129        /* apply video pre-amble and guard band in HDMI mode only */
1130        hdmi_reg_writeb(hdata, HDMI_CON_2, 0);
1131        /* disable bluescreen */
1132        hdmi_reg_writemask(hdata, HDMI_CON_0, 0, HDMI_BLUE_SCR_EN);
1133
1134        if (hdata->dvi_mode) {
1135                hdmi_reg_writemask(hdata, HDMI_MODE_SEL,
1136                                HDMI_MODE_DVI_EN, HDMI_MODE_MASK);
1137                hdmi_reg_writeb(hdata, HDMI_CON_2,
1138                                HDMI_VID_PREAMBLE_DIS | HDMI_GUARD_BAND_DIS);
1139        }
1140
1141        if (hdata->drv_data->type == HDMI_TYPE13) {
1142                /* choose bluescreen (fecal) color */
1143                hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_0, 0x12);
1144                hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_1, 0x34);
1145                hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_2, 0x56);
1146
1147                /* enable AVI packet every vsync, fixes purple line problem */
1148                hdmi_reg_writeb(hdata, HDMI_V13_AVI_CON, 0x02);
1149                /* force RGB, look to CEA-861-D, table 7 for more detail */
1150                hdmi_reg_writeb(hdata, HDMI_V13_AVI_BYTE(0), 0 << 5);
1151                hdmi_reg_writemask(hdata, HDMI_CON_1, 0x10 << 5, 0x11 << 5);
1152
1153                hdmi_reg_writeb(hdata, HDMI_V13_SPD_CON, 0x02);
1154                hdmi_reg_writeb(hdata, HDMI_V13_AUI_CON, 0x02);
1155                hdmi_reg_writeb(hdata, HDMI_V13_ACR_CON, 0x04);
1156        } else {
1157                hdmi_reg_infoframes(hdata);
1158
1159                /* enable AVI packet every vsync, fixes purple line problem */
1160                hdmi_reg_writemask(hdata, HDMI_CON_1, 2, 3 << 5);
1161        }
1162}
1163
1164static void hdmiphy_wait_for_pll(struct hdmi_context *hdata)
1165{
1166        int tries;
1167
1168        for (tries = 0; tries < 10; ++tries) {
1169                u32 val = hdmi_reg_read(hdata, HDMI_PHY_STATUS);
1170
1171                if (val & HDMI_PHY_STATUS_READY) {
1172                        DRM_DEBUG_KMS("PLL stabilized after %d tries\n", tries);
1173                        return;
1174                }
1175                usleep_range(10, 20);
1176        }
1177
1178        DRM_ERROR("PLL could not reach steady state\n");
1179}
1180
1181static void hdmi_v13_mode_apply(struct hdmi_context *hdata)
1182{
1183        struct drm_display_mode *m = &hdata->encoder.crtc->state->mode;
1184        unsigned int val;
1185
1186        hdmi_reg_writev(hdata, HDMI_H_BLANK_0, 2, m->htotal - m->hdisplay);
1187        hdmi_reg_writev(hdata, HDMI_V13_H_V_LINE_0, 3,
1188                        (m->htotal << 12) | m->vtotal);
1189
1190        val = (m->flags & DRM_MODE_FLAG_NVSYNC) ? 1 : 0;
1191        hdmi_reg_writev(hdata, HDMI_VSYNC_POL, 1, val);
1192
1193        val = (m->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0;
1194        hdmi_reg_writev(hdata, HDMI_INT_PRO_MODE, 1, val);
1195
1196        val = (m->hsync_start - m->hdisplay - 2);
1197        val |= ((m->hsync_end - m->hdisplay - 2) << 10);
1198        val |= ((m->flags & DRM_MODE_FLAG_NHSYNC) ? 1 : 0)<<20;
1199        hdmi_reg_writev(hdata, HDMI_V13_H_SYNC_GEN_0, 3, val);
1200
1201        /*
1202         * Quirk requirement for exynos HDMI IP design,
1203         * 2 pixels less than the actual calculation for hsync_start
1204         * and end.
1205         */
1206
1207        /* Following values & calculations differ for different type of modes */
1208        if (m->flags & DRM_MODE_FLAG_INTERLACE) {
1209                val = ((m->vsync_end - m->vdisplay) / 2);
1210                val |= ((m->vsync_start - m->vdisplay) / 2) << 12;
1211                hdmi_reg_writev(hdata, HDMI_V13_V_SYNC_GEN_1_0, 3, val);
1212
1213                val = m->vtotal / 2;
1214                val |= ((m->vtotal - m->vdisplay) / 2) << 11;
1215                hdmi_reg_writev(hdata, HDMI_V13_V_BLANK_0, 3, val);
1216
1217                val = (m->vtotal +
1218                        ((m->vsync_end - m->vsync_start) * 4) + 5) / 2;
1219                val |= m->vtotal << 11;
1220                hdmi_reg_writev(hdata, HDMI_V13_V_BLANK_F_0, 3, val);
1221
1222                val = ((m->vtotal / 2) + 7);
1223                val |= ((m->vtotal / 2) + 2) << 12;
1224                hdmi_reg_writev(hdata, HDMI_V13_V_SYNC_GEN_2_0, 3, val);
1225
1226                val = ((m->htotal / 2) + (m->hsync_start - m->hdisplay));
1227                val |= ((m->htotal / 2) +
1228                        (m->hsync_start - m->hdisplay)) << 12;
1229                hdmi_reg_writev(hdata, HDMI_V13_V_SYNC_GEN_3_0, 3, val);
1230
1231                hdmi_reg_writev(hdata, HDMI_TG_VACT_ST_L, 2,
1232                                (m->vtotal - m->vdisplay) / 2);
1233                hdmi_reg_writev(hdata, HDMI_TG_VACT_SZ_L, 2, m->vdisplay / 2);
1234
1235                hdmi_reg_writev(hdata, HDMI_TG_VACT_ST2_L, 2, 0x249);
1236        } else {
1237                val = m->vtotal;
1238                val |= (m->vtotal - m->vdisplay) << 11;
1239                hdmi_reg_writev(hdata, HDMI_V13_V_BLANK_0, 3, val);
1240
1241                hdmi_reg_writev(hdata, HDMI_V13_V_BLANK_F_0, 3, 0);
1242
1243                val = (m->vsync_end - m->vdisplay);
1244                val |= ((m->vsync_start - m->vdisplay) << 12);
1245                hdmi_reg_writev(hdata, HDMI_V13_V_SYNC_GEN_1_0, 3, val);
1246
1247                hdmi_reg_writev(hdata, HDMI_V13_V_SYNC_GEN_2_0, 3, 0x1001);
1248                hdmi_reg_writev(hdata, HDMI_V13_V_SYNC_GEN_3_0, 3, 0x1001);
1249                hdmi_reg_writev(hdata, HDMI_TG_VACT_ST_L, 2,
1250                                m->vtotal - m->vdisplay);
1251                hdmi_reg_writev(hdata, HDMI_TG_VACT_SZ_L, 2, m->vdisplay);
1252        }
1253
1254        hdmi_reg_writev(hdata, HDMI_TG_H_FSZ_L, 2, m->htotal);
1255        hdmi_reg_writev(hdata, HDMI_TG_HACT_ST_L, 2, m->htotal - m->hdisplay);
1256        hdmi_reg_writev(hdata, HDMI_TG_HACT_SZ_L, 2, m->hdisplay);
1257        hdmi_reg_writev(hdata, HDMI_TG_V_FSZ_L, 2, m->vtotal);
1258}
1259
1260static void hdmi_v14_mode_apply(struct hdmi_context *hdata)
1261{
1262        struct drm_display_mode *m = &hdata->encoder.crtc->state->mode;
1263        struct drm_display_mode *am =
1264                                &hdata->encoder.crtc->state->adjusted_mode;
1265        int hquirk = 0;
1266
1267        /*
1268         * In case video mode coming from CRTC differs from requested one HDMI
1269         * sometimes is able to almost properly perform conversion - only
1270         * first line is distorted.
1271         */
1272        if ((m->vdisplay != am->vdisplay) &&
1273            (m->hdisplay == 1280 || m->hdisplay == 1024 || m->hdisplay == 1366))
1274                hquirk = 258;
1275
1276        hdmi_reg_writev(hdata, HDMI_H_BLANK_0, 2, m->htotal - m->hdisplay);
1277        hdmi_reg_writev(hdata, HDMI_V_LINE_0, 2, m->vtotal);
1278        hdmi_reg_writev(hdata, HDMI_H_LINE_0, 2, m->htotal);
1279        hdmi_reg_writev(hdata, HDMI_HSYNC_POL, 1,
1280                        (m->flags & DRM_MODE_FLAG_NHSYNC) ? 1 : 0);
1281        hdmi_reg_writev(hdata, HDMI_VSYNC_POL, 1,
1282                        (m->flags & DRM_MODE_FLAG_NVSYNC) ? 1 : 0);
1283        hdmi_reg_writev(hdata, HDMI_INT_PRO_MODE, 1,
1284                        (m->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0);
1285
1286        /*
1287         * Quirk requirement for exynos 5 HDMI IP design,
1288         * 2 pixels less than the actual calculation for hsync_start
1289         * and end.
1290         */
1291
1292        /* Following values & calculations differ for different type of modes */
1293        if (m->flags & DRM_MODE_FLAG_INTERLACE) {
1294                hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_BEF_2_0, 2,
1295                        (m->vsync_end - m->vdisplay) / 2);
1296                hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_BEF_1_0, 2,
1297                        (m->vsync_start - m->vdisplay) / 2);
1298                hdmi_reg_writev(hdata, HDMI_V2_BLANK_0, 2, m->vtotal / 2);
1299                hdmi_reg_writev(hdata, HDMI_V1_BLANK_0, 2,
1300                                (m->vtotal - m->vdisplay) / 2);
1301                hdmi_reg_writev(hdata, HDMI_V_BLANK_F0_0, 2,
1302                                m->vtotal - m->vdisplay / 2);
1303                hdmi_reg_writev(hdata, HDMI_V_BLANK_F1_0, 2, m->vtotal);
1304                hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_2_0, 2,
1305                                (m->vtotal / 2) + 7);
1306                hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_1_0, 2,
1307                                (m->vtotal / 2) + 2);
1308                hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_PXL_2_0, 2,
1309                        (m->htotal / 2) + (m->hsync_start - m->hdisplay));
1310                hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_PXL_1_0, 2,
1311                        (m->htotal / 2) + (m->hsync_start - m->hdisplay));
1312                hdmi_reg_writev(hdata, HDMI_TG_VACT_ST_L, 2,
1313                                (m->vtotal - m->vdisplay) / 2);
1314                hdmi_reg_writev(hdata, HDMI_TG_VACT_SZ_L, 2, m->vdisplay / 2);
1315                hdmi_reg_writev(hdata, HDMI_TG_VACT_ST2_L, 2,
1316                                m->vtotal - m->vdisplay / 2);
1317                hdmi_reg_writev(hdata, HDMI_TG_VSYNC2_L, 2,
1318                                (m->vtotal / 2) + 1);
1319                hdmi_reg_writev(hdata, HDMI_TG_VSYNC_BOT_HDMI_L, 2,
1320                                (m->vtotal / 2) + 1);
1321                hdmi_reg_writev(hdata, HDMI_TG_FIELD_BOT_HDMI_L, 2,
1322                                (m->vtotal / 2) + 1);
1323                hdmi_reg_writev(hdata, HDMI_TG_VACT_ST3_L, 2, 0x0);
1324                hdmi_reg_writev(hdata, HDMI_TG_VACT_ST4_L, 2, 0x0);
1325        } else {
1326                hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_BEF_2_0, 2,
1327                        m->vsync_end - m->vdisplay);
1328                hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_BEF_1_0, 2,
1329                        m->vsync_start - m->vdisplay);
1330                hdmi_reg_writev(hdata, HDMI_V2_BLANK_0, 2, m->vtotal);
1331                hdmi_reg_writev(hdata, HDMI_V1_BLANK_0, 2,
1332                                m->vtotal - m->vdisplay);
1333                hdmi_reg_writev(hdata, HDMI_V_BLANK_F0_0, 2, 0xffff);
1334                hdmi_reg_writev(hdata, HDMI_V_BLANK_F1_0, 2, 0xffff);
1335                hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_2_0, 2, 0xffff);
1336                hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_1_0, 2, 0xffff);
1337                hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_PXL_2_0, 2, 0xffff);
1338                hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_PXL_1_0, 2, 0xffff);
1339                hdmi_reg_writev(hdata, HDMI_TG_VACT_ST_L, 2,
1340                                m->vtotal - m->vdisplay);
1341                hdmi_reg_writev(hdata, HDMI_TG_VACT_SZ_L, 2, m->vdisplay);
1342        }
1343
1344        hdmi_reg_writev(hdata, HDMI_H_SYNC_START_0, 2,
1345                        m->hsync_start - m->hdisplay - 2);
1346        hdmi_reg_writev(hdata, HDMI_H_SYNC_END_0, 2,
1347                        m->hsync_end - m->hdisplay - 2);
1348        hdmi_reg_writev(hdata, HDMI_VACT_SPACE_1_0, 2, 0xffff);
1349        hdmi_reg_writev(hdata, HDMI_VACT_SPACE_2_0, 2, 0xffff);
1350        hdmi_reg_writev(hdata, HDMI_VACT_SPACE_3_0, 2, 0xffff);
1351        hdmi_reg_writev(hdata, HDMI_VACT_SPACE_4_0, 2, 0xffff);
1352        hdmi_reg_writev(hdata, HDMI_VACT_SPACE_5_0, 2, 0xffff);
1353        hdmi_reg_writev(hdata, HDMI_VACT_SPACE_6_0, 2, 0xffff);
1354        hdmi_reg_writev(hdata, HDMI_V_BLANK_F2_0, 2, 0xffff);
1355        hdmi_reg_writev(hdata, HDMI_V_BLANK_F3_0, 2, 0xffff);
1356        hdmi_reg_writev(hdata, HDMI_V_BLANK_F4_0, 2, 0xffff);
1357        hdmi_reg_writev(hdata, HDMI_V_BLANK_F5_0, 2, 0xffff);
1358        hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_3_0, 2, 0xffff);
1359        hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_4_0, 2, 0xffff);
1360        hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_5_0, 2, 0xffff);
1361        hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_6_0, 2, 0xffff);
1362        hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_PXL_3_0, 2, 0xffff);
1363        hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_PXL_4_0, 2, 0xffff);
1364        hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_PXL_5_0, 2, 0xffff);
1365        hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_PXL_6_0, 2, 0xffff);
1366
1367        hdmi_reg_writev(hdata, HDMI_TG_H_FSZ_L, 2, m->htotal);
1368        hdmi_reg_writev(hdata, HDMI_TG_HACT_ST_L, 2,
1369                                        m->htotal - m->hdisplay - hquirk);
1370        hdmi_reg_writev(hdata, HDMI_TG_HACT_SZ_L, 2, m->hdisplay + hquirk);
1371        hdmi_reg_writev(hdata, HDMI_TG_V_FSZ_L, 2, m->vtotal);
1372        if (hdata->drv_data == &exynos5433_hdmi_driver_data)
1373                hdmi_reg_writeb(hdata, HDMI_TG_DECON_EN, 1);
1374}
1375
1376static void hdmi_mode_apply(struct hdmi_context *hdata)
1377{
1378        if (hdata->drv_data->type == HDMI_TYPE13)
1379                hdmi_v13_mode_apply(hdata);
1380        else
1381                hdmi_v14_mode_apply(hdata);
1382
1383        hdmi_start(hdata, true);
1384}
1385
1386static void hdmiphy_conf_reset(struct hdmi_context *hdata)
1387{
1388        hdmi_reg_writemask(hdata, HDMI_CORE_RSTOUT, 0, 1);
1389        usleep_range(10000, 12000);
1390        hdmi_reg_writemask(hdata, HDMI_CORE_RSTOUT, ~0, 1);
1391        usleep_range(10000, 12000);
1392        hdmi_reg_writemask(hdata, HDMI_PHY_RSTOUT, ~0, HDMI_PHY_SW_RSTOUT);
1393        usleep_range(10000, 12000);
1394        hdmi_reg_writemask(hdata, HDMI_PHY_RSTOUT, 0, HDMI_PHY_SW_RSTOUT);
1395        usleep_range(10000, 12000);
1396}
1397
1398static void hdmiphy_enable_mode_set(struct hdmi_context *hdata, bool enable)
1399{
1400        u8 v = enable ? HDMI_PHY_ENABLE_MODE_SET : HDMI_PHY_DISABLE_MODE_SET;
1401
1402        if (hdata->drv_data == &exynos5433_hdmi_driver_data)
1403                writel(v, hdata->regs_hdmiphy + HDMIPHY5433_MODE_SET_DONE);
1404}
1405
1406static void hdmiphy_conf_apply(struct hdmi_context *hdata)
1407{
1408        struct drm_display_mode *m = &hdata->encoder.crtc->state->mode;
1409        int ret;
1410        const u8 *phy_conf;
1411
1412        ret = hdmi_find_phy_conf(hdata, m->clock * 1000);
1413        if (ret < 0) {
1414                DRM_ERROR("failed to find hdmiphy conf\n");
1415                return;
1416        }
1417        phy_conf = hdata->drv_data->phy_confs.data[ret].conf;
1418
1419        hdmi_clk_set_parents(hdata, false);
1420
1421        hdmiphy_conf_reset(hdata);
1422
1423        hdmiphy_enable_mode_set(hdata, true);
1424        ret = hdmiphy_reg_write_buf(hdata, 0, phy_conf, 32);
1425        if (ret) {
1426                DRM_ERROR("failed to configure hdmiphy\n");
1427                return;
1428        }
1429        hdmiphy_enable_mode_set(hdata, false);
1430        hdmi_clk_set_parents(hdata, true);
1431        usleep_range(10000, 12000);
1432        hdmiphy_wait_for_pll(hdata);
1433}
1434
1435/* Should be called with hdata->mutex mutex held */
1436static void hdmi_conf_apply(struct hdmi_context *hdata)
1437{
1438        hdmi_start(hdata, false);
1439        hdmi_conf_init(hdata);
1440        hdmi_audio_config(hdata);
1441        hdmi_mode_apply(hdata);
1442        hdmi_audio_control(hdata);
1443}
1444
1445static void hdmi_set_refclk(struct hdmi_context *hdata, bool on)
1446{
1447        if (!hdata->sysreg)
1448                return;
1449
1450        regmap_update_bits(hdata->sysreg, EXYNOS5433_SYSREG_DISP_HDMI_PHY,
1451                           SYSREG_HDMI_REFCLK_INT_CLK, on ? ~0 : 0);
1452}
1453
1454/* Should be called with hdata->mutex mutex held. */
1455static void hdmiphy_enable(struct hdmi_context *hdata)
1456{
1457        if (hdata->powered)
1458                return;
1459
1460        pm_runtime_get_sync(hdata->dev);
1461
1462        if (regulator_bulk_enable(ARRAY_SIZE(supply), hdata->regul_bulk))
1463                DRM_DEBUG_KMS("failed to enable regulator bulk\n");
1464
1465        regmap_update_bits(hdata->pmureg, PMU_HDMI_PHY_CONTROL,
1466                        PMU_HDMI_PHY_ENABLE_BIT, 1);
1467
1468        hdmi_set_refclk(hdata, true);
1469
1470        hdmi_reg_writemask(hdata, HDMI_PHY_CON_0, 0, HDMI_PHY_POWER_OFF_EN);
1471
1472        hdmiphy_conf_apply(hdata);
1473
1474        hdata->powered = true;
1475}
1476
1477/* Should be called with hdata->mutex mutex held. */
1478static void hdmiphy_disable(struct hdmi_context *hdata)
1479{
1480        if (!hdata->powered)
1481                return;
1482
1483        hdmi_reg_writemask(hdata, HDMI_CON_0, 0, HDMI_EN);
1484
1485        hdmi_reg_writemask(hdata, HDMI_PHY_CON_0, ~0, HDMI_PHY_POWER_OFF_EN);
1486
1487        hdmi_set_refclk(hdata, false);
1488
1489        regmap_update_bits(hdata->pmureg, PMU_HDMI_PHY_CONTROL,
1490                        PMU_HDMI_PHY_ENABLE_BIT, 0);
1491
1492        regulator_bulk_disable(ARRAY_SIZE(supply), hdata->regul_bulk);
1493
1494        pm_runtime_put_sync(hdata->dev);
1495
1496        hdata->powered = false;
1497}
1498
1499static void hdmi_enable(struct drm_encoder *encoder)
1500{
1501        struct hdmi_context *hdata = encoder_to_hdmi(encoder);
1502
1503        mutex_lock(&hdata->mutex);
1504
1505        hdmiphy_enable(hdata);
1506        hdmi_conf_apply(hdata);
1507
1508        mutex_unlock(&hdata->mutex);
1509}
1510
1511static void hdmi_disable(struct drm_encoder *encoder)
1512{
1513        struct hdmi_context *hdata = encoder_to_hdmi(encoder);
1514
1515        mutex_lock(&hdata->mutex);
1516
1517        if (hdata->powered) {
1518                /*
1519                 * The SFRs of VP and Mixer are updated by Vertical Sync of
1520                 * Timing generator which is a part of HDMI so the sequence
1521                 * to disable TV Subsystem should be as following,
1522                 *      VP -> Mixer -> HDMI
1523                 *
1524                 * To achieve such sequence HDMI is disabled together with
1525                 * HDMI PHY, via pipe clock callback.
1526                 */
1527                mutex_unlock(&hdata->mutex);
1528                cancel_delayed_work(&hdata->hotplug_work);
1529                cec_notifier_set_phys_addr(hdata->notifier,
1530                                           CEC_PHYS_ADDR_INVALID);
1531                return;
1532        }
1533
1534        mutex_unlock(&hdata->mutex);
1535}
1536
1537static const struct drm_encoder_helper_funcs exynos_hdmi_encoder_helper_funcs = {
1538        .mode_fixup     = hdmi_mode_fixup,
1539        .enable         = hdmi_enable,
1540        .disable        = hdmi_disable,
1541};
1542
1543static const struct drm_encoder_funcs exynos_hdmi_encoder_funcs = {
1544        .destroy = drm_encoder_cleanup,
1545};
1546
1547static void hdmi_audio_shutdown(struct device *dev, void *data)
1548{
1549        struct hdmi_context *hdata = dev_get_drvdata(dev);
1550
1551        mutex_lock(&hdata->mutex);
1552
1553        hdata->audio.mute = true;
1554
1555        if (hdata->powered)
1556                hdmi_audio_control(hdata);
1557
1558        mutex_unlock(&hdata->mutex);
1559}
1560
1561static int hdmi_audio_hw_params(struct device *dev, void *data,
1562                                struct hdmi_codec_daifmt *daifmt,
1563                                struct hdmi_codec_params *params)
1564{
1565        struct hdmi_context *hdata = dev_get_drvdata(dev);
1566
1567        if (daifmt->fmt != HDMI_I2S || daifmt->bit_clk_inv ||
1568            daifmt->frame_clk_inv || daifmt->bit_clk_master ||
1569            daifmt->frame_clk_master) {
1570                dev_err(dev, "%s: Bad flags %d %d %d %d\n", __func__,
1571                        daifmt->bit_clk_inv, daifmt->frame_clk_inv,
1572                        daifmt->bit_clk_master,
1573                        daifmt->frame_clk_master);
1574                return -EINVAL;
1575        }
1576
1577        mutex_lock(&hdata->mutex);
1578
1579        hdata->audio.params = *params;
1580
1581        if (hdata->powered) {
1582                hdmi_audio_config(hdata);
1583                hdmi_audio_infoframe_apply(hdata);
1584        }
1585
1586        mutex_unlock(&hdata->mutex);
1587
1588        return 0;
1589}
1590
1591static int hdmi_audio_digital_mute(struct device *dev, void *data, bool mute)
1592{
1593        struct hdmi_context *hdata = dev_get_drvdata(dev);
1594
1595        mutex_lock(&hdata->mutex);
1596
1597        hdata->audio.mute = mute;
1598
1599        if (hdata->powered)
1600                hdmi_audio_control(hdata);
1601
1602        mutex_unlock(&hdata->mutex);
1603
1604        return 0;
1605}
1606
1607static int hdmi_audio_get_eld(struct device *dev, void *data, uint8_t *buf,
1608                              size_t len)
1609{
1610        struct hdmi_context *hdata = dev_get_drvdata(dev);
1611        struct drm_connector *connector = &hdata->connector;
1612
1613        memcpy(buf, connector->eld, min(sizeof(connector->eld), len));
1614
1615        return 0;
1616}
1617
1618static const struct hdmi_codec_ops audio_codec_ops = {
1619        .hw_params = hdmi_audio_hw_params,
1620        .audio_shutdown = hdmi_audio_shutdown,
1621        .digital_mute = hdmi_audio_digital_mute,
1622        .get_eld = hdmi_audio_get_eld,
1623};
1624
1625static int hdmi_register_audio_device(struct hdmi_context *hdata)
1626{
1627        struct hdmi_codec_pdata codec_data = {
1628                .ops = &audio_codec_ops,
1629                .max_i2s_channels = 6,
1630                .i2s = 1,
1631        };
1632
1633        hdata->audio.pdev = platform_device_register_data(
1634                hdata->dev, HDMI_CODEC_DRV_NAME, PLATFORM_DEVID_AUTO,
1635                &codec_data, sizeof(codec_data));
1636
1637        return PTR_ERR_OR_ZERO(hdata->audio.pdev);
1638}
1639
1640static void hdmi_hotplug_work_func(struct work_struct *work)
1641{
1642        struct hdmi_context *hdata;
1643
1644        hdata = container_of(work, struct hdmi_context, hotplug_work.work);
1645
1646        if (hdata->drm_dev)
1647                drm_helper_hpd_irq_event(hdata->drm_dev);
1648}
1649
1650static irqreturn_t hdmi_irq_thread(int irq, void *arg)
1651{
1652        struct hdmi_context *hdata = arg;
1653
1654        mod_delayed_work(system_wq, &hdata->hotplug_work,
1655                        msecs_to_jiffies(HOTPLUG_DEBOUNCE_MS));
1656
1657        return IRQ_HANDLED;
1658}
1659
1660static int hdmi_clks_get(struct hdmi_context *hdata,
1661                         const struct string_array_spec *names,
1662                         struct clk **clks)
1663{
1664        struct device *dev = hdata->dev;
1665        int i;
1666
1667        for (i = 0; i < names->count; ++i) {
1668                struct clk *clk = devm_clk_get(dev, names->data[i]);
1669
1670                if (IS_ERR(clk)) {
1671                        int ret = PTR_ERR(clk);
1672
1673                        dev_err(dev, "Cannot get clock %s, %d\n",
1674                                names->data[i], ret);
1675
1676                        return ret;
1677                }
1678
1679                clks[i] = clk;
1680        }
1681
1682        return 0;
1683}
1684
1685static int hdmi_clk_init(struct hdmi_context *hdata)
1686{
1687        const struct hdmi_driver_data *drv_data = hdata->drv_data;
1688        int count = drv_data->clk_gates.count + drv_data->clk_muxes.count;
1689        struct device *dev = hdata->dev;
1690        struct clk **clks;
1691        int ret;
1692
1693        if (!count)
1694                return 0;
1695
1696        clks = devm_kcalloc(dev, count, sizeof(*clks), GFP_KERNEL);
1697        if (!clks)
1698                return -ENOMEM;
1699
1700        hdata->clk_gates = clks;
1701        hdata->clk_muxes = clks + drv_data->clk_gates.count;
1702
1703        ret = hdmi_clks_get(hdata, &drv_data->clk_gates, hdata->clk_gates);
1704        if (ret)
1705                return ret;
1706
1707        return hdmi_clks_get(hdata, &drv_data->clk_muxes, hdata->clk_muxes);
1708}
1709
1710
1711static void hdmiphy_clk_enable(struct exynos_drm_clk *clk, bool enable)
1712{
1713        struct hdmi_context *hdata = container_of(clk, struct hdmi_context,
1714                                                  phy_clk);
1715        mutex_lock(&hdata->mutex);
1716
1717        if (enable)
1718                hdmiphy_enable(hdata);
1719        else
1720                hdmiphy_disable(hdata);
1721
1722        mutex_unlock(&hdata->mutex);
1723}
1724
1725static int hdmi_bridge_init(struct hdmi_context *hdata)
1726{
1727        struct device *dev = hdata->dev;
1728        struct device_node *ep, *np;
1729
1730        ep = of_graph_get_endpoint_by_regs(dev->of_node, 1, -1);
1731        if (!ep)
1732                return 0;
1733
1734        np = of_graph_get_remote_port_parent(ep);
1735        of_node_put(ep);
1736        if (!np) {
1737                DRM_ERROR("failed to get remote port parent");
1738                return -EINVAL;
1739        }
1740
1741        hdata->bridge = of_drm_find_bridge(np);
1742        of_node_put(np);
1743
1744        if (!hdata->bridge)
1745                return -EPROBE_DEFER;
1746
1747        return 0;
1748}
1749
1750static int hdmi_resources_init(struct hdmi_context *hdata)
1751{
1752        struct device *dev = hdata->dev;
1753        int i, ret;
1754
1755        DRM_DEBUG_KMS("HDMI resource init\n");
1756
1757        hdata->hpd_gpio = devm_gpiod_get(dev, "hpd", GPIOD_IN);
1758        if (IS_ERR(hdata->hpd_gpio)) {
1759                DRM_ERROR("cannot get hpd gpio property\n");
1760                return PTR_ERR(hdata->hpd_gpio);
1761        }
1762
1763        hdata->irq = gpiod_to_irq(hdata->hpd_gpio);
1764        if (hdata->irq < 0) {
1765                DRM_ERROR("failed to get GPIO irq\n");
1766                return  hdata->irq;
1767        }
1768
1769        ret = hdmi_clk_init(hdata);
1770        if (ret)
1771                return ret;
1772
1773        ret = hdmi_clk_set_parents(hdata, false);
1774        if (ret)
1775                return ret;
1776
1777        for (i = 0; i < ARRAY_SIZE(supply); ++i)
1778                hdata->regul_bulk[i].supply = supply[i];
1779
1780        ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(supply), hdata->regul_bulk);
1781        if (ret) {
1782                if (ret != -EPROBE_DEFER)
1783                        DRM_ERROR("failed to get regulators\n");
1784                return ret;
1785        }
1786
1787        hdata->reg_hdmi_en = devm_regulator_get_optional(dev, "hdmi-en");
1788
1789        if (PTR_ERR(hdata->reg_hdmi_en) != -ENODEV) {
1790                if (IS_ERR(hdata->reg_hdmi_en))
1791                        return PTR_ERR(hdata->reg_hdmi_en);
1792
1793                ret = regulator_enable(hdata->reg_hdmi_en);
1794                if (ret) {
1795                        DRM_ERROR("failed to enable hdmi-en regulator\n");
1796                        return ret;
1797                }
1798        }
1799
1800        return hdmi_bridge_init(hdata);
1801}
1802
1803static const struct of_device_id hdmi_match_types[] = {
1804        {
1805                .compatible = "samsung,exynos4210-hdmi",
1806                .data = &exynos4210_hdmi_driver_data,
1807        }, {
1808                .compatible = "samsung,exynos4212-hdmi",
1809                .data = &exynos4212_hdmi_driver_data,
1810        }, {
1811                .compatible = "samsung,exynos5420-hdmi",
1812                .data = &exynos5420_hdmi_driver_data,
1813        }, {
1814                .compatible = "samsung,exynos5433-hdmi",
1815                .data = &exynos5433_hdmi_driver_data,
1816        }, {
1817                /* end node */
1818        }
1819};
1820MODULE_DEVICE_TABLE (of, hdmi_match_types);
1821
1822static int hdmi_bind(struct device *dev, struct device *master, void *data)
1823{
1824        struct drm_device *drm_dev = data;
1825        struct hdmi_context *hdata = dev_get_drvdata(dev);
1826        struct drm_encoder *encoder = &hdata->encoder;
1827        struct exynos_drm_crtc *crtc;
1828        int ret;
1829
1830        hdata->drm_dev = drm_dev;
1831
1832        hdata->phy_clk.enable = hdmiphy_clk_enable;
1833
1834        drm_encoder_init(drm_dev, encoder, &exynos_hdmi_encoder_funcs,
1835                         DRM_MODE_ENCODER_TMDS, NULL);
1836
1837        drm_encoder_helper_add(encoder, &exynos_hdmi_encoder_helper_funcs);
1838
1839        ret = exynos_drm_set_possible_crtcs(encoder, EXYNOS_DISPLAY_TYPE_HDMI);
1840        if (ret < 0)
1841                return ret;
1842
1843        crtc = exynos_drm_crtc_get_by_type(drm_dev, EXYNOS_DISPLAY_TYPE_HDMI);
1844        crtc->pipe_clk = &hdata->phy_clk;
1845
1846        ret = hdmi_create_connector(encoder);
1847        if (ret) {
1848                DRM_ERROR("failed to create connector ret = %d\n", ret);
1849                drm_encoder_cleanup(encoder);
1850                return ret;
1851        }
1852
1853        return 0;
1854}
1855
1856static void hdmi_unbind(struct device *dev, struct device *master, void *data)
1857{
1858}
1859
1860static const struct component_ops hdmi_component_ops = {
1861        .bind   = hdmi_bind,
1862        .unbind = hdmi_unbind,
1863};
1864
1865static int hdmi_get_ddc_adapter(struct hdmi_context *hdata)
1866{
1867        const char *compatible_str = "samsung,exynos4210-hdmiddc";
1868        struct device_node *np;
1869        struct i2c_adapter *adpt;
1870
1871        np = of_find_compatible_node(NULL, NULL, compatible_str);
1872        if (np)
1873                np = of_get_next_parent(np);
1874        else
1875                np = of_parse_phandle(hdata->dev->of_node, "ddc", 0);
1876
1877        if (!np) {
1878                DRM_ERROR("Failed to find ddc node in device tree\n");
1879                return -ENODEV;
1880        }
1881
1882        adpt = of_find_i2c_adapter_by_node(np);
1883        of_node_put(np);
1884
1885        if (!adpt) {
1886                DRM_INFO("Failed to get ddc i2c adapter by node\n");
1887                return -EPROBE_DEFER;
1888        }
1889
1890        hdata->ddc_adpt = adpt;
1891
1892        return 0;
1893}
1894
1895static int hdmi_get_phy_io(struct hdmi_context *hdata)
1896{
1897        const char *compatible_str = "samsung,exynos4212-hdmiphy";
1898        struct device_node *np;
1899        int ret = 0;
1900
1901        np = of_find_compatible_node(NULL, NULL, compatible_str);
1902        if (!np) {
1903                np = of_parse_phandle(hdata->dev->of_node, "phy", 0);
1904                if (!np) {
1905                        DRM_ERROR("Failed to find hdmiphy node in device tree\n");
1906                        return -ENODEV;
1907                }
1908        }
1909
1910        if (hdata->drv_data->is_apb_phy) {
1911                hdata->regs_hdmiphy = of_iomap(np, 0);
1912                if (!hdata->regs_hdmiphy) {
1913                        DRM_ERROR("failed to ioremap hdmi phy\n");
1914                        ret = -ENOMEM;
1915                        goto out;
1916                }
1917        } else {
1918                hdata->hdmiphy_port = of_find_i2c_device_by_node(np);
1919                if (!hdata->hdmiphy_port) {
1920                        DRM_INFO("Failed to get hdmi phy i2c client\n");
1921                        ret = -EPROBE_DEFER;
1922                        goto out;
1923                }
1924        }
1925
1926out:
1927        of_node_put(np);
1928        return ret;
1929}
1930
1931static int hdmi_probe(struct platform_device *pdev)
1932{
1933        struct hdmi_audio_infoframe *audio_infoframe;
1934        struct device *dev = &pdev->dev;
1935        struct hdmi_context *hdata;
1936        struct resource *res;
1937        int ret;
1938
1939        hdata = devm_kzalloc(dev, sizeof(struct hdmi_context), GFP_KERNEL);
1940        if (!hdata)
1941                return -ENOMEM;
1942
1943        hdata->drv_data = of_device_get_match_data(dev);
1944
1945        platform_set_drvdata(pdev, hdata);
1946
1947        hdata->dev = dev;
1948
1949        mutex_init(&hdata->mutex);
1950
1951        ret = hdmi_resources_init(hdata);
1952        if (ret) {
1953                if (ret != -EPROBE_DEFER)
1954                        DRM_ERROR("hdmi_resources_init failed\n");
1955                return ret;
1956        }
1957
1958        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1959        hdata->regs = devm_ioremap_resource(dev, res);
1960        if (IS_ERR(hdata->regs)) {
1961                ret = PTR_ERR(hdata->regs);
1962                return ret;
1963        }
1964
1965        ret = hdmi_get_ddc_adapter(hdata);
1966        if (ret)
1967                return ret;
1968
1969        ret = hdmi_get_phy_io(hdata);
1970        if (ret)
1971                goto err_ddc;
1972
1973        INIT_DELAYED_WORK(&hdata->hotplug_work, hdmi_hotplug_work_func);
1974
1975        ret = devm_request_threaded_irq(dev, hdata->irq, NULL,
1976                        hdmi_irq_thread, IRQF_TRIGGER_RISING |
1977                        IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
1978                        "hdmi", hdata);
1979        if (ret) {
1980                DRM_ERROR("failed to register hdmi interrupt\n");
1981                goto err_hdmiphy;
1982        }
1983
1984        hdata->pmureg = syscon_regmap_lookup_by_phandle(dev->of_node,
1985                        "samsung,syscon-phandle");
1986        if (IS_ERR(hdata->pmureg)) {
1987                DRM_ERROR("syscon regmap lookup failed.\n");
1988                ret = -EPROBE_DEFER;
1989                goto err_hdmiphy;
1990        }
1991
1992        if (hdata->drv_data->has_sysreg) {
1993                hdata->sysreg = syscon_regmap_lookup_by_phandle(dev->of_node,
1994                                "samsung,sysreg-phandle");
1995                if (IS_ERR(hdata->sysreg)) {
1996                        DRM_ERROR("sysreg regmap lookup failed.\n");
1997                        ret = -EPROBE_DEFER;
1998                        goto err_hdmiphy;
1999                }
2000        }
2001
2002        hdata->notifier = cec_notifier_get(&pdev->dev);
2003        if (hdata->notifier == NULL) {
2004                ret = -ENOMEM;
2005                goto err_hdmiphy;
2006        }
2007
2008        pm_runtime_enable(dev);
2009
2010        audio_infoframe = &hdata->audio.infoframe;
2011        hdmi_audio_infoframe_init(audio_infoframe);
2012        audio_infoframe->coding_type = HDMI_AUDIO_CODING_TYPE_STREAM;
2013        audio_infoframe->sample_size = HDMI_AUDIO_SAMPLE_SIZE_STREAM;
2014        audio_infoframe->sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_STREAM;
2015        audio_infoframe->channels = 2;
2016
2017        ret = hdmi_register_audio_device(hdata);
2018        if (ret)
2019                goto err_notifier_put;
2020
2021        ret = component_add(&pdev->dev, &hdmi_component_ops);
2022        if (ret)
2023                goto err_unregister_audio;
2024
2025        return ret;
2026
2027err_unregister_audio:
2028        platform_device_unregister(hdata->audio.pdev);
2029
2030err_notifier_put:
2031        cec_notifier_put(hdata->notifier);
2032        pm_runtime_disable(dev);
2033
2034err_hdmiphy:
2035        if (hdata->hdmiphy_port)
2036                put_device(&hdata->hdmiphy_port->dev);
2037        if (hdata->regs_hdmiphy)
2038                iounmap(hdata->regs_hdmiphy);
2039err_ddc:
2040        put_device(&hdata->ddc_adpt->dev);
2041
2042        return ret;
2043}
2044
2045static int hdmi_remove(struct platform_device *pdev)
2046{
2047        struct hdmi_context *hdata = platform_get_drvdata(pdev);
2048
2049        cancel_delayed_work_sync(&hdata->hotplug_work);
2050        cec_notifier_set_phys_addr(hdata->notifier, CEC_PHYS_ADDR_INVALID);
2051
2052        component_del(&pdev->dev, &hdmi_component_ops);
2053        platform_device_unregister(hdata->audio.pdev);
2054
2055        cec_notifier_put(hdata->notifier);
2056        pm_runtime_disable(&pdev->dev);
2057
2058        if (!IS_ERR(hdata->reg_hdmi_en))
2059                regulator_disable(hdata->reg_hdmi_en);
2060
2061        if (hdata->hdmiphy_port)
2062                put_device(&hdata->hdmiphy_port->dev);
2063
2064        if (hdata->regs_hdmiphy)
2065                iounmap(hdata->regs_hdmiphy);
2066
2067        put_device(&hdata->ddc_adpt->dev);
2068
2069        mutex_destroy(&hdata->mutex);
2070
2071        return 0;
2072}
2073
2074static int __maybe_unused exynos_hdmi_suspend(struct device *dev)
2075{
2076        struct hdmi_context *hdata = dev_get_drvdata(dev);
2077
2078        hdmi_clk_disable_gates(hdata);
2079
2080        return 0;
2081}
2082
2083static int __maybe_unused exynos_hdmi_resume(struct device *dev)
2084{
2085        struct hdmi_context *hdata = dev_get_drvdata(dev);
2086        int ret;
2087
2088        ret = hdmi_clk_enable_gates(hdata);
2089        if (ret < 0)
2090                return ret;
2091
2092        return 0;
2093}
2094
2095static const struct dev_pm_ops exynos_hdmi_pm_ops = {
2096        SET_RUNTIME_PM_OPS(exynos_hdmi_suspend, exynos_hdmi_resume, NULL)
2097        SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
2098                                pm_runtime_force_resume)
2099};
2100
2101struct platform_driver hdmi_driver = {
2102        .probe          = hdmi_probe,
2103        .remove         = hdmi_remove,
2104        .driver         = {
2105                .name   = "exynos-hdmi",
2106                .owner  = THIS_MODULE,
2107                .pm     = &exynos_hdmi_pm_ops,
2108                .of_match_table = hdmi_match_types,
2109        },
2110};
2111