// SPDX-License-Identifier: GPL-2.0-only
/*
* v4l2-dv-timings - dv-timings helper functions
*
* Copyright 2013 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/rational.h>
#include <linux/videodev2.h>
#include <linux/v4l2-dv-timings.h>
#include <media/v4l2-dv-timings.h>
#include <linux/math64.h>
#include <linux/hdmi.h>
#include <media/cec.h>
MODULE_AUTHOR("Hans Verkuil");
MODULE_DESCRIPTION("V4L2 DV Timings Helper Functions");
MODULE_LICENSE("GPL");
const struct v4l2_dv_timings v4l2_dv_timings_presets[] = {
V4L2_DV_BT_CEA_640X480P59_94,
V4L2_DV_BT_CEA_720X480I59_94,
V4L2_DV_BT_CEA_720X480P59_94,
V4L2_DV_BT_CEA_720X576I50,
V4L2_DV_BT_CEA_720X576P50,
V4L2_DV_BT_CEA_1280X720P24,
V4L2_DV_BT_CEA_1280X720P25,
V4L2_DV_BT_CEA_1280X720P30,
V4L2_DV_BT_CEA_1280X720P50,
V4L2_DV_BT_CEA_1280X720P60,
V4L2_DV_BT_CEA_1920X1080P24,
V4L2_DV_BT_CEA_1920X1080P25,
V4L2_DV_BT_CEA_1920X1080P30,
V4L2_DV_BT_CEA_1920X1080I50,
V4L2_DV_BT_CEA_1920X1080P50,
V4L2_DV_BT_CEA_1920X1080I60,
V4L2_DV_BT_CEA_1920X1080P60,
V4L2_DV_BT_DMT_640X350P85,
V4L2_DV_BT_DMT_640X400P85,
V4L2_DV_BT_DMT_720X400P85,
V4L2_DV_BT_DMT_640X480P72,
V4L2_DV_BT_DMT_640X480P75,
V4L2_DV_BT_DMT_640X480P85,
V4L2_DV_BT_DMT_800X600P56,
V4L2_DV_BT_DMT_800X600P60,
V4L2_DV_BT_DMT_800X600P72,
V4L2_DV_BT_DMT_800X600P75,
V4L2_DV_BT_DMT_800X600P85,
V4L2_DV_BT_DMT_800X600P120_RB,
V4L2_DV_BT_DMT_848X480P60,
V4L2_DV_BT_DMT_1024X768I43,
V4L2_DV_BT_DMT_1024X768P60,
V4L2_DV_BT_DMT_1024X768P70,
V4L2_DV_BT_DMT_1024X768P75,
V4L2_DV_BT_DMT_1024X768P85,
V4L2_DV_BT_DMT_1024X768P120_RB,
V4L2_DV_BT_DMT_1152X864P75,
V4L2_DV_BT_DMT_1280X768P60_RB,
V4L2_DV_BT_DMT_1280X768P60,
V4L2_DV_BT_DMT_1280X768P75,
V4L2_DV_BT_DMT_1280X768P85,
V4L2_DV_BT_DMT_1280X768P120_RB,
V4L2_DV_BT_DMT_1280X800P60_RB,
V4L2_DV_BT_DMT_1280X800P60,
V4L2_DV_BT_DMT_1280X800P75,
V4L2_DV_BT_DMT_1280X800P85,
V4L2_DV_BT_DMT_1280X800P120_RB,
V4L2_DV_BT_DMT_1280X960P60,
V4L2_DV_BT_DMT_1280X960P85,
V4L2_DV_BT_DMT_1280X960P120_RB,
V4L2_DV_BT_DMT_1280X1024P60,
V4L2_DV_BT_DMT_1280X1024P75,
V4L2_DV_BT_DMT_1280X1024P85,
V4L2_DV_BT_DMT_1280X1024P120_RB,
V4L2_DV_BT_DMT_1360X768P60,
V4L2_DV_BT_DMT_1360X768P120_RB,
V4L2_DV_BT_DMT_1366X768P60,
V4L2_DV_BT_DMT_1366X768P60_RB,
V4L2_DV_BT_DMT_1400X1050P60_RB,
V4L2_DV_BT_DMT_1400X1050P60,
V4L2_DV_BT_DMT_1400X1050P75,
V4L2_DV_BT_DMT_1400X1050P85,
V4L2_DV_BT_DMT_1400X1050P120_RB,
V4L2_DV_BT_DMT_1440X900P60_RB,
V4L2_DV_BT_DMT_1440X900P60,
V4L2_DV_BT_DMT_1440X900P75,
V4L2_DV_BT_DMT_1440X900P85,
V4L2_DV_BT_DMT_1440X900P120_RB,
V4L2_DV_BT_DMT_1600X900P60_RB,
V4L2_DV_BT_DMT_1600X1200P60,
V4L2_DV_BT_DMT_1600X1200P65,
V4L2_DV_BT_DMT_1600X1200P70,
V4L2_DV_BT_DMT_1600X1200P75,
V4L2_DV_BT_DMT_1600X1200P85,
V4L2_DV_BT_DMT_1600X1200P120_RB,
V4L2_DV_BT_DMT_1680X1050P60_RB,
V4L2_DV_BT_DMT_1680X1050P60,
V4L2_DV_BT_DMT_1680X1050P75,
V4L2_DV_BT_DMT_1680X1050P85,
V4L2_DV_BT_DMT_1680X1050P120_RB,
V4L2_DV_BT_DMT_1792X1344P60,
V4L2_DV_BT_DMT_1792X1344P75,
V4L2_DV_BT_DMT_1792X1344P120_RB,
V4L2_DV_BT_DMT_1856X1392P60,
V4L2_DV_BT_DMT_1856X1392P75,
V4L2_DV_BT_DMT_1856X1392P120_RB,
V4L2_DV_BT_DMT_1920X1200P60_RB,
V4L2_DV_BT_DMT_1920X1200P60,
V4L2_DV_BT_DMT_1920X1200P75,
V4L2_DV_BT_DMT_1920X1200P85,
V4L2_DV_BT_DMT_1920X1200P120_RB,
V4L2_DV_BT_DMT_1920X1440P60,
V4L2_DV_BT_DMT_1920X1440P75,
V4L2_DV_BT_DMT_1920X1440P120_RB,
V4L2_DV_BT_DMT_2048X1152P60_RB,
V4L2_DV_BT_DMT_2560X1600P60_RB,
V4L2_DV_BT_DMT_2560X1600P60,
V4L2_DV_BT_DMT_2560X1600P75,
V4L2_DV_BT_DMT_2560X1600P85,
V4L2_DV_BT_DMT_2560X1600P120_RB,
V4L2_DV_BT_CEA_3840X2160P24,
V4L2_DV_BT_CEA_3840X2160P25,
V4L2_DV_BT_CEA_3840X2160P30,
V4L2_DV_BT_CEA_3840X2160P50,
V4L2_DV_BT_CEA_3840X2160P60,
V4L2_DV_BT_CEA_4096X2160P24,
V4L2_DV_BT_CEA_4096X2160P25,
V4L2_DV_BT_CEA_4096X2160P30,
V4L2_DV_BT_CEA_4096X2160P50,
V4L2_DV_BT_DMT_4096X2160P59_94_RB,
V4L2_DV_BT_CEA_4096X2160P60,
{ }
};
EXPORT_SYMBOL_GPL(v4l2_dv_timings_presets);
bool v4l2_valid_dv_timings(const struct v4l2_dv_timings *t,
const struct v4l2_dv_timings_cap *dvcap,
v4l2_check_dv_timings_fnc fnc,
void *fnc_handle)
{
const struct v4l2_bt_timings *bt = &t->bt;
const struct v4l2_bt_timings_cap *cap = &dvcap->bt;
u32 caps = cap->capabilities;
const u32 max_vert = 10240;
u32 max_hor = 3 * bt->width;
if (t->type != V4L2_DV_BT_656_1120)
return false;
if (t->type != dvcap->type ||
bt->height < cap->min_height ||
bt->height > cap->max_height ||
bt->width < cap->min_width ||
bt->width > cap->max_width ||
bt->pixelclock < cap->min_pixelclock ||
bt->pixelclock > cap->max_pixelclock ||
(!(caps & V4L2_DV_BT_CAP_CUSTOM) &&
cap->standards && bt->standards &&
!(bt->standards & cap->standards)) ||
(bt->interlaced && !(caps & V4L2_DV_BT_CAP_INTERLACED)) ||
(!bt->interlaced && !(caps & V4L2_DV_BT_CAP_PROGRESSIVE)))
return false;
/* sanity checks for the blanking timings */
if (!bt->interlaced &&
(bt->il_vbackporch || bt->il_vsync || bt->il_vfrontporch))
return false;
/*
* Some video receivers cannot properly separate the frontporch,
* backporch and sync values, and instead they only have the total
* blanking. That can be assigned to any of these three fields.
* So just check that none of these are way out of range.