linux/drivers/media/v4l2-core/v4l2-dv-timings.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * v4l2-dv-timings - dv-timings helper functions
   4 *
   5 * Copyright 2013 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
   6 */
   7
   8#include <linux/module.h>
   9#include <linux/types.h>
  10#include <linux/kernel.h>
  11#include <linux/errno.h>
  12#include <linux/rational.h>
  13#include <linux/videodev2.h>
  14#include <linux/v4l2-dv-timings.h>
  15#include <media/v4l2-dv-timings.h>
  16#include <linux/math64.h>
  17#include <linux/hdmi.h>
  18#include <media/cec.h>
  19
  20MODULE_AUTHOR("Hans Verkuil");
  21MODULE_DESCRIPTION("V4L2 DV Timings Helper Functions");
  22MODULE_LICENSE("GPL");
  23
  24const struct v4l2_dv_timings v4l2_dv_timings_presets[] = {
  25        V4L2_DV_BT_CEA_640X480P59_94,
  26        V4L2_DV_BT_CEA_720X480I59_94,
  27        V4L2_DV_BT_CEA_720X480P59_94,
  28        V4L2_DV_BT_CEA_720X576I50,
  29        V4L2_DV_BT_CEA_720X576P50,
  30        V4L2_DV_BT_CEA_1280X720P24,
  31        V4L2_DV_BT_CEA_1280X720P25,
  32        V4L2_DV_BT_CEA_1280X720P30,
  33        V4L2_DV_BT_CEA_1280X720P50,
  34        V4L2_DV_BT_CEA_1280X720P60,
  35        V4L2_DV_BT_CEA_1920X1080P24,
  36        V4L2_DV_BT_CEA_1920X1080P25,
  37        V4L2_DV_BT_CEA_1920X1080P30,
  38        V4L2_DV_BT_CEA_1920X1080I50,
  39        V4L2_DV_BT_CEA_1920X1080P50,
  40        V4L2_DV_BT_CEA_1920X1080I60,
  41        V4L2_DV_BT_CEA_1920X1080P60,
  42        V4L2_DV_BT_DMT_640X350P85,
  43        V4L2_DV_BT_DMT_640X400P85,
  44        V4L2_DV_BT_DMT_720X400P85,
  45        V4L2_DV_BT_DMT_640X480P72,
  46        V4L2_DV_BT_DMT_640X480P75,
  47        V4L2_DV_BT_DMT_640X480P85,
  48        V4L2_DV_BT_DMT_800X600P56,
  49        V4L2_DV_BT_DMT_800X600P60,
  50        V4L2_DV_BT_DMT_800X600P72,
  51        V4L2_DV_BT_DMT_800X600P75,
  52        V4L2_DV_BT_DMT_800X600P85,
  53        V4L2_DV_BT_DMT_800X600P120_RB,
  54        V4L2_DV_BT_DMT_848X480P60,
  55        V4L2_DV_BT_DMT_1024X768I43,
  56        V4L2_DV_BT_DMT_1024X768P60,
  57        V4L2_DV_BT_DMT_1024X768P70,
  58        V4L2_DV_BT_DMT_1024X768P75,
  59        V4L2_DV_BT_DMT_1024X768P85,
  60        V4L2_DV_BT_DMT_1024X768P120_RB,
  61        V4L2_DV_BT_DMT_1152X864P75,
  62        V4L2_DV_BT_DMT_1280X768P60_RB,
  63        V4L2_DV_BT_DMT_1280X768P60,
  64        V4L2_DV_BT_DMT_1280X768P75,
  65        V4L2_DV_BT_DMT_1280X768P85,
  66        V4L2_DV_BT_DMT_1280X768P120_RB,
  67        V4L2_DV_BT_DMT_1280X800P60_RB,
  68        V4L2_DV_BT_DMT_1280X800P60,
  69        V4L2_DV_BT_DMT_1280X800P75,
  70        V4L2_DV_BT_DMT_1280X800P85,
  71        V4L2_DV_BT_DMT_1280X800P120_RB,
  72        V4L2_DV_BT_DMT_1280X960P60,
  73        V4L2_DV_BT_DMT_1280X960P85,
  74        V4L2_DV_BT_DMT_1280X960P120_RB,
  75        V4L2_DV_BT_DMT_1280X1024P60,
  76        V4L2_DV_BT_DMT_1280X1024P75,
  77        V4L2_DV_BT_DMT_1280X1024P85,
  78        V4L2_DV_BT_DMT_1280X1024P120_RB,
  79        V4L2_DV_BT_DMT_1360X768P60,
  80        V4L2_DV_BT_DMT_1360X768P120_RB,
  81        V4L2_DV_BT_DMT_1366X768P60,
  82        V4L2_DV_BT_DMT_1366X768P60_RB,
  83        V4L2_DV_BT_DMT_1400X1050P60_RB,
  84        V4L2_DV_BT_DMT_1400X1050P60,
  85        V4L2_DV_BT_DMT_1400X1050P75,
  86        V4L2_DV_BT_DMT_1400X1050P85,
  87        V4L2_DV_BT_DMT_1400X1050P120_RB,
  88        V4L2_DV_BT_DMT_1440X900P60_RB,
  89        V4L2_DV_BT_DMT_1440X900P60,
  90        V4L2_DV_BT_DMT_1440X900P75,
  91        V4L2_DV_BT_DMT_1440X900P85,
  92        V4L2_DV_BT_DMT_1440X900P120_RB,
  93        V4L2_DV_BT_DMT_1600X900P60_RB,
  94        V4L2_DV_BT_DMT_1600X1200P60,
  95        V4L2_DV_BT_DMT_1600X1200P65,
  96        V4L2_DV_BT_DMT_1600X1200P70,
  97        V4L2_DV_BT_DMT_1600X1200P75,
  98        V4L2_DV_BT_DMT_1600X1200P85,
  99        V4L2_DV_BT_DMT_1600X1200P120_RB,
 100        V4L2_DV_BT_DMT_1680X1050P60_RB,
 101        V4L2_DV_BT_DMT_1680X1050P60,
 102        V4L2_DV_BT_DMT_1680X1050P75,
 103        V4L2_DV_BT_DMT_1680X1050P85,
 104        V4L2_DV_BT_DMT_1680X1050P120_RB,
 105        V4L2_DV_BT_DMT_1792X1344P60,
 106        V4L2_DV_BT_DMT_1792X1344P75,
 107        V4L2_DV_BT_DMT_1792X1344P120_RB,
 108        V4L2_DV_BT_DMT_1856X1392P60,
 109        V4L2_DV_BT_DMT_1856X1392P75,
 110        V4L2_DV_BT_DMT_1856X1392P120_RB,
 111        V4L2_DV_BT_DMT_1920X1200P60_RB,
 112        V4L2_DV_BT_DMT_1920X1200P60,
 113        V4L2_DV_BT_DMT_1920X1200P75,
 114        V4L2_DV_BT_DMT_1920X1200P85,
 115        V4L2_DV_BT_DMT_1920X1200P120_RB,
 116        V4L2_DV_BT_DMT_1920X1440P60,
 117        V4L2_DV_BT_DMT_1920X1440P75,
 118        V4L2_DV_BT_DMT_1920X1440P120_RB,
 119        V4L2_DV_BT_DMT_2048X1152P60_RB,
 120        V4L2_DV_BT_DMT_2560X1600P60_RB,
 121        V4L2_DV_BT_DMT_2560X1600P60,
 122        V4L2_DV_BT_DMT_2560X1600P75,
 123        V4L2_DV_BT_DMT_2560X1600P85,
 124        V4L2_DV_BT_DMT_2560X1600P120_RB,
 125        V4L2_DV_BT_CEA_3840X2160P24,
 126        V4L2_DV_BT_CEA_3840X2160P25,
 127        V4L2_DV_BT_CEA_3840X2160P30,
 128        V4L2_DV_BT_CEA_3840X2160P50,
 129        V4L2_DV_BT_CEA_3840X2160P60,
 130        V4L2_DV_BT_CEA_4096X2160P24,
 131        V4L2_DV_BT_CEA_4096X2160P25,
 132        V4L2_DV_BT_CEA_4096X2160P30,
 133        V4L2_DV_BT_CEA_4096X2160P50,
 134        V4L2_DV_BT_DMT_4096X2160P59_94_RB,
 135        V4L2_DV_BT_CEA_4096X2160P60,
 136        { }
 137};
 138EXPORT_SYMBOL_GPL(v4l2_dv_timings_presets);
 139
 140bool v4l2_valid_dv_timings(const struct v4l2_dv_timings *t,
 141                           const struct v4l2_dv_timings_cap *dvcap,
 142                           v4l2_check_dv_timings_fnc fnc,
 143                           void *fnc_handle)
 144{
 145        const struct v4l2_bt_timings *bt = &t->bt;
 146        const struct v4l2_bt_timings_cap *cap = &dvcap->bt;
 147        u32 caps = cap->capabilities;
 148
 149        if (t->type != V4L2_DV_BT_656_1120)
 150                return false;
 151        if (t->type != dvcap->type ||
 152            bt->height < cap->min_height ||
 153            bt->height > cap->max_height ||
 154            bt->width < cap->min_width ||
 155            bt->width > cap->max_width ||
 156            bt->pixelclock < cap->min_pixelclock ||
 157            bt->pixelclock > cap->max_pixelclock ||
 158            (!(caps & V4L2_DV_BT_CAP_CUSTOM) &&
 159             cap->standards && bt->standards &&
 160             !(bt->standards & cap->standards)) ||
 161            (bt->interlaced && !(caps & V4L2_DV_BT_CAP_INTERLACED)) ||
 162            (!bt->interlaced && !(caps & V4L2_DV_BT_CAP_PROGRESSIVE)))
 163                return false;
 164        return fnc == NULL || fnc(t, fnc_handle);
 165}
 166EXPORT_SYMBOL_GPL(v4l2_valid_dv_timings);
 167
 168int v4l2_enum_dv_timings_cap(struct v4l2_enum_dv_timings *t,
 169                             const struct v4l2_dv_timings_cap *cap,
 170                             v4l2_check_dv_timings_fnc fnc,
 171                             void *fnc_handle)
 172{
 173        u32 i, idx;
 174
 175        memset(t->reserved, 0, sizeof(t->reserved));
 176        for (i = idx = 0; v4l2_dv_timings_presets[i].bt.width; i++) {
 177                if (v4l2_valid_dv_timings(v4l2_dv_timings_presets + i, cap,
 178                                          fnc, fnc_handle) &&
 179                    idx++ == t->index) {
 180                        t->timings = v4l2_dv_timings_presets[i];
 181                        return 0;
 182                }
 183        }
 184        return -EINVAL;
 185}
 186EXPORT_SYMBOL_GPL(v4l2_enum_dv_timings_cap);
 187
 188bool v4l2_find_dv_timings_cap(struct v4l2_dv_timings *t,
 189                              const struct v4l2_dv_timings_cap *cap,
 190                              unsigned pclock_delta,
 191                              v4l2_check_dv_timings_fnc fnc,
 192                              void *fnc_handle)
 193{
 194        int i;
 195
 196        if (!v4l2_valid_dv_timings(t, cap, fnc, fnc_handle))
 197                return false;
 198
 199        for (i = 0; i < v4l2_dv_timings_presets[i].bt.width; i++) {
 200                if (v4l2_valid_dv_timings(v4l2_dv_timings_presets + i, cap,
 201                                          fnc, fnc_handle) &&
 202                    v4l2_match_dv_timings(t, v4l2_dv_timings_presets + i,
 203                                          pclock_delta, false)) {
 204                        u32 flags = t->bt.flags & V4L2_DV_FL_REDUCED_FPS;
 205
 206                        *t = v4l2_dv_timings_presets[i];
 207                        if (can_reduce_fps(&t->bt))
 208                                t->bt.flags |= flags;
 209
 210                        return true;
 211                }
 212        }
 213        return false;
 214}
 215EXPORT_SYMBOL_GPL(v4l2_find_dv_timings_cap);
 216
 217bool v4l2_find_dv_timings_cea861_vic(struct v4l2_dv_timings *t, u8 vic)
 218{
 219        unsigned int i;
 220
 221        for (i = 0; i < v4l2_dv_timings_presets[i].bt.width; i++) {
 222                const struct v4l2_bt_timings *bt =
 223                        &v4l2_dv_timings_presets[i].bt;
 224
 225                if ((bt->flags & V4L2_DV_FL_HAS_CEA861_VIC) &&
 226                    bt->cea861_vic == vic) {
 227                        *t = v4l2_dv_timings_presets[i];
 228                        return true;
 229                }
 230        }
 231        return false;
 232}
 233EXPORT_SYMBOL_GPL(v4l2_find_dv_timings_cea861_vic);
 234
 235/**
 236 * v4l2_match_dv_timings - check if two timings match
 237 * @t1: compare this v4l2_dv_timings struct...
 238 * @t2: with this struct.
 239 * @pclock_delta: the allowed pixelclock deviation.
 240 * @match_reduced_fps: if true, then fail if V4L2_DV_FL_REDUCED_FPS does not
 241 *      match.
 242 *
 243 * Compare t1 with t2 with a given margin of error for the pixelclock.
 244 */
 245bool v4l2_match_dv_timings(const struct v4l2_dv_timings *t1,
 246                           const struct v4l2_dv_timings *t2,
 247                           unsigned pclock_delta, bool match_reduced_fps)
 248{
 249        if (t1->type != t2->type || t1->type != V4L2_DV_BT_656_1120)
 250                return false;
 251        if (t1->bt.width == t2->bt.width &&
 252            t1->bt.height == t2->bt.height &&
 253            t1->bt.interlaced == t2->bt.interlaced &&
 254            t1->bt.polarities == t2->bt.polarities &&
 255            t1->bt.pixelclock >= t2->bt.pixelclock - pclock_delta &&
 256            t1->bt.pixelclock <= t2->bt.pixelclock + pclock_delta &&
 257            t1->bt.hfrontporch == t2->bt.hfrontporch &&
 258            t1->bt.hsync == t2->bt.hsync &&
 259            t1->bt.hbackporch == t2->bt.hbackporch &&
 260            t1->bt.vfrontporch == t2->bt.vfrontporch &&
 261            t1->bt.vsync == t2->bt.vsync &&
 262            t1->bt.vbackporch == t2->bt.vbackporch &&
 263            (!match_reduced_fps ||
 264             (t1->bt.flags & V4L2_DV_FL_REDUCED_FPS) ==
 265                (t2->bt.flags & V4L2_DV_FL_REDUCED_FPS)) &&
 266            (!t1->bt.interlaced ||
 267                (t1->bt.il_vfrontporch == t2->bt.il_vfrontporch &&
 268                 t1->bt.il_vsync == t2->bt.il_vsync &&
 269                 t1->bt.il_vbackporch == t2->bt.il_vbackporch)))
 270                return true;
 271        return false;
 272}
 273EXPORT_SYMBOL_GPL(v4l2_match_dv_timings);
 274
 275void v4l2_print_dv_timings(const char *dev_prefix, const char *prefix,
 276                           const struct v4l2_dv_timings *t, bool detailed)
 277{
 278        const struct v4l2_bt_timings *bt = &t->bt;
 279        u32 htot, vtot;
 280        u32 fps;
 281
 282        if (t->type != V4L2_DV_BT_656_1120)
 283                return;
 284
 285        htot = V4L2_DV_BT_FRAME_WIDTH(bt);
 286        vtot = V4L2_DV_BT_FRAME_HEIGHT(bt);
 287        if (bt->interlaced)
 288                vtot /= 2;
 289
 290        fps = (htot * vtot) > 0 ? div_u64((100 * (u64)bt->pixelclock),
 291                                  (htot * vtot)) : 0;
 292
 293        if (prefix == NULL)
 294                prefix = "";
 295
 296        pr_info("%s: %s%ux%u%s%u.%u (%ux%u)\n", dev_prefix, prefix,
 297                bt->width, bt->height, bt->interlaced ? "i" : "p",
 298                fps / 100, fps % 100, htot, vtot);
 299
 300        if (!detailed)
 301                return;
 302
 303        pr_info("%s: horizontal: fp = %u, %ssync = %u, bp = %u\n",
 304                        dev_prefix, bt->hfrontporch,
 305                        (bt->polarities & V4L2_DV_HSYNC_POS_POL) ? "+" : "-",
 306                        bt->hsync, bt->hbackporch);
 307        pr_info("%s: vertical: fp = %u, %ssync = %u, bp = %u\n",
 308                        dev_prefix, bt->vfrontporch,
 309                        (bt->polarities & V4L2_DV_VSYNC_POS_POL) ? "+" : "-",
 310                        bt->vsync, bt->vbackporch);
 311        if (bt->interlaced)
 312                pr_info("%s: vertical bottom field: fp = %u, %ssync = %u, bp = %u\n",
 313                        dev_prefix, bt->il_vfrontporch,
 314                        (bt->polarities & V4L2_DV_VSYNC_POS_POL) ? "+" : "-",
 315                        bt->il_vsync, bt->il_vbackporch);
 316        pr_info("%s: pixelclock: %llu\n", dev_prefix, bt->pixelclock);
 317        pr_info("%s: flags (0x%x):%s%s%s%s%s%s%s%s%s%s\n",
 318                        dev_prefix, bt->flags,
 319                        (bt->flags & V4L2_DV_FL_REDUCED_BLANKING) ?
 320                        " REDUCED_BLANKING" : "",
 321                        ((bt->flags & V4L2_DV_FL_REDUCED_BLANKING) &&
 322                         bt->vsync == 8) ? " (V2)" : "",
 323                        (bt->flags & V4L2_DV_FL_CAN_REDUCE_FPS) ?
 324                        " CAN_REDUCE_FPS" : "",
 325                        (bt->flags & V4L2_DV_FL_REDUCED_FPS) ?
 326                        " REDUCED_FPS" : "",
 327                        (bt->flags & V4L2_DV_FL_HALF_LINE) ?
 328                        " HALF_LINE" : "",
 329                        (bt->flags & V4L2_DV_FL_IS_CE_VIDEO) ?
 330                        " CE_VIDEO" : "",
 331                        (bt->flags & V4L2_DV_FL_FIRST_FIELD_EXTRA_LINE) ?
 332                        " FIRST_FIELD_EXTRA_LINE" : "",
 333                        (bt->flags & V4L2_DV_FL_HAS_PICTURE_ASPECT) ?
 334                        " HAS_PICTURE_ASPECT" : "",
 335                        (bt->flags & V4L2_DV_FL_HAS_CEA861_VIC) ?
 336                        " HAS_CEA861_VIC" : "",
 337                        (bt->flags & V4L2_DV_FL_HAS_HDMI_VIC) ?
 338                        " HAS_HDMI_VIC" : "");
 339        pr_info("%s: standards (0x%x):%s%s%s%s%s\n", dev_prefix, bt->standards,
 340                        (bt->standards & V4L2_DV_BT_STD_CEA861) ?  " CEA" : "",
 341                        (bt->standards & V4L2_DV_BT_STD_DMT) ?  " DMT" : "",
 342                        (bt->standards & V4L2_DV_BT_STD_CVT) ?  " CVT" : "",
 343                        (bt->standards & V4L2_DV_BT_STD_GTF) ?  " GTF" : "",
 344                        (bt->standards & V4L2_DV_BT_STD_SDI) ?  " SDI" : "");
 345        if (bt->flags & V4L2_DV_FL_HAS_PICTURE_ASPECT)
 346                pr_info("%s: picture aspect (hor:vert): %u:%u\n", dev_prefix,
 347                        bt->picture_aspect.numerator,
 348                        bt->picture_aspect.denominator);
 349        if (bt->flags & V4L2_DV_FL_HAS_CEA861_VIC)
 350                pr_info("%s: CEA-861 VIC: %u\n", dev_prefix, bt->cea861_vic);
 351        if (bt->flags & V4L2_DV_FL_HAS_HDMI_VIC)
 352                pr_info("%s: HDMI VIC: %u\n", dev_prefix, bt->hdmi_vic);
 353}
 354EXPORT_SYMBOL_GPL(v4l2_print_dv_timings);
 355
 356struct v4l2_fract v4l2_dv_timings_aspect_ratio(const struct v4l2_dv_timings *t)
 357{
 358        struct v4l2_fract ratio = { 1, 1 };
 359        unsigned long n, d;
 360
 361        if (t->type != V4L2_DV_BT_656_1120)
 362                return ratio;
 363        if (!(t->bt.flags & V4L2_DV_FL_HAS_PICTURE_ASPECT))
 364                return ratio;
 365
 366        ratio.numerator = t->bt.width * t->bt.picture_aspect.denominator;
 367        ratio.denominator = t->bt.height * t->bt.picture_aspect.numerator;
 368
 369        rational_best_approximation(ratio.numerator, ratio.denominator,
 370                                    ratio.numerator, ratio.denominator, &n, &d);
 371        ratio.numerator = n;
 372        ratio.denominator = d;
 373        return ratio;
 374}
 375EXPORT_SYMBOL_GPL(v4l2_dv_timings_aspect_ratio);
 376
 377/** v4l2_calc_timeperframe - helper function to calculate timeperframe based
 378 *      v4l2_dv_timings fields.
 379 * @t - Timings for the video mode.
 380 *
 381 * Calculates the expected timeperframe using the pixel clock value and
 382 * horizontal/vertical measures. This means that v4l2_dv_timings structure
 383 * must be correctly and fully filled.
 384 */
 385struct v4l2_fract v4l2_calc_timeperframe(const struct v4l2_dv_timings *t)
 386{
 387        const struct v4l2_bt_timings *bt = &t->bt;
 388        struct v4l2_fract fps_fract = { 1, 1 };
 389        unsigned long n, d;
 390        u32 htot, vtot, fps;
 391        u64 pclk;
 392
 393        if (t->type != V4L2_DV_BT_656_1120)
 394                return fps_fract;
 395
 396        htot = V4L2_DV_BT_FRAME_WIDTH(bt);
 397        vtot = V4L2_DV_BT_FRAME_HEIGHT(bt);
 398        pclk = bt->pixelclock;
 399
 400        if ((bt->flags & V4L2_DV_FL_CAN_DETECT_REDUCED_FPS) &&
 401            (bt->flags & V4L2_DV_FL_REDUCED_FPS))
 402                pclk = div_u64(pclk * 1000ULL, 1001);
 403
 404        fps = (htot * vtot) > 0 ? div_u64((100 * pclk), (htot * vtot)) : 0;
 405        if (!fps)
 406                return fps_fract;
 407
 408        rational_best_approximation(fps, 100, fps, 100, &n, &d);
 409
 410        fps_fract.numerator = d;
 411        fps_fract.denominator = n;
 412        return fps_fract;
 413}
 414EXPORT_SYMBOL_GPL(v4l2_calc_timeperframe);
 415
 416/*
 417 * CVT defines
 418 * Based on Coordinated Video Timings Standard
 419 * version 1.1 September 10, 2003
 420 */
 421
 422#define CVT_PXL_CLK_GRAN        250000  /* pixel clock granularity */
 423#define CVT_PXL_CLK_GRAN_RB_V2 1000     /* granularity for reduced blanking v2*/
 424
 425/* Normal blanking */
 426#define CVT_MIN_V_BPORCH        7       /* lines */
 427#define CVT_MIN_V_PORCH_RND     3       /* lines */
 428#define CVT_MIN_VSYNC_BP        550     /* min time of vsync + back porch (us) */
 429#define CVT_HSYNC_PERCENT       8       /* nominal hsync as percentage of line */
 430
 431/* Normal blanking for CVT uses GTF to calculate horizontal blanking */
 432#define CVT_CELL_GRAN           8       /* character cell granularity */
 433#define CVT_M                   600     /* blanking formula gradient */
 434#define CVT_C                   40      /* blanking formula offset */
 435#define CVT_K                   128     /* blanking formula scaling factor */
 436#define CVT_J                   20      /* blanking formula scaling factor */
 437#define CVT_C_PRIME (((CVT_C - CVT_J) * CVT_K / 256) + CVT_J)
 438#define CVT_M_PRIME (CVT_K * CVT_M / 256)
 439
 440/* Reduced Blanking */
 441#define CVT_RB_MIN_V_BPORCH    7       /* lines  */
 442#define CVT_RB_V_FPORCH        3       /* lines  */
 443#define CVT_RB_MIN_V_BLANK   460       /* us     */
 444#define CVT_RB_H_SYNC         32       /* pixels */
 445#define CVT_RB_H_BLANK       160       /* pixels */
 446/* Reduce blanking Version 2 */
 447#define CVT_RB_V2_H_BLANK     80       /* pixels */
 448#define CVT_RB_MIN_V_FPORCH    3       /* lines  */
 449#define CVT_RB_V2_MIN_V_FPORCH 1       /* lines  */
 450#define CVT_RB_V_BPORCH        6       /* lines  */
 451
 452/** v4l2_detect_cvt - detect if the given timings follow the CVT standard
 453 * @frame_height - the total height of the frame (including blanking) in lines.
 454 * @hfreq - the horizontal frequency in Hz.
 455 * @vsync - the height of the vertical sync in lines.
 456 * @active_width - active width of image (does not include blanking). This
 457 * information is needed only in case of version 2 of reduced blanking.
 458 * In other cases, this parameter does not have any effect on timings.
 459 * @polarities - the horizontal and vertical polarities (same as struct
 460 *              v4l2_bt_timings polarities).
 461 * @interlaced - if this flag is true, it indicates interlaced format
 462 * @fmt - the resulting timings.
 463 *
 464 * This function will attempt to detect if the given values correspond to a
 465 * valid CVT format. If so, then it will return true, and fmt will be filled
 466 * in with the found CVT timings.
 467 */
 468bool v4l2_detect_cvt(unsigned frame_height,
 469                     unsigned hfreq,
 470                     unsigned vsync,
 471                     unsigned active_width,
 472                     u32 polarities,
 473                     bool interlaced,
 474                     struct v4l2_dv_timings *fmt)
 475{
 476        int  v_fp, v_bp, h_fp, h_bp, hsync;
 477        int  frame_width, image_height, image_width;
 478        bool reduced_blanking;
 479        bool rb_v2 = false;
 480        unsigned pix_clk;
 481
 482        if (vsync < 4 || vsync > 8)
 483                return false;
 484
 485        if (polarities == V4L2_DV_VSYNC_POS_POL)
 486                reduced_blanking = false;
 487        else if (polarities == V4L2_DV_HSYNC_POS_POL)
 488                reduced_blanking = true;
 489        else
 490                return false;
 491
 492        if (reduced_blanking && vsync == 8)
 493                rb_v2 = true;
 494
 495        if (rb_v2 && active_width == 0)
 496                return false;
 497
 498        if (!rb_v2 && vsync > 7)
 499                return false;
 500
 501        if (hfreq == 0)
 502                return false;
 503
 504        /* Vertical */
 505        if (reduced_blanking) {
 506                if (rb_v2) {
 507                        v_bp = CVT_RB_V_BPORCH;
 508                        v_fp = (CVT_RB_MIN_V_BLANK * hfreq) / 1000000 + 1;
 509                        v_fp -= vsync + v_bp;
 510
 511                        if (v_fp < CVT_RB_V2_MIN_V_FPORCH)
 512                                v_fp = CVT_RB_V2_MIN_V_FPORCH;
 513                } else {
 514                        v_fp = CVT_RB_V_FPORCH;
 515                        v_bp = (CVT_RB_MIN_V_BLANK * hfreq) / 1000000 + 1;
 516                        v_bp -= vsync + v_fp;
 517
 518                        if (v_bp < CVT_RB_MIN_V_BPORCH)
 519                                v_bp = CVT_RB_MIN_V_BPORCH;
 520                }
 521        } else {
 522                v_fp = CVT_MIN_V_PORCH_RND;
 523                v_bp = (CVT_MIN_VSYNC_BP * hfreq) / 1000000 + 1 - vsync;
 524
 525                if (v_bp < CVT_MIN_V_BPORCH)
 526                        v_bp = CVT_MIN_V_BPORCH;
 527        }
 528
 529        if (interlaced)
 530                image_height = (frame_height - 2 * v_fp - 2 * vsync - 2 * v_bp) & ~0x1;
 531        else
 532                image_height = (frame_height - v_fp - vsync - v_bp + 1) & ~0x1;
 533
 534        if (image_height < 0)
 535                return false;
 536
 537        /* Aspect ratio based on vsync */
 538        switch (vsync) {
 539        case 4:
 540                image_width = (image_height * 4) / 3;
 541                break;
 542        case 5:
 543                image_width = (image_height * 16) / 9;
 544                break;
 545        case 6:
 546                image_width = (image_height * 16) / 10;
 547                break;
 548        case 7:
 549                /* special case */
 550                if (image_height == 1024)
 551                        image_width = (image_height * 5) / 4;
 552                else if (image_height == 768)
 553                        image_width = (image_height * 15) / 9;
 554                else
 555                        return false;
 556                break;
 557        case 8:
 558                image_width = active_width;
 559                break;
 560        default:
 561                return false;
 562        }
 563
 564        if (!rb_v2)
 565                image_width = image_width & ~7;
 566
 567        /* Horizontal */
 568        if (reduced_blanking) {
 569                int h_blank;
 570                int clk_gran;
 571
 572                h_blank = rb_v2 ? CVT_RB_V2_H_BLANK : CVT_RB_H_BLANK;
 573                clk_gran = rb_v2 ? CVT_PXL_CLK_GRAN_RB_V2 : CVT_PXL_CLK_GRAN;
 574
 575                pix_clk = (image_width + h_blank) * hfreq;
 576                pix_clk = (pix_clk / clk_gran) * clk_gran;
 577
 578                h_bp  = h_blank / 2;
 579                hsync = CVT_RB_H_SYNC;
 580                h_fp  = h_blank - h_bp - hsync;
 581
 582                frame_width = image_width + h_blank;
 583        } else {
 584                unsigned ideal_duty_cycle_per_myriad =
 585                        100 * CVT_C_PRIME - (CVT_M_PRIME * 100000) / hfreq;
 586                int h_blank;
 587
 588                if (ideal_duty_cycle_per_myriad < 2000)
 589                        ideal_duty_cycle_per_myriad = 2000;
 590
 591                h_blank = image_width * ideal_duty_cycle_per_myriad /
 592                                        (10000 - ideal_duty_cycle_per_myriad);
 593                h_blank = (h_blank / (2 * CVT_CELL_GRAN)) * 2 * CVT_CELL_GRAN;
 594
 595                pix_clk = (image_width + h_blank) * hfreq;
 596                pix_clk = (pix_clk / CVT_PXL_CLK_GRAN) * CVT_PXL_CLK_GRAN;
 597
 598                h_bp = h_blank / 2;
 599                frame_width = image_width + h_blank;
 600
 601                hsync = frame_width * CVT_HSYNC_PERCENT / 100;
 602                hsync = (hsync / CVT_CELL_GRAN) * CVT_CELL_GRAN;
 603                h_fp = h_blank - hsync - h_bp;
 604        }
 605
 606        fmt->type = V4L2_DV_BT_656_1120;
 607        fmt->bt.polarities = polarities;
 608        fmt->bt.width = image_width;
 609        fmt->bt.height = image_height;
 610        fmt->bt.hfrontporch = h_fp;
 611        fmt->bt.vfrontporch = v_fp;
 612        fmt->bt.hsync = hsync;
 613        fmt->bt.vsync = vsync;
 614        fmt->bt.hbackporch = frame_width - image_width - h_fp - hsync;
 615
 616        if (!interlaced) {
 617                fmt->bt.vbackporch = frame_height - image_height - v_fp - vsync;
 618                fmt->bt.interlaced = V4L2_DV_PROGRESSIVE;
 619        } else {
 620                fmt->bt.vbackporch = (frame_height - image_height - 2 * v_fp -
 621                                      2 * vsync) / 2;
 622                fmt->bt.il_vbackporch = frame_height - image_height - 2 * v_fp -
 623                                        2 * vsync - fmt->bt.vbackporch;
 624                fmt->bt.il_vfrontporch = v_fp;
 625                fmt->bt.il_vsync = vsync;
 626                fmt->bt.flags |= V4L2_DV_FL_HALF_LINE;
 627                fmt->bt.interlaced = V4L2_DV_INTERLACED;
 628        }
 629
 630        fmt->bt.pixelclock = pix_clk;
 631        fmt->bt.standards = V4L2_DV_BT_STD_CVT;
 632
 633        if (reduced_blanking)
 634                fmt->bt.flags |= V4L2_DV_FL_REDUCED_BLANKING;
 635
 636        return true;
 637}
 638EXPORT_SYMBOL_GPL(v4l2_detect_cvt);
 639
 640/*
 641 * GTF defines
 642 * Based on Generalized Timing Formula Standard
 643 * Version 1.1 September 2, 1999
 644 */
 645
 646#define GTF_PXL_CLK_GRAN        250000  /* pixel clock granularity */
 647
 648#define GTF_MIN_VSYNC_BP        550     /* min time of vsync + back porch (us) */
 649#define GTF_V_FP                1       /* vertical front porch (lines) */
 650#define GTF_CELL_GRAN           8       /* character cell granularity */
 651
 652/* Default */
 653#define GTF_D_M                 600     /* blanking formula gradient */
 654#define GTF_D_C                 40      /* blanking formula offset */
 655#define GTF_D_K                 128     /* blanking formula scaling factor */
 656#define GTF_D_J                 20      /* blanking formula scaling factor */
 657#define GTF_D_C_PRIME ((((GTF_D_C - GTF_D_J) * GTF_D_K) / 256) + GTF_D_J)
 658#define GTF_D_M_PRIME ((GTF_D_K * GTF_D_M) / 256)
 659
 660/* Secondary */
 661#define GTF_S_M                 3600    /* blanking formula gradient */
 662#define GTF_S_C                 40      /* blanking formula offset */
 663#define GTF_S_K                 128     /* blanking formula scaling factor */
 664#define GTF_S_J                 35      /* blanking formula scaling factor */
 665#define GTF_S_C_PRIME ((((GTF_S_C - GTF_S_J) * GTF_S_K) / 256) + GTF_S_J)
 666#define GTF_S_M_PRIME ((GTF_S_K * GTF_S_M) / 256)
 667
 668/** v4l2_detect_gtf - detect if the given timings follow the GTF standard
 669 * @frame_height - the total height of the frame (including blanking) in lines.
 670 * @hfreq - the horizontal frequency in Hz.
 671 * @vsync - the height of the vertical sync in lines.
 672 * @polarities - the horizontal and vertical polarities (same as struct
 673 *              v4l2_bt_timings polarities).
 674 * @interlaced - if this flag is true, it indicates interlaced format
 675 * @aspect - preferred aspect ratio. GTF has no method of determining the
 676 *              aspect ratio in order to derive the image width from the
 677 *              image height, so it has to be passed explicitly. Usually
 678 *              the native screen aspect ratio is used for this. If it
 679 *              is not filled in correctly, then 16:9 will be assumed.
 680 * @fmt - the resulting timings.
 681 *
 682 * This function will attempt to detect if the given values correspond to a
 683 * valid GTF format. If so, then it will return true, and fmt will be filled
 684 * in with the found GTF timings.
 685 */
 686bool v4l2_detect_gtf(unsigned frame_height,
 687                unsigned hfreq,
 688                unsigned vsync,
 689                u32 polarities,
 690                bool interlaced,
 691                struct v4l2_fract aspect,
 692                struct v4l2_dv_timings *fmt)
 693{
 694        int pix_clk;
 695        int  v_fp, v_bp, h_fp, hsync;
 696        int frame_width, image_height, image_width;
 697        bool default_gtf;
 698        int h_blank;
 699
 700        if (vsync != 3)
 701                return false;
 702
 703        if (polarities == V4L2_DV_VSYNC_POS_POL)
 704                default_gtf = true;
 705        else if (polarities == V4L2_DV_HSYNC_POS_POL)
 706                default_gtf = false;
 707        else
 708                return false;
 709
 710        if (hfreq == 0)
 711                return false;
 712
 713        /* Vertical */
 714        v_fp = GTF_V_FP;
 715        v_bp = (GTF_MIN_VSYNC_BP * hfreq + 500000) / 1000000 - vsync;
 716        if (interlaced)
 717                image_height = (frame_height - 2 * v_fp - 2 * vsync - 2 * v_bp) & ~0x1;
 718        else
 719                image_height = (frame_height - v_fp - vsync - v_bp + 1) & ~0x1;
 720
 721        if (image_height < 0)
 722                return false;
 723
 724        if (aspect.numerator == 0 || aspect.denominator == 0) {
 725                aspect.numerator = 16;
 726                aspect.denominator = 9;
 727        }
 728        image_width = ((image_height * aspect.numerator) / aspect.denominator);
 729        image_width = (image_width + GTF_CELL_GRAN/2) & ~(GTF_CELL_GRAN - 1);
 730
 731        /* Horizontal */
 732        if (default_gtf) {
 733                u64 num;
 734                u32 den;
 735
 736                num = ((image_width * GTF_D_C_PRIME * (u64)hfreq) -
 737                      ((u64)image_width * GTF_D_M_PRIME * 1000));
 738                den = (hfreq * (100 - GTF_D_C_PRIME) + GTF_D_M_PRIME * 1000) *
 739                      (2 * GTF_CELL_GRAN);
 740                h_blank = div_u64((num + (den >> 1)), den);
 741                h_blank *= (2 * GTF_CELL_GRAN);
 742        } else {
 743                u64 num;
 744                u32 den;
 745
 746                num = ((image_width * GTF_S_C_PRIME * (u64)hfreq) -
 747                      ((u64)image_width * GTF_S_M_PRIME * 1000));
 748                den = (hfreq * (100 - GTF_S_C_PRIME) + GTF_S_M_PRIME * 1000) *
 749                      (2 * GTF_CELL_GRAN);
 750                h_blank = div_u64((num + (den >> 1)), den);
 751                h_blank *= (2 * GTF_CELL_GRAN);
 752        }
 753
 754        frame_width = image_width + h_blank;
 755
 756        pix_clk = (image_width + h_blank) * hfreq;
 757        pix_clk = pix_clk / GTF_PXL_CLK_GRAN * GTF_PXL_CLK_GRAN;
 758
 759        hsync = (frame_width * 8 + 50) / 100;
 760        hsync = ((hsync + GTF_CELL_GRAN / 2) / GTF_CELL_GRAN) * GTF_CELL_GRAN;
 761
 762        h_fp = h_blank / 2 - hsync;
 763
 764        fmt->type = V4L2_DV_BT_656_1120;
 765        fmt->bt.polarities = polarities;
 766        fmt->bt.width = image_width;
 767        fmt->bt.height = image_height;
 768        fmt->bt.hfrontporch = h_fp;
 769        fmt->bt.vfrontporch = v_fp;
 770        fmt->bt.hsync = hsync;
 771        fmt->bt.vsync = vsync;
 772        fmt->bt.hbackporch = frame_width - image_width - h_fp - hsync;
 773
 774        if (!interlaced) {
 775                fmt->bt.vbackporch = frame_height - image_height - v_fp - vsync;
 776                fmt->bt.interlaced = V4L2_DV_PROGRESSIVE;
 777        } else {
 778                fmt->bt.vbackporch = (frame_height - image_height - 2 * v_fp -
 779                                      2 * vsync) / 2;
 780                fmt->bt.il_vbackporch = frame_height - image_height - 2 * v_fp -
 781                                        2 * vsync - fmt->bt.vbackporch;
 782                fmt->bt.il_vfrontporch = v_fp;
 783                fmt->bt.il_vsync = vsync;
 784                fmt->bt.flags |= V4L2_DV_FL_HALF_LINE;
 785                fmt->bt.interlaced = V4L2_DV_INTERLACED;
 786        }
 787
 788        fmt->bt.pixelclock = pix_clk;
 789        fmt->bt.standards = V4L2_DV_BT_STD_GTF;
 790
 791        if (!default_gtf)
 792                fmt->bt.flags |= V4L2_DV_FL_REDUCED_BLANKING;
 793
 794        return true;
 795}
 796EXPORT_SYMBOL_GPL(v4l2_detect_gtf);
 797
 798/** v4l2_calc_aspect_ratio - calculate the aspect ratio based on bytes
 799 *      0x15 and 0x16 from the EDID.
 800 * @hor_landscape - byte 0x15 from the EDID.
 801 * @vert_portrait - byte 0x16 from the EDID.
 802 *
 803 * Determines the aspect ratio from the EDID.
 804 * See VESA Enhanced EDID standard, release A, rev 2, section 3.6.2:
 805 * "Horizontal and Vertical Screen Size or Aspect Ratio"
 806 */
 807struct v4l2_fract v4l2_calc_aspect_ratio(u8 hor_landscape, u8 vert_portrait)
 808{
 809        struct v4l2_fract aspect = { 16, 9 };
 810        u8 ratio;
 811
 812        /* Nothing filled in, fallback to 16:9 */
 813        if (!hor_landscape && !vert_portrait)
 814                return aspect;
 815        /* Both filled in, so they are interpreted as the screen size in cm */
 816        if (hor_landscape && vert_portrait) {
 817                aspect.numerator = hor_landscape;
 818                aspect.denominator = vert_portrait;
 819                return aspect;
 820        }
 821        /* Only one is filled in, so interpret them as a ratio:
 822           (val + 99) / 100 */
 823        ratio = hor_landscape | vert_portrait;
 824        /* Change some rounded values into the exact aspect ratio */
 825        if (ratio == 79) {
 826                aspect.numerator = 16;
 827                aspect.denominator = 9;
 828        } else if (ratio == 34) {
 829                aspect.numerator = 4;
 830                aspect.denominator = 3;
 831        } else if (ratio == 68) {
 832                aspect.numerator = 15;
 833                aspect.denominator = 9;
 834        } else {
 835                aspect.numerator = hor_landscape + 99;
 836                aspect.denominator = 100;
 837        }
 838        if (hor_landscape)
 839                return aspect;
 840        /* The aspect ratio is for portrait, so swap numerator and denominator */
 841        swap(aspect.denominator, aspect.numerator);
 842        return aspect;
 843}
 844EXPORT_SYMBOL_GPL(v4l2_calc_aspect_ratio);
 845
 846/** v4l2_hdmi_rx_colorimetry - determine HDMI colorimetry information
 847 *      based on various InfoFrames.
 848 * @avi: the AVI InfoFrame
 849 * @hdmi: the HDMI Vendor InfoFrame, may be NULL
 850 * @height: the frame height
 851 *
 852 * Determines the HDMI colorimetry information, i.e. how the HDMI
 853 * pixel color data should be interpreted.
 854 *
 855 * Note that some of the newer features (DCI-P3, HDR) are not yet
 856 * implemented: the hdmi.h header needs to be updated to the HDMI 2.0
 857 * and CTA-861-G standards.
 858 */
 859struct v4l2_hdmi_colorimetry
 860v4l2_hdmi_rx_colorimetry(const struct hdmi_avi_infoframe *avi,
 861                         const struct hdmi_vendor_infoframe *hdmi,
 862                         unsigned int height)
 863{
 864        struct v4l2_hdmi_colorimetry c = {
 865                V4L2_COLORSPACE_SRGB,
 866                V4L2_YCBCR_ENC_DEFAULT,
 867                V4L2_QUANTIZATION_FULL_RANGE,
 868                V4L2_XFER_FUNC_SRGB
 869        };
 870        bool is_ce = avi->video_code || (hdmi && hdmi->vic);
 871        bool is_sdtv = height <= 576;
 872        bool default_is_lim_range_rgb = avi->video_code > 1;
 873
 874        switch (avi->colorspace) {
 875        case HDMI_COLORSPACE_RGB:
 876                /* RGB pixel encoding */
 877                switch (avi->colorimetry) {
 878                case HDMI_COLORIMETRY_EXTENDED:
 879                        switch (avi->extended_colorimetry) {
 880                        case HDMI_EXTENDED_COLORIMETRY_OPRGB:
 881                                c.colorspace = V4L2_COLORSPACE_OPRGB;
 882                                c.xfer_func = V4L2_XFER_FUNC_OPRGB;
 883                                break;
 884                        case HDMI_EXTENDED_COLORIMETRY_BT2020:
 885                                c.colorspace = V4L2_COLORSPACE_BT2020;
 886                                c.xfer_func = V4L2_XFER_FUNC_709;
 887                                break;
 888                        default:
 889                                break;
 890                        }
 891                        break;
 892                default:
 893                        break;
 894                }
 895                switch (avi->quantization_range) {
 896                case HDMI_QUANTIZATION_RANGE_LIMITED:
 897                        c.quantization = V4L2_QUANTIZATION_LIM_RANGE;
 898                        break;
 899                case HDMI_QUANTIZATION_RANGE_FULL:
 900                        break;
 901                default:
 902                        if (default_is_lim_range_rgb)
 903                                c.quantization = V4L2_QUANTIZATION_LIM_RANGE;
 904                        break;
 905                }
 906                break;
 907
 908        default:
 909                /* YCbCr pixel encoding */
 910                c.quantization = V4L2_QUANTIZATION_LIM_RANGE;
 911                switch (avi->colorimetry) {
 912                case HDMI_COLORIMETRY_NONE:
 913                        if (!is_ce)
 914                                break;
 915                        if (is_sdtv) {
 916                                c.colorspace = V4L2_COLORSPACE_SMPTE170M;
 917                                c.ycbcr_enc = V4L2_YCBCR_ENC_601;
 918                        } else {
 919                                c.colorspace = V4L2_COLORSPACE_REC709;
 920                                c.ycbcr_enc = V4L2_YCBCR_ENC_709;
 921                        }
 922                        c.xfer_func = V4L2_XFER_FUNC_709;
 923                        break;
 924                case HDMI_COLORIMETRY_ITU_601:
 925                        c.colorspace = V4L2_COLORSPACE_SMPTE170M;
 926                        c.ycbcr_enc = V4L2_YCBCR_ENC_601;
 927                        c.xfer_func = V4L2_XFER_FUNC_709;
 928                        break;
 929                case HDMI_COLORIMETRY_ITU_709:
 930                        c.colorspace = V4L2_COLORSPACE_REC709;
 931                        c.ycbcr_enc = V4L2_YCBCR_ENC_709;
 932                        c.xfer_func = V4L2_XFER_FUNC_709;
 933                        break;
 934                case HDMI_COLORIMETRY_EXTENDED:
 935                        switch (avi->extended_colorimetry) {
 936                        case HDMI_EXTENDED_COLORIMETRY_XV_YCC_601:
 937                                c.colorspace = V4L2_COLORSPACE_REC709;
 938                                c.ycbcr_enc = V4L2_YCBCR_ENC_XV709;
 939                                c.xfer_func = V4L2_XFER_FUNC_709;
 940                                break;
 941                        case HDMI_EXTENDED_COLORIMETRY_XV_YCC_709:
 942                                c.colorspace = V4L2_COLORSPACE_REC709;
 943                                c.ycbcr_enc = V4L2_YCBCR_ENC_XV601;
 944                                c.xfer_func = V4L2_XFER_FUNC_709;
 945                                break;
 946                        case HDMI_EXTENDED_COLORIMETRY_S_YCC_601:
 947                                c.colorspace = V4L2_COLORSPACE_SRGB;
 948                                c.ycbcr_enc = V4L2_YCBCR_ENC_601;
 949                                c.xfer_func = V4L2_XFER_FUNC_SRGB;
 950                                break;
 951                        case HDMI_EXTENDED_COLORIMETRY_OPYCC_601:
 952                                c.colorspace = V4L2_COLORSPACE_OPRGB;
 953                                c.ycbcr_enc = V4L2_YCBCR_ENC_601;
 954                                c.xfer_func = V4L2_XFER_FUNC_OPRGB;
 955                                break;
 956                        case HDMI_EXTENDED_COLORIMETRY_BT2020:
 957                                c.colorspace = V4L2_COLORSPACE_BT2020;
 958                                c.ycbcr_enc = V4L2_YCBCR_ENC_BT2020;
 959                                c.xfer_func = V4L2_XFER_FUNC_709;
 960                                break;
 961                        case HDMI_EXTENDED_COLORIMETRY_BT2020_CONST_LUM:
 962                                c.colorspace = V4L2_COLORSPACE_BT2020;
 963                                c.ycbcr_enc = V4L2_YCBCR_ENC_BT2020_CONST_LUM;
 964                                c.xfer_func = V4L2_XFER_FUNC_709;
 965                                break;
 966                        default: /* fall back to ITU_709 */
 967                                c.colorspace = V4L2_COLORSPACE_REC709;
 968                                c.ycbcr_enc = V4L2_YCBCR_ENC_709;
 969                                c.xfer_func = V4L2_XFER_FUNC_709;
 970                                break;
 971                        }
 972                        break;
 973                default:
 974                        break;
 975                }
 976                /*
 977                 * YCC Quantization Range signaling is more-or-less broken,
 978                 * let's just ignore this.
 979                 */
 980                break;
 981        }
 982        return c;
 983}
 984EXPORT_SYMBOL_GPL(v4l2_hdmi_rx_colorimetry);
 985
 986/**
 987 * v4l2_get_edid_phys_addr() - find and return the physical address
 988 *
 989 * @edid:       pointer to the EDID data
 990 * @size:       size in bytes of the EDID data
 991 * @offset:     If not %NULL then the location of the physical address
 992 *              bytes in the EDID will be returned here. This is set to 0
 993 *              if there is no physical address found.
 994 *
 995 * Return: the physical address or CEC_PHYS_ADDR_INVALID if there is none.
 996 */
 997u16 v4l2_get_edid_phys_addr(const u8 *edid, unsigned int size,
 998                            unsigned int *offset)
 999{
1000        unsigned int loc = cec_get_edid_spa_location(edid, size);
1001
1002        if (offset)
1003                *offset = loc;
1004        if (loc == 0)
1005                return CEC_PHYS_ADDR_INVALID;
1006        return (edid[loc] << 8) | edid[loc + 1];
1007}
1008EXPORT_SYMBOL_GPL(v4l2_get_edid_phys_addr);
1009
1010/**
1011 * v4l2_set_edid_phys_addr() - find and set the physical address
1012 *
1013 * @edid:       pointer to the EDID data
1014 * @size:       size in bytes of the EDID data
1015 * @phys_addr:  the new physical address
1016 *
1017 * This function finds the location of the physical address in the EDID
1018 * and fills in the given physical address and updates the checksum
1019 * at the end of the EDID block. It does nothing if the EDID doesn't
1020 * contain a physical address.
1021 */
1022void v4l2_set_edid_phys_addr(u8 *edid, unsigned int size, u16 phys_addr)
1023{
1024        unsigned int loc = cec_get_edid_spa_location(edid, size);
1025        u8 sum = 0;
1026        unsigned int i;
1027
1028        if (loc == 0)
1029                return;
1030        edid[loc] = phys_addr >> 8;
1031        edid[loc + 1] = phys_addr & 0xff;
1032        loc &= ~0x7f;
1033
1034        /* update the checksum */
1035        for (i = loc; i < loc + 127; i++)
1036                sum += edid[i];
1037        edid[i] = 256 - sum;
1038}
1039EXPORT_SYMBOL_GPL(v4l2_set_edid_phys_addr);
1040
1041/**
1042 * v4l2_phys_addr_for_input() - calculate the PA for an input
1043 *
1044 * @phys_addr:  the physical address of the parent
1045 * @input:      the number of the input port, must be between 1 and 15
1046 *
1047 * This function calculates a new physical address based on the input
1048 * port number. For example:
1049 *
1050 * PA = 0.0.0.0 and input = 2 becomes 2.0.0.0
1051 *
1052 * PA = 3.0.0.0 and input = 1 becomes 3.1.0.0
1053 *
1054 * PA = 3.2.1.0 and input = 5 becomes 3.2.1.5
1055 *
1056 * PA = 3.2.1.3 and input = 5 becomes f.f.f.f since it maxed out the depth.
1057 *
1058 * Return: the new physical address or CEC_PHYS_ADDR_INVALID.
1059 */
1060u16 v4l2_phys_addr_for_input(u16 phys_addr, u8 input)
1061{
1062        /* Check if input is sane */
1063        if (WARN_ON(input == 0 || input > 0xf))
1064                return CEC_PHYS_ADDR_INVALID;
1065
1066        if (phys_addr == 0)
1067                return input << 12;
1068
1069        if ((phys_addr & 0x0fff) == 0)
1070                return phys_addr | (input << 8);
1071
1072        if ((phys_addr & 0x00ff) == 0)
1073                return phys_addr | (input << 4);
1074
1075        if ((phys_addr & 0x000f) == 0)
1076                return phys_addr | input;
1077
1078        /*
1079         * All nibbles are used so no valid physical addresses can be assigned
1080         * to the input.
1081         */
1082        return CEC_PHYS_ADDR_INVALID;
1083}
1084EXPORT_SYMBOL_GPL(v4l2_phys_addr_for_input);
1085
1086/**
1087 * v4l2_phys_addr_validate() - validate a physical address from an EDID
1088 *
1089 * @phys_addr:  the physical address to validate
1090 * @parent:     if not %NULL, then this is filled with the parents PA.
1091 * @port:       if not %NULL, then this is filled with the input port.
1092 *
1093 * This validates a physical address as read from an EDID. If the
1094 * PA is invalid (such as 1.0.1.0 since '0' is only allowed at the end),
1095 * then it will return -EINVAL.
1096 *
1097 * The parent PA is passed into %parent and the input port is passed into
1098 * %port. For example:
1099 *
1100 * PA = 0.0.0.0: has parent 0.0.0.0 and input port 0.
1101 *
1102 * PA = 1.0.0.0: has parent 0.0.0.0 and input port 1.
1103 *
1104 * PA = 3.2.0.0: has parent 3.0.0.0 and input port 2.
1105 *
1106 * PA = f.f.f.f: has parent f.f.f.f and input port 0.
1107 *
1108 * Return: 0 if the PA is valid, -EINVAL if not.
1109 */
1110int v4l2_phys_addr_validate(u16 phys_addr, u16 *parent, u16 *port)
1111{
1112        int i;
1113
1114        if (parent)
1115                *parent = phys_addr;
1116        if (port)
1117                *port = 0;
1118        if (phys_addr == CEC_PHYS_ADDR_INVALID)
1119                return 0;
1120        for (i = 0; i < 16; i += 4)
1121                if (phys_addr & (0xf << i))
1122                        break;
1123        if (i == 16)
1124                return 0;
1125        if (parent)
1126                *parent = phys_addr & (0xfff0 << i);
1127        if (port)
1128                *port = (phys_addr >> i) & 0xf;
1129        for (i += 4; i < 16; i += 4)
1130                if ((phys_addr & (0xf << i)) == 0)
1131                        return -EINVAL;
1132        return 0;
1133}
1134EXPORT_SYMBOL_GPL(v4l2_phys_addr_validate);
1135