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_edid.h>
  19#include <drm/drm_crtc_helper.h>
  20#include <drm/drm_atomic_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, m, false);
 823        if (!ret)
 824                ret = hdmi_avi_infoframe_pack(&frm.avi, buf, sizeof(buf));
 825        if (ret > 0) {
 826                hdmi_reg_writeb(hdata, HDMI_AVI_CON, HDMI_AVI_CON_EVERY_VSYNC);
 827                hdmi_reg_write_buf(hdata, HDMI_AVI_HEADER0, buf, ret);
 828        } else {
 829                DRM_INFO("%s: invalid AVI infoframe (%d)\n", __func__, ret);
 830        }
 831
 832        ret = drm_hdmi_vendor_infoframe_from_display_mode(&frm.vendor.hdmi,
 833                                                          &hdata->connector, m);
 834        if (!ret)
 835                ret = hdmi_vendor_infoframe_pack(&frm.vendor.hdmi, buf,
 836                                sizeof(buf));
 837        if (ret > 0) {
 838                hdmi_reg_writeb(hdata, HDMI_VSI_CON, HDMI_VSI_CON_EVERY_VSYNC);
 839                hdmi_reg_write_buf(hdata, HDMI_VSI_HEADER0, buf, 3);
 840                hdmi_reg_write_buf(hdata, HDMI_VSI_DATA(0), buf + 3, ret - 3);
 841        }
 842
 843        hdmi_audio_infoframe_apply(hdata);
 844}
 845
 846static enum drm_connector_status hdmi_detect(struct drm_connector *connector,
 847                                bool force)
 848{
 849        struct hdmi_context *hdata = connector_to_hdmi(connector);
 850
 851        if (gpiod_get_value(hdata->hpd_gpio))
 852                return connector_status_connected;
 853
 854        cec_notifier_set_phys_addr(hdata->notifier, CEC_PHYS_ADDR_INVALID);
 855        return connector_status_disconnected;
 856}
 857
 858static void hdmi_connector_destroy(struct drm_connector *connector)
 859{
 860        drm_connector_unregister(connector);
 861        drm_connector_cleanup(connector);
 862}
 863
 864static const struct drm_connector_funcs hdmi_connector_funcs = {
 865        .fill_modes = drm_helper_probe_single_connector_modes,
 866        .detect = hdmi_detect,
 867        .destroy = hdmi_connector_destroy,
 868        .reset = drm_atomic_helper_connector_reset,
 869        .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
 870        .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
 871};
 872
 873static int hdmi_get_modes(struct drm_connector *connector)
 874{
 875        struct hdmi_context *hdata = connector_to_hdmi(connector);
 876        struct edid *edid;
 877        int ret;
 878
 879        if (!hdata->ddc_adpt)
 880                return -ENODEV;
 881
 882        edid = drm_get_edid(connector, hdata->ddc_adpt);
 883        if (!edid)
 884                return -ENODEV;
 885
 886        hdata->dvi_mode = !drm_detect_hdmi_monitor(edid);
 887        DRM_DEBUG_KMS("%s : width[%d] x height[%d]\n",
 888                (hdata->dvi_mode ? "dvi monitor" : "hdmi monitor"),
 889                edid->width_cm, edid->height_cm);
 890
 891        drm_connector_update_edid_property(connector, edid);
 892        cec_notifier_set_phys_addr_from_edid(hdata->notifier, edid);
 893
 894        ret = drm_add_edid_modes(connector, edid);
 895
 896        kfree(edid);
 897
 898        return ret;
 899}
 900
 901static int hdmi_find_phy_conf(struct hdmi_context *hdata, u32 pixel_clock)
 902{
 903        const struct hdmiphy_configs *confs = &hdata->drv_data->phy_confs;
 904        int i;
 905
 906        for (i = 0; i < confs->count; i++)
 907                if (confs->data[i].pixel_clock == pixel_clock)
 908                        return i;
 909
 910        DRM_DEBUG_KMS("Could not find phy config for %d\n", pixel_clock);
 911        return -EINVAL;
 912}
 913
 914static int hdmi_mode_valid(struct drm_connector *connector,
 915                        struct drm_display_mode *mode)
 916{
 917        struct hdmi_context *hdata = connector_to_hdmi(connector);
 918        int ret;
 919
 920        DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%d clock=%d\n",
 921                mode->hdisplay, mode->vdisplay, mode->vrefresh,
 922                (mode->flags & DRM_MODE_FLAG_INTERLACE) ? true :
 923                false, mode->clock * 1000);
 924
 925        ret = hdmi_find_phy_conf(hdata, mode->clock * 1000);
 926        if (ret < 0)
 927                return MODE_BAD;
 928
 929        return MODE_OK;
 930}
 931
 932static const struct drm_connector_helper_funcs hdmi_connector_helper_funcs = {
 933        .get_modes = hdmi_get_modes,
 934        .mode_valid = hdmi_mode_valid,
 935};
 936
 937static int hdmi_create_connector(struct drm_encoder *encoder)
 938{
 939        struct hdmi_context *hdata = encoder_to_hdmi(encoder);
 940        struct drm_connector *connector = &hdata->connector;
 941        int ret;
 942
 943        connector->interlace_allowed = true;
 944        connector->polled = DRM_CONNECTOR_POLL_HPD;
 945
 946        ret = drm_connector_init(hdata->drm_dev, connector,
 947                        &hdmi_connector_funcs, DRM_MODE_CONNECTOR_HDMIA);
 948        if (ret) {
 949                DRM_ERROR("Failed to initialize connector with drm\n");
 950                return ret;
 951        }
 952
 953        drm_connector_helper_add(connector, &hdmi_connector_helper_funcs);
 954        drm_connector_attach_encoder(connector, encoder);
 955
 956        if (hdata->bridge) {
 957                ret = drm_bridge_attach(encoder, hdata->bridge, NULL);
 958                if (ret)
 959                        DRM_ERROR("Failed to attach bridge\n");
 960        }
 961
 962        return ret;
 963}
 964
 965static bool hdmi_mode_fixup(struct drm_encoder *encoder,
 966                            const struct drm_display_mode *mode,
 967                            struct drm_display_mode *adjusted_mode)
 968{
 969        struct drm_device *dev = encoder->dev;
 970        struct drm_connector *connector;
 971        struct drm_display_mode *m;
 972        struct drm_connector_list_iter conn_iter;
 973        int mode_ok;
 974
 975        drm_mode_set_crtcinfo(adjusted_mode, 0);
 976
 977        drm_connector_list_iter_begin(dev, &conn_iter);
 978        drm_for_each_connector_iter(connector, &conn_iter) {
 979                if (connector->encoder == encoder)
 980                        break;
 981        }
 982        if (connector)
 983                drm_connector_get(connector);
 984        drm_connector_list_iter_end(&conn_iter);
 985
 986        if (!connector)
 987                return true;
 988
 989        mode_ok = hdmi_mode_valid(connector, adjusted_mode);
 990
 991        if (mode_ok == MODE_OK)
 992                goto cleanup;
 993
 994        /*
 995         * Find the most suitable mode and copy it to adjusted_mode.
 996         */
 997        list_for_each_entry(m, &connector->modes, head) {
 998                mode_ok = hdmi_mode_valid(connector, m);
 999
1000                if (mode_ok == MODE_OK) {
1001                        DRM_INFO("desired mode doesn't exist so\n");
1002                        DRM_INFO("use the most suitable mode among modes.\n");
1003
1004                        DRM_DEBUG_KMS("Adjusted Mode: [%d]x[%d] [%d]Hz\n",
1005                                m->hdisplay, m->vdisplay, m->vrefresh);
1006
1007                        drm_mode_copy(adjusted_mode, m);
1008                        break;
1009                }
1010        }
1011
1012cleanup:
1013        drm_connector_put(connector);
1014
1015        return true;
1016}
1017
1018static void hdmi_reg_acr(struct hdmi_context *hdata, u32 freq)
1019{
1020        u32 n, cts;
1021
1022        cts = (freq % 9) ? 27000 : 30000;
1023        n = 128 * freq / (27000000 / cts);
1024
1025        hdmi_reg_writev(hdata, HDMI_ACR_N0, 3, n);
1026        hdmi_reg_writev(hdata, HDMI_ACR_MCTS0, 3, cts);
1027        hdmi_reg_writev(hdata, HDMI_ACR_CTS0, 3, cts);
1028        hdmi_reg_writeb(hdata, HDMI_ACR_CON, 4);
1029}
1030
1031static void hdmi_audio_config(struct hdmi_context *hdata)
1032{
1033        u32 bit_ch = 1;
1034        u32 data_num, val;
1035        int i;
1036
1037        switch (hdata->audio.params.sample_width) {
1038        case 20:
1039                data_num = 2;
1040                break;
1041        case 24:
1042                data_num = 3;
1043                break;
1044        default:
1045                data_num = 1;
1046                bit_ch = 0;
1047                break;
1048        }
1049
1050        hdmi_reg_acr(hdata, hdata->audio.params.sample_rate);
1051
1052        hdmi_reg_writeb(hdata, HDMI_I2S_MUX_CON, HDMI_I2S_IN_DISABLE
1053                                | HDMI_I2S_AUD_I2S | HDMI_I2S_CUV_I2S_ENABLE
1054                                | HDMI_I2S_MUX_ENABLE);
1055
1056        hdmi_reg_writeb(hdata, HDMI_I2S_MUX_CH, HDMI_I2S_CH0_EN
1057                        | HDMI_I2S_CH1_EN | HDMI_I2S_CH2_EN);
1058
1059        hdmi_reg_writeb(hdata, HDMI_I2S_MUX_CUV, HDMI_I2S_CUV_RL_EN);
1060        hdmi_reg_writeb(hdata, HDMI_I2S_CLK_CON, HDMI_I2S_CLK_DIS);
1061        hdmi_reg_writeb(hdata, HDMI_I2S_CLK_CON, HDMI_I2S_CLK_EN);
1062
1063        val = hdmi_reg_read(hdata, HDMI_I2S_DSD_CON) | 0x01;
1064        hdmi_reg_writeb(hdata, HDMI_I2S_DSD_CON, val);
1065
1066        /* Configuration I2S input ports. Configure I2S_PIN_SEL_0~4 */
1067        hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_0, HDMI_I2S_SEL_SCLK(5)
1068                        | HDMI_I2S_SEL_LRCK(6));
1069
1070        hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_1, HDMI_I2S_SEL_SDATA1(3)
1071                        | HDMI_I2S_SEL_SDATA0(4));
1072
1073        hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_2, HDMI_I2S_SEL_SDATA3(1)
1074                        | HDMI_I2S_SEL_SDATA2(2));
1075
1076        hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_3, HDMI_I2S_SEL_DSD(0));
1077
1078        /* I2S_CON_1 & 2 */
1079        hdmi_reg_writeb(hdata, HDMI_I2S_CON_1, HDMI_I2S_SCLK_FALLING_EDGE
1080                        | HDMI_I2S_L_CH_LOW_POL);
1081        hdmi_reg_writeb(hdata, HDMI_I2S_CON_2, HDMI_I2S_MSB_FIRST_MODE
1082                        | HDMI_I2S_SET_BIT_CH(bit_ch)
1083                        | HDMI_I2S_SET_SDATA_BIT(data_num)
1084                        | HDMI_I2S_BASIC_FORMAT);
1085
1086        /* Configuration of the audio channel status registers */
1087        for (i = 0; i < HDMI_I2S_CH_ST_MAXNUM; i++)
1088                hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST(i),
1089                                hdata->audio.params.iec.status[i]);
1090
1091        hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_CON, HDMI_I2S_CH_STATUS_RELOAD);
1092}
1093
1094static void hdmi_audio_control(struct hdmi_context *hdata)
1095{
1096        bool enable = !hdata->audio.mute;
1097
1098        if (hdata->dvi_mode)
1099                return;
1100
1101        hdmi_reg_writeb(hdata, HDMI_AUI_CON, enable ?
1102                        HDMI_AVI_CON_EVERY_VSYNC : HDMI_AUI_CON_NO_TRAN);
1103        hdmi_reg_writemask(hdata, HDMI_CON_0, enable ?
1104                        HDMI_ASP_EN : HDMI_ASP_DIS, HDMI_ASP_MASK);
1105}
1106
1107static void hdmi_start(struct hdmi_context *hdata, bool start)
1108{
1109        struct drm_display_mode *m = &hdata->encoder.crtc->state->mode;
1110        u32 val = start ? HDMI_TG_EN : 0;
1111
1112        if (m->flags & DRM_MODE_FLAG_INTERLACE)
1113                val |= HDMI_FIELD_EN;
1114
1115        hdmi_reg_writemask(hdata, HDMI_CON_0, val, HDMI_EN);
1116        hdmi_reg_writemask(hdata, HDMI_TG_CMD, val, HDMI_TG_EN | HDMI_FIELD_EN);
1117}
1118
1119static void hdmi_conf_init(struct hdmi_context *hdata)
1120{
1121        /* disable HPD interrupts from HDMI IP block, use GPIO instead */
1122        hdmi_reg_writemask(hdata, HDMI_INTC_CON, 0, HDMI_INTC_EN_GLOBAL |
1123                HDMI_INTC_EN_HPD_PLUG | HDMI_INTC_EN_HPD_UNPLUG);
1124
1125        /* choose HDMI mode */
1126        hdmi_reg_writemask(hdata, HDMI_MODE_SEL,
1127                HDMI_MODE_HDMI_EN, HDMI_MODE_MASK);
1128        /* apply video pre-amble and guard band in HDMI mode only */
1129        hdmi_reg_writeb(hdata, HDMI_CON_2, 0);
1130        /* disable bluescreen */
1131        hdmi_reg_writemask(hdata, HDMI_CON_0, 0, HDMI_BLUE_SCR_EN);
1132
1133        if (hdata->dvi_mode) {
1134                hdmi_reg_writemask(hdata, HDMI_MODE_SEL,
1135                                HDMI_MODE_DVI_EN, HDMI_MODE_MASK);
1136                hdmi_reg_writeb(hdata, HDMI_CON_2,
1137                                HDMI_VID_PREAMBLE_DIS | HDMI_GUARD_BAND_DIS);
1138        }
1139
1140        if (hdata->drv_data->type == HDMI_TYPE13) {
1141                /* choose bluescreen (fecal) color */
1142                hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_0, 0x12);
1143                hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_1, 0x34);
1144                hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_2, 0x56);
1145
1146                /* enable AVI packet every vsync, fixes purple line problem */
1147                hdmi_reg_writeb(hdata, HDMI_V13_AVI_CON, 0x02);
1148                /* force RGB, look to CEA-861-D, table 7 for more detail */
1149                hdmi_reg_writeb(hdata, HDMI_V13_AVI_BYTE(0), 0 << 5);
1150                hdmi_reg_writemask(hdata, HDMI_CON_1, 0x10 << 5, 0x11 << 5);
1151
1152                hdmi_reg_writeb(hdata, HDMI_V13_SPD_CON, 0x02);
1153                hdmi_reg_writeb(hdata, HDMI_V13_AUI_CON, 0x02);
1154                hdmi_reg_writeb(hdata, HDMI_V13_ACR_CON, 0x04);
1155        } else {
1156                hdmi_reg_infoframes(hdata);
1157
1158                /* enable AVI packet every vsync, fixes purple line problem */
1159                hdmi_reg_writemask(hdata, HDMI_CON_1, 2, 3 << 5);
1160        }
1161}
1162
1163static void hdmiphy_wait_for_pll(struct hdmi_context *hdata)
1164{
1165        int tries;
1166
1167        for (tries = 0; tries < 10; ++tries) {
1168                u32 val = hdmi_reg_read(hdata, HDMI_PHY_STATUS);
1169
1170                if (val & HDMI_PHY_STATUS_READY) {
1171                        DRM_DEBUG_KMS("PLL stabilized after %d tries\n", tries);
1172                        return;
1173                }
1174                usleep_range(10, 20);
1175        }
1176
1177        DRM_ERROR("PLL could not reach steady state\n");
1178}
1179
1180static void hdmi_v13_mode_apply(struct hdmi_context *hdata)
1181{
1182        struct drm_display_mode *m = &hdata->encoder.crtc->state->mode;
1183        unsigned int val;
1184
1185        hdmi_reg_writev(hdata, HDMI_H_BLANK_0, 2, m->htotal - m->hdisplay);
1186        hdmi_reg_writev(hdata, HDMI_V13_H_V_LINE_0, 3,
1187                        (m->htotal << 12) | m->vtotal);
1188
1189        val = (m->flags & DRM_MODE_FLAG_NVSYNC) ? 1 : 0;
1190        hdmi_reg_writev(hdata, HDMI_VSYNC_POL, 1, val);
1191
1192        val = (m->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0;
1193        hdmi_reg_writev(hdata, HDMI_INT_PRO_MODE, 1, val);
1194
1195        val = (m->hsync_start - m->hdisplay - 2);
1196        val |= ((m->hsync_end - m->hdisplay - 2) << 10);
1197        val |= ((m->flags & DRM_MODE_FLAG_NHSYNC) ? 1 : 0)<<20;
1198        hdmi_reg_writev(hdata, HDMI_V13_H_SYNC_GEN_0, 3, val);
1199
1200        /*
1201         * Quirk requirement for exynos HDMI IP design,
1202         * 2 pixels less than the actual calculation for hsync_start
1203         * and end.
1204         */
1205
1206        /* Following values & calculations differ for different type of modes */
1207        if (m->flags & DRM_MODE_FLAG_INTERLACE) {
1208                val = ((m->vsync_end - m->vdisplay) / 2);
1209                val |= ((m->vsync_start - m->vdisplay) / 2) << 12;
1210                hdmi_reg_writev(hdata, HDMI_V13_V_SYNC_GEN_1_0, 3, val);
1211
1212                val = m->vtotal / 2;
1213                val |= ((m->vtotal - m->vdisplay) / 2) << 11;
1214                hdmi_reg_writev(hdata, HDMI_V13_V_BLANK_0, 3, val);
1215
1216                val = (m->vtotal +
1217                        ((m->vsync_end - m->vsync_start) * 4) + 5) / 2;
1218                val |= m->vtotal << 11;
1219                hdmi_reg_writev(hdata, HDMI_V13_V_BLANK_F_0, 3, val);
1220
1221                val = ((m->vtotal / 2) + 7);
1222                val |= ((m->vtotal / 2) + 2) << 12;
1223                hdmi_reg_writev(hdata, HDMI_V13_V_SYNC_GEN_2_0, 3, val);
1224
1225                val = ((m->htotal / 2) + (m->hsync_start - m->hdisplay));
1226                val |= ((m->htotal / 2) +
1227                        (m->hsync_start - m->hdisplay)) << 12;
1228                hdmi_reg_writev(hdata, HDMI_V13_V_SYNC_GEN_3_0, 3, val);
1229
1230                hdmi_reg_writev(hdata, HDMI_TG_VACT_ST_L, 2,
1231                                (m->vtotal - m->vdisplay) / 2);
1232                hdmi_reg_writev(hdata, HDMI_TG_VACT_SZ_L, 2, m->vdisplay / 2);
1233
1234                hdmi_reg_writev(hdata, HDMI_TG_VACT_ST2_L, 2, 0x249);
1235        } else {
1236                val = m->vtotal;
1237                val |= (m->vtotal - m->vdisplay) << 11;
1238                hdmi_reg_writev(hdata, HDMI_V13_V_BLANK_0, 3, val);
1239
1240                hdmi_reg_writev(hdata, HDMI_V13_V_BLANK_F_0, 3, 0);
1241
1242                val = (m->vsync_end - m->vdisplay);
1243                val |= ((m->vsync_start - m->vdisplay) << 12);
1244                hdmi_reg_writev(hdata, HDMI_V13_V_SYNC_GEN_1_0, 3, val);
1245
1246                hdmi_reg_writev(hdata, HDMI_V13_V_SYNC_GEN_2_0, 3, 0x1001);
1247                hdmi_reg_writev(hdata, HDMI_V13_V_SYNC_GEN_3_0, 3, 0x1001);
1248                hdmi_reg_writev(hdata, HDMI_TG_VACT_ST_L, 2,
1249                                m->vtotal - m->vdisplay);
1250                hdmi_reg_writev(hdata, HDMI_TG_VACT_SZ_L, 2, m->vdisplay);
1251        }
1252
1253        hdmi_reg_writev(hdata, HDMI_TG_H_FSZ_L, 2, m->htotal);
1254        hdmi_reg_writev(hdata, HDMI_TG_HACT_ST_L, 2, m->htotal - m->hdisplay);
1255        hdmi_reg_writev(hdata, HDMI_TG_HACT_SZ_L, 2, m->hdisplay);
1256        hdmi_reg_writev(hdata, HDMI_TG_V_FSZ_L, 2, m->vtotal);
1257}
1258
1259static void hdmi_v14_mode_apply(struct hdmi_context *hdata)
1260{
1261        struct drm_display_mode *m = &hdata->encoder.crtc->state->mode;
1262        struct drm_display_mode *am =
1263                                &hdata->encoder.crtc->state->adjusted_mode;
1264        int hquirk = 0;
1265
1266        /*
1267         * In case video mode coming from CRTC differs from requested one HDMI
1268         * sometimes is able to almost properly perform conversion - only
1269         * first line is distorted.
1270         */
1271        if ((m->vdisplay != am->vdisplay) &&
1272            (m->hdisplay == 1280 || m->hdisplay == 1024 || m->hdisplay == 1366))
1273                hquirk = 258;
1274
1275        hdmi_reg_writev(hdata, HDMI_H_BLANK_0, 2, m->htotal - m->hdisplay);
1276        hdmi_reg_writev(hdata, HDMI_V_LINE_0, 2, m->vtotal);
1277        hdmi_reg_writev(hdata, HDMI_H_LINE_0, 2, m->htotal);
1278        hdmi_reg_writev(hdata, HDMI_HSYNC_POL, 1,
1279                        (m->flags & DRM_MODE_FLAG_NHSYNC) ? 1 : 0);
1280        hdmi_reg_writev(hdata, HDMI_VSYNC_POL, 1,
1281                        (m->flags & DRM_MODE_FLAG_NVSYNC) ? 1 : 0);
1282        hdmi_reg_writev(hdata, HDMI_INT_PRO_MODE, 1,
1283                        (m->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0);
1284
1285        /*
1286         * Quirk requirement for exynos 5 HDMI IP design,
1287         * 2 pixels less than the actual calculation for hsync_start
1288         * and end.
1289         */
1290
1291        /* Following values & calculations differ for different type of modes */
1292        if (m->flags & DRM_MODE_FLAG_INTERLACE) {
1293                hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_BEF_2_0, 2,
1294                        (m->vsync_end - m->vdisplay) / 2);
1295                hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_BEF_1_0, 2,
1296                        (m->vsync_start - m->vdisplay) / 2);
1297                hdmi_reg_writev(hdata, HDMI_V2_BLANK_0, 2, m->vtotal / 2);
1298                hdmi_reg_writev(hdata, HDMI_V1_BLANK_0, 2,
1299                                (m->vtotal - m->vdisplay) / 2);
1300                hdmi_reg_writev(hdata, HDMI_V_BLANK_F0_0, 2,
1301                                m->vtotal - m->vdisplay / 2);
1302                hdmi_reg_writev(hdata, HDMI_V_BLANK_F1_0, 2, m->vtotal);
1303                hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_2_0, 2,
1304                                (m->vtotal / 2) + 7);
1305                hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_1_0, 2,
1306                                (m->vtotal / 2) + 2);
1307                hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_PXL_2_0, 2,
1308                        (m->htotal / 2) + (m->hsync_start - m->hdisplay));
1309                hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_PXL_1_0, 2,
1310                        (m->htotal / 2) + (m->hsync_start - m->hdisplay));
1311                hdmi_reg_writev(hdata, HDMI_TG_VACT_ST_L, 2,
1312                                (m->vtotal - m->vdisplay) / 2);
1313                hdmi_reg_writev(hdata, HDMI_TG_VACT_SZ_L, 2, m->vdisplay / 2);
1314                hdmi_reg_writev(hdata, HDMI_TG_VACT_ST2_L, 2,
1315                                m->vtotal - m->vdisplay / 2);
1316                hdmi_reg_writev(hdata, HDMI_TG_VSYNC2_L, 2,
1317                                (m->vtotal / 2) + 1);
1318                hdmi_reg_writev(hdata, HDMI_TG_VSYNC_BOT_HDMI_L, 2,
1319                                (m->vtotal / 2) + 1);
1320                hdmi_reg_writev(hdata, HDMI_TG_FIELD_BOT_HDMI_L, 2,
1321                                (m->vtotal / 2) + 1);
1322                hdmi_reg_writev(hdata, HDMI_TG_VACT_ST3_L, 2, 0x0);
1323                hdmi_reg_writev(hdata, HDMI_TG_VACT_ST4_L, 2, 0x0);
1324        } else {
1325                hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_BEF_2_0, 2,
1326                        m->vsync_end - m->vdisplay);
1327                hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_BEF_1_0, 2,
1328                        m->vsync_start - m->vdisplay);
1329                hdmi_reg_writev(hdata, HDMI_V2_BLANK_0, 2, m->vtotal);
1330                hdmi_reg_writev(hdata, HDMI_V1_BLANK_0, 2,
1331                                m->vtotal - m->vdisplay);
1332                hdmi_reg_writev(hdata, HDMI_V_BLANK_F0_0, 2, 0xffff);
1333                hdmi_reg_writev(hdata, HDMI_V_BLANK_F1_0, 2, 0xffff);
1334                hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_2_0, 2, 0xffff);
1335                hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_1_0, 2, 0xffff);
1336                hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_PXL_2_0, 2, 0xffff);
1337                hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_PXL_1_0, 2, 0xffff);
1338                hdmi_reg_writev(hdata, HDMI_TG_VACT_ST_L, 2,
1339                                m->vtotal - m->vdisplay);
1340                hdmi_reg_writev(hdata, HDMI_TG_VACT_SZ_L, 2, m->vdisplay);
1341        }
1342
1343        hdmi_reg_writev(hdata, HDMI_H_SYNC_START_0, 2,
1344                        m->hsync_start - m->hdisplay - 2);
1345        hdmi_reg_writev(hdata, HDMI_H_SYNC_END_0, 2,
1346                        m->hsync_end - m->hdisplay - 2);
1347        hdmi_reg_writev(hdata, HDMI_VACT_SPACE_1_0, 2, 0xffff);
1348        hdmi_reg_writev(hdata, HDMI_VACT_SPACE_2_0, 2, 0xffff);
1349        hdmi_reg_writev(hdata, HDMI_VACT_SPACE_3_0, 2, 0xffff);
1350        hdmi_reg_writev(hdata, HDMI_VACT_SPACE_4_0, 2, 0xffff);
1351        hdmi_reg_writev(hdata, HDMI_VACT_SPACE_5_0, 2, 0xffff);
1352        hdmi_reg_writev(hdata, HDMI_VACT_SPACE_6_0, 2, 0xffff);
1353        hdmi_reg_writev(hdata, HDMI_V_BLANK_F2_0, 2, 0xffff);
1354        hdmi_reg_writev(hdata, HDMI_V_BLANK_F3_0, 2, 0xffff);
1355        hdmi_reg_writev(hdata, HDMI_V_BLANK_F4_0, 2, 0xffff);
1356        hdmi_reg_writev(hdata, HDMI_V_BLANK_F5_0, 2, 0xffff);
1357        hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_3_0, 2, 0xffff);
1358        hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_4_0, 2, 0xffff);
1359        hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_5_0, 2, 0xffff);
1360        hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_6_0, 2, 0xffff);
1361        hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_PXL_3_0, 2, 0xffff);
1362        hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_PXL_4_0, 2, 0xffff);
1363        hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_PXL_5_0, 2, 0xffff);
1364        hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_PXL_6_0, 2, 0xffff);
1365
1366        hdmi_reg_writev(hdata, HDMI_TG_H_FSZ_L, 2, m->htotal);
1367        hdmi_reg_writev(hdata, HDMI_TG_HACT_ST_L, 2,
1368                                        m->htotal - m->hdisplay - hquirk);
1369        hdmi_reg_writev(hdata, HDMI_TG_HACT_SZ_L, 2, m->hdisplay + hquirk);
1370        hdmi_reg_writev(hdata, HDMI_TG_V_FSZ_L, 2, m->vtotal);
1371        if (hdata->drv_data == &exynos5433_hdmi_driver_data)
1372                hdmi_reg_writeb(hdata, HDMI_TG_DECON_EN, 1);
1373}
1374
1375static void hdmi_mode_apply(struct hdmi_context *hdata)
1376{
1377        if (hdata->drv_data->type == HDMI_TYPE13)
1378                hdmi_v13_mode_apply(hdata);
1379        else
1380                hdmi_v14_mode_apply(hdata);
1381
1382        hdmi_start(hdata, true);
1383}
1384
1385static void hdmiphy_conf_reset(struct hdmi_context *hdata)
1386{
1387        hdmi_reg_writemask(hdata, HDMI_CORE_RSTOUT, 0, 1);
1388        usleep_range(10000, 12000);
1389        hdmi_reg_writemask(hdata, HDMI_CORE_RSTOUT, ~0, 1);
1390        usleep_range(10000, 12000);
1391        hdmi_reg_writemask(hdata, HDMI_PHY_RSTOUT, ~0, HDMI_PHY_SW_RSTOUT);
1392        usleep_range(10000, 12000);
1393        hdmi_reg_writemask(hdata, HDMI_PHY_RSTOUT, 0, HDMI_PHY_SW_RSTOUT);
1394        usleep_range(10000, 12000);
1395}
1396
1397static void hdmiphy_enable_mode_set(struct hdmi_context *hdata, bool enable)
1398{
1399        u8 v = enable ? HDMI_PHY_ENABLE_MODE_SET : HDMI_PHY_DISABLE_MODE_SET;
1400
1401        if (hdata->drv_data == &exynos5433_hdmi_driver_data)
1402                writel(v, hdata->regs_hdmiphy + HDMIPHY5433_MODE_SET_DONE);
1403}
1404
1405static void hdmiphy_conf_apply(struct hdmi_context *hdata)
1406{
1407        struct drm_display_mode *m = &hdata->encoder.crtc->state->mode;
1408        int ret;
1409        const u8 *phy_conf;
1410
1411        ret = hdmi_find_phy_conf(hdata, m->clock * 1000);
1412        if (ret < 0) {
1413                DRM_ERROR("failed to find hdmiphy conf\n");
1414                return;
1415        }
1416        phy_conf = hdata->drv_data->phy_confs.data[ret].conf;
1417
1418        hdmi_clk_set_parents(hdata, false);
1419
1420        hdmiphy_conf_reset(hdata);
1421
1422        hdmiphy_enable_mode_set(hdata, true);
1423        ret = hdmiphy_reg_write_buf(hdata, 0, phy_conf, 32);
1424        if (ret) {
1425                DRM_ERROR("failed to configure hdmiphy\n");
1426                return;
1427        }
1428        hdmiphy_enable_mode_set(hdata, false);
1429        hdmi_clk_set_parents(hdata, true);
1430        usleep_range(10000, 12000);
1431        hdmiphy_wait_for_pll(hdata);
1432}
1433
1434/* Should be called with hdata->mutex mutex held */
1435static void hdmi_conf_apply(struct hdmi_context *hdata)
1436{
1437        hdmi_start(hdata, false);
1438        hdmi_conf_init(hdata);
1439        hdmi_audio_config(hdata);
1440        hdmi_mode_apply(hdata);
1441        hdmi_audio_control(hdata);
1442}
1443
1444static void hdmi_set_refclk(struct hdmi_context *hdata, bool on)
1445{
1446        if (!hdata->sysreg)
1447                return;
1448
1449        regmap_update_bits(hdata->sysreg, EXYNOS5433_SYSREG_DISP_HDMI_PHY,
1450                           SYSREG_HDMI_REFCLK_INT_CLK, on ? ~0 : 0);
1451}
1452
1453/* Should be called with hdata->mutex mutex held. */
1454static void hdmiphy_enable(struct hdmi_context *hdata)
1455{
1456        if (hdata->powered)
1457                return;
1458
1459        pm_runtime_get_sync(hdata->dev);
1460
1461        if (regulator_bulk_enable(ARRAY_SIZE(supply), hdata->regul_bulk))
1462                DRM_DEBUG_KMS("failed to enable regulator bulk\n");
1463
1464        regmap_update_bits(hdata->pmureg, PMU_HDMI_PHY_CONTROL,
1465                        PMU_HDMI_PHY_ENABLE_BIT, 1);
1466
1467        hdmi_set_refclk(hdata, true);
1468
1469        hdmi_reg_writemask(hdata, HDMI_PHY_CON_0, 0, HDMI_PHY_POWER_OFF_EN);
1470
1471        hdmiphy_conf_apply(hdata);
1472
1473        hdata->powered = true;
1474}
1475
1476/* Should be called with hdata->mutex mutex held. */
1477static void hdmiphy_disable(struct hdmi_context *hdata)
1478{
1479        if (!hdata->powered)
1480                return;
1481
1482        hdmi_reg_writemask(hdata, HDMI_CON_0, 0, HDMI_EN);
1483
1484        hdmi_reg_writemask(hdata, HDMI_PHY_CON_0, ~0, HDMI_PHY_POWER_OFF_EN);
1485
1486        hdmi_set_refclk(hdata, false);
1487
1488        regmap_update_bits(hdata->pmureg, PMU_HDMI_PHY_CONTROL,
1489                        PMU_HDMI_PHY_ENABLE_BIT, 0);
1490
1491        regulator_bulk_disable(ARRAY_SIZE(supply), hdata->regul_bulk);
1492
1493        pm_runtime_put_sync(hdata->dev);
1494
1495        hdata->powered = false;
1496}
1497
1498static void hdmi_enable(struct drm_encoder *encoder)
1499{
1500        struct hdmi_context *hdata = encoder_to_hdmi(encoder);
1501
1502        mutex_lock(&hdata->mutex);
1503
1504        hdmiphy_enable(hdata);
1505        hdmi_conf_apply(hdata);
1506
1507        mutex_unlock(&hdata->mutex);
1508}
1509
1510static void hdmi_disable(struct drm_encoder *encoder)
1511{
1512        struct hdmi_context *hdata = encoder_to_hdmi(encoder);
1513
1514        mutex_lock(&hdata->mutex);
1515
1516        if (hdata->powered) {
1517                /*
1518                 * The SFRs of VP and Mixer are updated by Vertical Sync of
1519                 * Timing generator which is a part of HDMI so the sequence
1520                 * to disable TV Subsystem should be as following,
1521                 *      VP -> Mixer -> HDMI
1522                 *
1523                 * To achieve such sequence HDMI is disabled together with
1524                 * HDMI PHY, via pipe clock callback.
1525                 */
1526                mutex_unlock(&hdata->mutex);
1527                cancel_delayed_work(&hdata->hotplug_work);
1528                cec_notifier_set_phys_addr(hdata->notifier,
1529                                           CEC_PHYS_ADDR_INVALID);
1530                return;
1531        }
1532
1533        mutex_unlock(&hdata->mutex);
1534}
1535
1536static const struct drm_encoder_helper_funcs exynos_hdmi_encoder_helper_funcs = {
1537        .mode_fixup     = hdmi_mode_fixup,
1538        .enable         = hdmi_enable,
1539        .disable        = hdmi_disable,
1540};
1541
1542static const struct drm_encoder_funcs exynos_hdmi_encoder_funcs = {
1543        .destroy = drm_encoder_cleanup,
1544};
1545
1546static void hdmi_audio_shutdown(struct device *dev, void *data)
1547{
1548        struct hdmi_context *hdata = dev_get_drvdata(dev);
1549
1550        mutex_lock(&hdata->mutex);
1551
1552        hdata->audio.mute = true;
1553
1554        if (hdata->powered)
1555                hdmi_audio_control(hdata);
1556
1557        mutex_unlock(&hdata->mutex);
1558}
1559
1560static int hdmi_audio_hw_params(struct device *dev, void *data,
1561                                struct hdmi_codec_daifmt *daifmt,
1562                                struct hdmi_codec_params *params)
1563{
1564        struct hdmi_context *hdata = dev_get_drvdata(dev);
1565
1566        if (daifmt->fmt != HDMI_I2S || daifmt->bit_clk_inv ||
1567            daifmt->frame_clk_inv || daifmt->bit_clk_master ||
1568            daifmt->frame_clk_master) {
1569                dev_err(dev, "%s: Bad flags %d %d %d %d\n", __func__,
1570                        daifmt->bit_clk_inv, daifmt->frame_clk_inv,
1571                        daifmt->bit_clk_master,
1572                        daifmt->frame_clk_master);
1573                return -EINVAL;
1574        }
1575
1576        mutex_lock(&hdata->mutex);
1577
1578        hdata->audio.params = *params;
1579
1580        if (hdata->powered) {
1581                hdmi_audio_config(hdata);
1582                hdmi_audio_infoframe_apply(hdata);
1583        }
1584
1585        mutex_unlock(&hdata->mutex);
1586
1587        return 0;
1588}
1589
1590static int hdmi_audio_digital_mute(struct device *dev, void *data, bool mute)
1591{
1592        struct hdmi_context *hdata = dev_get_drvdata(dev);
1593
1594        mutex_lock(&hdata->mutex);
1595
1596        hdata->audio.mute = mute;
1597
1598        if (hdata->powered)
1599                hdmi_audio_control(hdata);
1600
1601        mutex_unlock(&hdata->mutex);
1602
1603        return 0;
1604}
1605
1606static int hdmi_audio_get_eld(struct device *dev, void *data, uint8_t *buf,
1607                              size_t len)
1608{
1609        struct hdmi_context *hdata = dev_get_drvdata(dev);
1610        struct drm_connector *connector = &hdata->connector;
1611
1612        memcpy(buf, connector->eld, min(sizeof(connector->eld), len));
1613
1614        return 0;
1615}
1616
1617static const struct hdmi_codec_ops audio_codec_ops = {
1618        .hw_params = hdmi_audio_hw_params,
1619        .audio_shutdown = hdmi_audio_shutdown,
1620        .digital_mute = hdmi_audio_digital_mute,
1621        .get_eld = hdmi_audio_get_eld,
1622};
1623
1624static int hdmi_register_audio_device(struct hdmi_context *hdata)
1625{
1626        struct hdmi_codec_pdata codec_data = {
1627                .ops = &audio_codec_ops,
1628                .max_i2s_channels = 6,
1629                .i2s = 1,
1630        };
1631
1632        hdata->audio.pdev = platform_device_register_data(
1633                hdata->dev, HDMI_CODEC_DRV_NAME, PLATFORM_DEVID_AUTO,
1634                &codec_data, sizeof(codec_data));
1635
1636        return PTR_ERR_OR_ZERO(hdata->audio.pdev);
1637}
1638
1639static void hdmi_hotplug_work_func(struct work_struct *work)
1640{
1641        struct hdmi_context *hdata;
1642
1643        hdata = container_of(work, struct hdmi_context, hotplug_work.work);
1644
1645        if (hdata->drm_dev)
1646                drm_helper_hpd_irq_event(hdata->drm_dev);
1647}
1648
1649static irqreturn_t hdmi_irq_thread(int irq, void *arg)
1650{
1651        struct hdmi_context *hdata = arg;
1652
1653        mod_delayed_work(system_wq, &hdata->hotplug_work,
1654                        msecs_to_jiffies(HOTPLUG_DEBOUNCE_MS));
1655
1656        return IRQ_HANDLED;
1657}
1658
1659static int hdmi_clks_get(struct hdmi_context *hdata,
1660                         const struct string_array_spec *names,
1661                         struct clk **clks)
1662{
1663        struct device *dev = hdata->dev;
1664        int i;
1665
1666        for (i = 0; i < names->count; ++i) {
1667                struct clk *clk = devm_clk_get(dev, names->data[i]);
1668
1669                if (IS_ERR(clk)) {
1670                        int ret = PTR_ERR(clk);
1671
1672                        dev_err(dev, "Cannot get clock %s, %d\n",
1673                                names->data[i], ret);
1674
1675                        return ret;
1676                }
1677
1678                clks[i] = clk;
1679        }
1680
1681        return 0;
1682}
1683
1684static int hdmi_clk_init(struct hdmi_context *hdata)
1685{
1686        const struct hdmi_driver_data *drv_data = hdata->drv_data;
1687        int count = drv_data->clk_gates.count + drv_data->clk_muxes.count;
1688        struct device *dev = hdata->dev;
1689        struct clk **clks;
1690        int ret;
1691
1692        if (!count)
1693                return 0;
1694
1695        clks = devm_kcalloc(dev, count, sizeof(*clks), GFP_KERNEL);
1696        if (!clks)
1697                return -ENOMEM;
1698
1699        hdata->clk_gates = clks;
1700        hdata->clk_muxes = clks + drv_data->clk_gates.count;
1701
1702        ret = hdmi_clks_get(hdata, &drv_data->clk_gates, hdata->clk_gates);
1703        if (ret)
1704                return ret;
1705
1706        return hdmi_clks_get(hdata, &drv_data->clk_muxes, hdata->clk_muxes);
1707}
1708
1709
1710static void hdmiphy_clk_enable(struct exynos_drm_clk *clk, bool enable)
1711{
1712        struct hdmi_context *hdata = container_of(clk, struct hdmi_context,
1713                                                  phy_clk);
1714        mutex_lock(&hdata->mutex);
1715
1716        if (enable)
1717                hdmiphy_enable(hdata);
1718        else
1719                hdmiphy_disable(hdata);
1720
1721        mutex_unlock(&hdata->mutex);
1722}
1723
1724static int hdmi_bridge_init(struct hdmi_context *hdata)
1725{
1726        struct device *dev = hdata->dev;
1727        struct device_node *ep, *np;
1728
1729        ep = of_graph_get_endpoint_by_regs(dev->of_node, 1, -1);
1730        if (!ep)
1731                return 0;
1732
1733        np = of_graph_get_remote_port_parent(ep);
1734        of_node_put(ep);
1735        if (!np) {
1736                DRM_ERROR("failed to get remote port parent");
1737                return -EINVAL;
1738        }
1739
1740        hdata->bridge = of_drm_find_bridge(np);
1741        of_node_put(np);
1742
1743        if (!hdata->bridge)
1744                return -EPROBE_DEFER;
1745
1746        return 0;
1747}
1748
1749static int hdmi_resources_init(struct hdmi_context *hdata)
1750{
1751        struct device *dev = hdata->dev;
1752        int i, ret;
1753
1754        DRM_DEBUG_KMS("HDMI resource init\n");
1755
1756        hdata->hpd_gpio = devm_gpiod_get(dev, "hpd", GPIOD_IN);
1757        if (IS_ERR(hdata->hpd_gpio)) {
1758                DRM_ERROR("cannot get hpd gpio property\n");
1759                return PTR_ERR(hdata->hpd_gpio);
1760        }
1761
1762        hdata->irq = gpiod_to_irq(hdata->hpd_gpio);
1763        if (hdata->irq < 0) {
1764                DRM_ERROR("failed to get GPIO irq\n");
1765                return  hdata->irq;
1766        }
1767
1768        ret = hdmi_clk_init(hdata);
1769        if (ret)
1770                return ret;
1771
1772        ret = hdmi_clk_set_parents(hdata, false);
1773        if (ret)
1774                return ret;
1775
1776        for (i = 0; i < ARRAY_SIZE(supply); ++i)
1777                hdata->regul_bulk[i].supply = supply[i];
1778
1779        ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(supply), hdata->regul_bulk);
1780        if (ret) {
1781                if (ret != -EPROBE_DEFER)
1782                        DRM_ERROR("failed to get regulators\n");
1783                return ret;
1784        }
1785
1786        hdata->reg_hdmi_en = devm_regulator_get_optional(dev, "hdmi-en");
1787
1788        if (PTR_ERR(hdata->reg_hdmi_en) != -ENODEV) {
1789                if (IS_ERR(hdata->reg_hdmi_en))
1790                        return PTR_ERR(hdata->reg_hdmi_en);
1791
1792                ret = regulator_enable(hdata->reg_hdmi_en);
1793                if (ret) {
1794                        DRM_ERROR("failed to enable hdmi-en regulator\n");
1795                        return ret;
1796                }
1797        }
1798
1799        return hdmi_bridge_init(hdata);
1800}
1801
1802static const struct of_device_id hdmi_match_types[] = {
1803        {
1804                .compatible = "samsung,exynos4210-hdmi",
1805                .data = &exynos4210_hdmi_driver_data,
1806        }, {
1807                .compatible = "samsung,exynos4212-hdmi",
1808                .data = &exynos4212_hdmi_driver_data,
1809        }, {
1810                .compatible = "samsung,exynos5420-hdmi",
1811                .data = &exynos5420_hdmi_driver_data,
1812        }, {
1813                .compatible = "samsung,exynos5433-hdmi",
1814                .data = &exynos5433_hdmi_driver_data,
1815        }, {
1816                /* end node */
1817        }
1818};
1819MODULE_DEVICE_TABLE (of, hdmi_match_types);
1820
1821static int hdmi_bind(struct device *dev, struct device *master, void *data)
1822{
1823        struct drm_device *drm_dev = data;
1824        struct hdmi_context *hdata = dev_get_drvdata(dev);
1825        struct drm_encoder *encoder = &hdata->encoder;
1826        struct exynos_drm_crtc *crtc;
1827        int ret;
1828
1829        hdata->drm_dev = drm_dev;
1830
1831        hdata->phy_clk.enable = hdmiphy_clk_enable;
1832
1833        drm_encoder_init(drm_dev, encoder, &exynos_hdmi_encoder_funcs,
1834                         DRM_MODE_ENCODER_TMDS, NULL);
1835
1836        drm_encoder_helper_add(encoder, &exynos_hdmi_encoder_helper_funcs);
1837
1838        ret = exynos_drm_set_possible_crtcs(encoder, EXYNOS_DISPLAY_TYPE_HDMI);
1839        if (ret < 0)
1840                return ret;
1841
1842        crtc = exynos_drm_crtc_get_by_type(drm_dev, EXYNOS_DISPLAY_TYPE_HDMI);
1843        crtc->pipe_clk = &hdata->phy_clk;
1844
1845        ret = hdmi_create_connector(encoder);
1846        if (ret) {
1847                DRM_ERROR("failed to create connector ret = %d\n", ret);
1848                drm_encoder_cleanup(encoder);
1849                return ret;
1850        }
1851
1852        return 0;
1853}
1854
1855static void hdmi_unbind(struct device *dev, struct device *master, void *data)
1856{
1857}
1858
1859static const struct component_ops hdmi_component_ops = {
1860        .bind   = hdmi_bind,
1861        .unbind = hdmi_unbind,
1862};
1863
1864static int hdmi_get_ddc_adapter(struct hdmi_context *hdata)
1865{
1866        const char *compatible_str = "samsung,exynos4210-hdmiddc";
1867        struct device_node *np;
1868        struct i2c_adapter *adpt;
1869
1870        np = of_find_compatible_node(NULL, NULL, compatible_str);
1871        if (np)
1872                np = of_get_next_parent(np);
1873        else
1874                np = of_parse_phandle(hdata->dev->of_node, "ddc", 0);
1875
1876        if (!np) {
1877                DRM_ERROR("Failed to find ddc node in device tree\n");
1878                return -ENODEV;
1879        }
1880
1881        adpt = of_find_i2c_adapter_by_node(np);
1882        of_node_put(np);
1883
1884        if (!adpt) {
1885                DRM_INFO("Failed to get ddc i2c adapter by node\n");
1886                return -EPROBE_DEFER;
1887        }
1888
1889        hdata->ddc_adpt = adpt;
1890
1891        return 0;
1892}
1893
1894static int hdmi_get_phy_io(struct hdmi_context *hdata)
1895{
1896        const char *compatible_str = "samsung,exynos4212-hdmiphy";
1897        struct device_node *np;
1898        int ret = 0;
1899
1900        np = of_find_compatible_node(NULL, NULL, compatible_str);
1901        if (!np) {
1902                np = of_parse_phandle(hdata->dev->of_node, "phy", 0);
1903                if (!np) {
1904                        DRM_ERROR("Failed to find hdmiphy node in device tree\n");
1905                        return -ENODEV;
1906                }
1907        }
1908
1909        if (hdata->drv_data->is_apb_phy) {
1910                hdata->regs_hdmiphy = of_iomap(np, 0);
1911                if (!hdata->regs_hdmiphy) {
1912                        DRM_ERROR("failed to ioremap hdmi phy\n");
1913                        ret = -ENOMEM;
1914                        goto out;
1915                }
1916        } else {
1917                hdata->hdmiphy_port = of_find_i2c_device_by_node(np);
1918                if (!hdata->hdmiphy_port) {
1919                        DRM_INFO("Failed to get hdmi phy i2c client\n");
1920                        ret = -EPROBE_DEFER;
1921                        goto out;
1922                }
1923        }
1924
1925out:
1926        of_node_put(np);
1927        return ret;
1928}
1929
1930static int hdmi_probe(struct platform_device *pdev)
1931{
1932        struct hdmi_audio_infoframe *audio_infoframe;
1933        struct device *dev = &pdev->dev;
1934        struct hdmi_context *hdata;
1935        struct resource *res;
1936        int ret;
1937
1938        hdata = devm_kzalloc(dev, sizeof(struct hdmi_context), GFP_KERNEL);
1939        if (!hdata)
1940                return -ENOMEM;
1941
1942        hdata->drv_data = of_device_get_match_data(dev);
1943
1944        platform_set_drvdata(pdev, hdata);
1945
1946        hdata->dev = dev;
1947
1948        mutex_init(&hdata->mutex);
1949
1950        ret = hdmi_resources_init(hdata);
1951        if (ret) {
1952                if (ret != -EPROBE_DEFER)
1953                        DRM_ERROR("hdmi_resources_init failed\n");
1954                return ret;
1955        }
1956
1957        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1958        hdata->regs = devm_ioremap_resource(dev, res);
1959        if (IS_ERR(hdata->regs)) {
1960                ret = PTR_ERR(hdata->regs);
1961                return ret;
1962        }
1963
1964        ret = hdmi_get_ddc_adapter(hdata);
1965        if (ret)
1966                return ret;
1967
1968        ret = hdmi_get_phy_io(hdata);
1969        if (ret)
1970                goto err_ddc;
1971
1972        INIT_DELAYED_WORK(&hdata->hotplug_work, hdmi_hotplug_work_func);
1973
1974        ret = devm_request_threaded_irq(dev, hdata->irq, NULL,
1975                        hdmi_irq_thread, IRQF_TRIGGER_RISING |
1976                        IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
1977                        "hdmi", hdata);
1978        if (ret) {
1979                DRM_ERROR("failed to register hdmi interrupt\n");
1980                goto err_hdmiphy;
1981        }
1982
1983        hdata->pmureg = syscon_regmap_lookup_by_phandle(dev->of_node,
1984                        "samsung,syscon-phandle");
1985        if (IS_ERR(hdata->pmureg)) {
1986                DRM_ERROR("syscon regmap lookup failed.\n");
1987                ret = -EPROBE_DEFER;
1988                goto err_hdmiphy;
1989        }
1990
1991        if (hdata->drv_data->has_sysreg) {
1992                hdata->sysreg = syscon_regmap_lookup_by_phandle(dev->of_node,
1993                                "samsung,sysreg-phandle");
1994                if (IS_ERR(hdata->sysreg)) {
1995                        DRM_ERROR("sysreg regmap lookup failed.\n");
1996                        ret = -EPROBE_DEFER;
1997                        goto err_hdmiphy;
1998                }
1999        }
2000
2001        hdata->notifier = cec_notifier_get(&pdev->dev);
2002        if (hdata->notifier == NULL) {
2003                ret = -ENOMEM;
2004                goto err_hdmiphy;
2005        }
2006
2007        pm_runtime_enable(dev);
2008
2009        audio_infoframe = &hdata->audio.infoframe;
2010        hdmi_audio_infoframe_init(audio_infoframe);
2011        audio_infoframe->coding_type = HDMI_AUDIO_CODING_TYPE_STREAM;
2012        audio_infoframe->sample_size = HDMI_AUDIO_SAMPLE_SIZE_STREAM;
2013        audio_infoframe->sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_STREAM;
2014        audio_infoframe->channels = 2;
2015
2016        ret = hdmi_register_audio_device(hdata);
2017        if (ret)
2018                goto err_notifier_put;
2019
2020        ret = component_add(&pdev->dev, &hdmi_component_ops);
2021        if (ret)
2022                goto err_unregister_audio;
2023
2024        return ret;
2025
2026err_unregister_audio:
2027        platform_device_unregister(hdata->audio.pdev);
2028
2029err_notifier_put:
2030        cec_notifier_put(hdata->notifier);
2031        pm_runtime_disable(dev);
2032
2033err_hdmiphy:
2034        if (hdata->hdmiphy_port)
2035                put_device(&hdata->hdmiphy_port->dev);
2036        if (hdata->regs_hdmiphy)
2037                iounmap(hdata->regs_hdmiphy);
2038err_ddc:
2039        put_device(&hdata->ddc_adpt->dev);
2040
2041        return ret;
2042}
2043
2044static int hdmi_remove(struct platform_device *pdev)
2045{
2046        struct hdmi_context *hdata = platform_get_drvdata(pdev);
2047
2048        cancel_delayed_work_sync(&hdata->hotplug_work);
2049        cec_notifier_set_phys_addr(hdata->notifier, CEC_PHYS_ADDR_INVALID);
2050
2051        component_del(&pdev->dev, &hdmi_component_ops);
2052        platform_device_unregister(hdata->audio.pdev);
2053
2054        cec_notifier_put(hdata->notifier);
2055        pm_runtime_disable(&pdev->dev);
2056
2057        if (!IS_ERR(hdata->reg_hdmi_en))
2058                regulator_disable(hdata->reg_hdmi_en);
2059
2060        if (hdata->hdmiphy_port)
2061                put_device(&hdata->hdmiphy_port->dev);
2062
2063        if (hdata->regs_hdmiphy)
2064                iounmap(hdata->regs_hdmiphy);
2065
2066        put_device(&hdata->ddc_adpt->dev);
2067
2068        mutex_destroy(&hdata->mutex);
2069
2070        return 0;
2071}
2072
2073static int __maybe_unused exynos_hdmi_suspend(struct device *dev)
2074{
2075        struct hdmi_context *hdata = dev_get_drvdata(dev);
2076
2077        hdmi_clk_disable_gates(hdata);
2078
2079        return 0;
2080}
2081
2082static int __maybe_unused exynos_hdmi_resume(struct device *dev)
2083{
2084        struct hdmi_context *hdata = dev_get_drvdata(dev);
2085        int ret;
2086
2087        ret = hdmi_clk_enable_gates(hdata);
2088        if (ret < 0)
2089                return ret;
2090
2091        return 0;
2092}
2093
2094static const struct dev_pm_ops exynos_hdmi_pm_ops = {
2095        SET_RUNTIME_PM_OPS(exynos_hdmi_suspend, exynos_hdmi_resume, NULL)
2096        SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
2097                                pm_runtime_force_resume)
2098};
2099
2100struct platform_driver hdmi_driver = {
2101        .probe          = hdmi_probe,
2102        .remove         = hdmi_remove,
2103        .driver         = {
2104                .name   = "exynos-hdmi",
2105                .owner  = THIS_MODULE,
2106                .pm     = &exynos_hdmi_pm_ops,
2107                .of_match_table = hdmi_match_types,
2108        },
2109};
2110