linux/drivers/video/fbdev/omap2/dss/hdmi_common.c
<<
>>
Prefs
   1
   2/*
   3 * Logic for the below structure :
   4 * user enters the CEA or VESA timings by specifying the HDMI/DVI code.
   5 * There is a correspondence between CEA/VESA timing and code, please
   6 * refer to section 6.3 in HDMI 1.3 specification for timing code.
   7 *
   8 * In the below structure, cea_vesa_timings corresponds to all OMAP4
   9 * supported CEA and VESA timing values.code_cea corresponds to the CEA
  10 * code, It is used to get the timing from cea_vesa_timing array.Similarly
  11 * with code_vesa. Code_index is used for back mapping, that is once EDID
  12 * is read from the TV, EDID is parsed to find the timing values and then
  13 * map it to corresponding CEA or VESA index.
  14 */
  15
  16#define DSS_SUBSYS_NAME "HDMI"
  17
  18#include <linux/kernel.h>
  19#include <linux/err.h>
  20#include <linux/of.h>
  21#include <video/omapdss.h>
  22
  23#include "hdmi.h"
  24
  25static const struct hdmi_config cea_timings[] = {
  26        {
  27                { 640, 480, 25200000, 96, 16, 48, 2, 10, 33,
  28                        OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
  29                        false, },
  30                { 1, HDMI_HDMI },
  31        },
  32        {
  33                { 720, 480, 27027000, 62, 16, 60, 6, 9, 30,
  34                        OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
  35                        false, },
  36                { 2, HDMI_HDMI },
  37        },
  38        {
  39                { 1280, 720, 74250000, 40, 110, 220, 5, 5, 20,
  40                        OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
  41                        false, },
  42                { 4, HDMI_HDMI },
  43        },
  44        {
  45                { 1920, 540, 74250000, 44, 88, 148, 5, 2, 15,
  46                        OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
  47                        true, },
  48                { 5, HDMI_HDMI },
  49        },
  50        {
  51                { 1440, 240, 27027000, 124, 38, 114, 3, 4, 15,
  52                        OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
  53                        true, },
  54                { 6, HDMI_HDMI },
  55        },
  56        {
  57                { 1920, 1080, 148500000, 44, 88, 148, 5, 4, 36,
  58                        OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
  59                        false, },
  60                { 16, HDMI_HDMI },
  61        },
  62        {
  63                { 720, 576, 27000000, 64, 12, 68, 5, 5, 39,
  64                        OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
  65                        false, },
  66                { 17, HDMI_HDMI },
  67        },
  68        {
  69                { 1280, 720, 74250000, 40, 440, 220, 5, 5, 20,
  70                        OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
  71                        false, },
  72                { 19, HDMI_HDMI },
  73        },
  74        {
  75                { 1920, 540, 74250000, 44, 528, 148, 5, 2, 15,
  76                        OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
  77                        true, },
  78                { 20, HDMI_HDMI },
  79        },
  80        {
  81                { 1440, 288, 27000000, 126, 24, 138, 3, 2, 19,
  82                        OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
  83                        true, },
  84                { 21, HDMI_HDMI },
  85        },
  86        {
  87                { 1440, 576, 54000000, 128, 24, 136, 5, 5, 39,
  88                        OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
  89                        false, },
  90                { 29, HDMI_HDMI },
  91        },
  92        {
  93                { 1920, 1080, 148500000, 44, 528, 148, 5, 4, 36,
  94                        OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
  95                        false, },
  96                { 31, HDMI_HDMI },
  97        },
  98        {
  99                { 1920, 1080, 74250000, 44, 638, 148, 5, 4, 36,
 100                        OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
 101                        false, },
 102                { 32, HDMI_HDMI },
 103        },
 104        {
 105                { 2880, 480, 108108000, 248, 64, 240, 6, 9, 30,
 106                        OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
 107                        false, },
 108                { 35, HDMI_HDMI },
 109        },
 110        {
 111                { 2880, 576, 108000000, 256, 48, 272, 5, 5, 39,
 112                        OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
 113                        false, },
 114                { 37, HDMI_HDMI },
 115        },
 116};
 117
 118static const struct hdmi_config vesa_timings[] = {
 119/* VESA From Here */
 120        {
 121                { 640, 480, 25175000, 96, 16, 48, 2, 11, 31,
 122                        OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
 123                        false, },
 124                { 4, HDMI_DVI },
 125        },
 126        {
 127                { 800, 600, 40000000, 128, 40, 88, 4, 1, 23,
 128                        OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
 129                        false, },
 130                { 9, HDMI_DVI },
 131        },
 132        {
 133                { 848, 480, 33750000, 112, 16, 112, 8, 6, 23,
 134                        OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
 135                        false, },
 136                { 0xE, HDMI_DVI },
 137        },
 138        {
 139                { 1280, 768, 79500000, 128, 64, 192, 7, 3, 20,
 140                        OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
 141                        false, },
 142                { 0x17, HDMI_DVI },
 143        },
 144        {
 145                { 1280, 800, 83500000, 128, 72, 200, 6, 3, 22,
 146                        OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
 147                        false, },
 148                { 0x1C, HDMI_DVI },
 149        },
 150        {
 151                { 1360, 768, 85500000, 112, 64, 256, 6, 3, 18,
 152                        OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
 153                        false, },
 154                { 0x27, HDMI_DVI },
 155        },
 156        {
 157                { 1280, 960, 108000000, 112, 96, 312, 3, 1, 36,
 158                        OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
 159                        false, },
 160                { 0x20, HDMI_DVI },
 161        },
 162        {
 163                { 1280, 1024, 108000000, 112, 48, 248, 3, 1, 38,
 164                        OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
 165                        false, },
 166                { 0x23, HDMI_DVI },
 167        },
 168        {
 169                { 1024, 768, 65000000, 136, 24, 160, 6, 3, 29,
 170                        OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
 171                        false, },
 172                { 0x10, HDMI_DVI },
 173        },
 174        {
 175                { 1400, 1050, 121750000, 144, 88, 232, 4, 3, 32,
 176                        OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
 177                        false, },
 178                { 0x2A, HDMI_DVI },
 179        },
 180        {
 181                { 1440, 900, 106500000, 152, 80, 232, 6, 3, 25,
 182                        OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
 183                        false, },
 184                { 0x2F, HDMI_DVI },
 185        },
 186        {
 187                { 1680, 1050, 146250000, 176 , 104, 280, 6, 3, 30,
 188                        OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
 189                        false, },
 190                { 0x3A, HDMI_DVI },
 191        },
 192        {
 193                { 1366, 768, 85500000, 143, 70, 213, 3, 3, 24,
 194                        OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
 195                        false, },
 196                { 0x51, HDMI_DVI },
 197        },
 198        {
 199                { 1920, 1080, 148500000, 44, 148, 80, 5, 4, 36,
 200                        OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
 201                        false, },
 202                { 0x52, HDMI_DVI },
 203        },
 204        {
 205                { 1280, 768, 68250000, 32, 48, 80, 7, 3, 12,
 206                        OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
 207                        false, },
 208                { 0x16, HDMI_DVI },
 209        },
 210        {
 211                { 1400, 1050, 101000000, 32, 48, 80, 4, 3, 23,
 212                        OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
 213                        false, },
 214                { 0x29, HDMI_DVI },
 215        },
 216        {
 217                { 1680, 1050, 119000000, 32, 48, 80, 6, 3, 21,
 218                        OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
 219                        false, },
 220                { 0x39, HDMI_DVI },
 221        },
 222        {
 223                { 1280, 800, 79500000, 32, 48, 80, 6, 3, 14,
 224                        OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
 225                        false, },
 226                { 0x1B, HDMI_DVI },
 227        },
 228        {
 229                { 1280, 720, 74250000, 40, 110, 220, 5, 5, 20,
 230                        OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
 231                        false, },
 232                { 0x55, HDMI_DVI },
 233        },
 234        {
 235                { 1920, 1200, 154000000, 32, 48, 80, 6, 3, 26,
 236                        OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
 237                        false, },
 238                { 0x44, HDMI_DVI },
 239        },
 240};
 241
 242const struct hdmi_config *hdmi_default_timing(void)
 243{
 244        return &vesa_timings[0];
 245}
 246
 247static const struct hdmi_config *hdmi_find_timing(int code,
 248                        const struct hdmi_config *timings_arr, int len)
 249{
 250        int i;
 251
 252        for (i = 0; i < len; i++) {
 253                if (timings_arr[i].cm.code == code)
 254                        return &timings_arr[i];
 255        }
 256
 257        return NULL;
 258}
 259
 260const struct hdmi_config *hdmi_get_timings(int mode, int code)
 261{
 262        const struct hdmi_config *arr;
 263        int len;
 264
 265        if (mode == HDMI_DVI) {
 266                arr = vesa_timings;
 267                len = ARRAY_SIZE(vesa_timings);
 268        } else {
 269                arr = cea_timings;
 270                len = ARRAY_SIZE(cea_timings);
 271        }
 272
 273        return hdmi_find_timing(code, arr, len);
 274}
 275
 276static bool hdmi_timings_compare(struct omap_video_timings *timing1,
 277                        const struct omap_video_timings *timing2)
 278{
 279        int timing1_vsync, timing1_hsync, timing2_vsync, timing2_hsync;
 280
 281        if ((DIV_ROUND_CLOSEST(timing2->pixelclock, 1000000) ==
 282                        DIV_ROUND_CLOSEST(timing1->pixelclock, 1000000)) &&
 283                (timing2->x_res == timing1->x_res) &&
 284                (timing2->y_res == timing1->y_res)) {
 285
 286                timing2_hsync = timing2->hfp + timing2->hsw + timing2->hbp;
 287                timing1_hsync = timing1->hfp + timing1->hsw + timing1->hbp;
 288                timing2_vsync = timing2->vfp + timing2->vsw + timing2->vbp;
 289                timing1_vsync = timing1->vfp + timing1->vsw + timing1->vbp;
 290
 291                DSSDBG("timing1_hsync = %d timing1_vsync = %d"\
 292                        "timing2_hsync = %d timing2_vsync = %d\n",
 293                        timing1_hsync, timing1_vsync,
 294                        timing2_hsync, timing2_vsync);
 295
 296                if ((timing1_hsync == timing2_hsync) &&
 297                        (timing1_vsync == timing2_vsync)) {
 298                        return true;
 299                }
 300        }
 301        return false;
 302}
 303
 304struct hdmi_cm hdmi_get_code(struct omap_video_timings *timing)
 305{
 306        int i;
 307        struct hdmi_cm cm = {-1};
 308        DSSDBG("hdmi_get_code\n");
 309
 310        for (i = 0; i < ARRAY_SIZE(cea_timings); i++) {
 311                if (hdmi_timings_compare(timing, &cea_timings[i].timings)) {
 312                        cm = cea_timings[i].cm;
 313                        goto end;
 314                }
 315        }
 316        for (i = 0; i < ARRAY_SIZE(vesa_timings); i++) {
 317                if (hdmi_timings_compare(timing, &vesa_timings[i].timings)) {
 318                        cm = vesa_timings[i].cm;
 319                        goto end;
 320                }
 321        }
 322
 323end:
 324        return cm;
 325}
 326
 327int hdmi_parse_lanes_of(struct platform_device *pdev, struct device_node *ep,
 328        struct hdmi_phy_data *phy)
 329{
 330        struct property *prop;
 331        int r, len;
 332
 333        prop = of_find_property(ep, "lanes", &len);
 334        if (prop) {
 335                u32 lanes[8];
 336
 337                if (len / sizeof(u32) != ARRAY_SIZE(lanes)) {
 338                        dev_err(&pdev->dev, "bad number of lanes\n");
 339                        return -EINVAL;
 340                }
 341
 342                r = of_property_read_u32_array(ep, "lanes", lanes,
 343                        ARRAY_SIZE(lanes));
 344                if (r) {
 345                        dev_err(&pdev->dev, "failed to read lane data\n");
 346                        return r;
 347                }
 348
 349                r = hdmi_phy_parse_lanes(phy, lanes);
 350                if (r) {
 351                        dev_err(&pdev->dev, "failed to parse lane data\n");
 352                        return r;
 353                }
 354        } else {
 355                static const u32 default_lanes[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
 356
 357                r = hdmi_phy_parse_lanes(phy, default_lanes);
 358                if (WARN_ON(r)) {
 359                        dev_err(&pdev->dev, "failed to parse lane data\n");
 360                        return r;
 361                }
 362        }
 363
 364        return 0;
 365}
 366
 367#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
 368int hdmi_compute_acr(u32 pclk, u32 sample_freq, u32 *n, u32 *cts)
 369{
 370        u32 deep_color;
 371        bool deep_color_correct = false;
 372
 373        if (n == NULL || cts == NULL)
 374                return -EINVAL;
 375
 376        /* TODO: When implemented, query deep color mode here. */
 377        deep_color = 100;
 378
 379        /*
 380         * When using deep color, the default N value (as in the HDMI
 381         * specification) yields to an non-integer CTS. Hence, we
 382         * modify it while keeping the restrictions described in
 383         * section 7.2.1 of the HDMI 1.4a specification.
 384         */
 385        switch (sample_freq) {
 386        case 32000:
 387        case 48000:
 388        case 96000:
 389        case 192000:
 390                if (deep_color == 125)
 391                        if (pclk == 27027000 || pclk == 74250000)
 392                                deep_color_correct = true;
 393                if (deep_color == 150)
 394                        if (pclk == 27027000)
 395                                deep_color_correct = true;
 396                break;
 397        case 44100:
 398        case 88200:
 399        case 176400:
 400                if (deep_color == 125)
 401                        if (pclk == 27027000)
 402                                deep_color_correct = true;
 403                break;
 404        default:
 405                return -EINVAL;
 406        }
 407
 408        if (deep_color_correct) {
 409                switch (sample_freq) {
 410                case 32000:
 411                        *n = 8192;
 412                        break;
 413                case 44100:
 414                        *n = 12544;
 415                        break;
 416                case 48000:
 417                        *n = 8192;
 418                        break;
 419                case 88200:
 420                        *n = 25088;
 421                        break;
 422                case 96000:
 423                        *n = 16384;
 424                        break;
 425                case 176400:
 426                        *n = 50176;
 427                        break;
 428                case 192000:
 429                        *n = 32768;
 430                        break;
 431                default:
 432                        return -EINVAL;
 433                }
 434        } else {
 435                switch (sample_freq) {
 436                case 32000:
 437                        *n = 4096;
 438                        break;
 439                case 44100:
 440                        *n = 6272;
 441                        break;
 442                case 48000:
 443                        *n = 6144;
 444                        break;
 445                case 88200:
 446                        *n = 12544;
 447                        break;
 448                case 96000:
 449                        *n = 12288;
 450                        break;
 451                case 176400:
 452                        *n = 25088;
 453                        break;
 454                case 192000:
 455                        *n = 24576;
 456                        break;
 457                default:
 458                        return -EINVAL;
 459                }
 460        }
 461        /* Calculate CTS. See HDMI 1.3a or 1.4a specifications */
 462        *cts = (pclk/1000) * (*n / 128) * deep_color / (sample_freq / 10);
 463
 464        return 0;
 465}
 466#endif
 467