/* sanity checks for the blanking timings */ if (!bt->interlaced &&
(bt->il_vbackporch || bt->il_vsync || bt->il_vfrontporch)) returnfalse; /* * 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.
*/ if (bt->hfrontporch > max_hor ||
bt->hsync > max_hor || bt->hbackporch > max_hor) returnfalse; if (bt->vfrontporch > max_vert ||
bt->vsync > max_vert || bt->vbackporch > max_vert) returnfalse; if (bt->interlaced && (bt->il_vfrontporch > max_vert ||
bt->il_vsync > max_vert || bt->il_vbackporch > max_vert)) returnfalse; return fnc == NULL || fnc(t, fnc_handle);
}
EXPORT_SYMBOL_GPL(v4l2_valid_dv_timings);
int v4l2_enum_dv_timings_cap(struct v4l2_enum_dv_timings *t, conststruct v4l2_dv_timings_cap *cap,
v4l2_check_dv_timings_fnc fnc, void *fnc_handle)
{
u32 i, idx;
memset(t->reserved, 0, sizeof(t->reserved)); for (i = idx = 0; v4l2_dv_timings_presets[i].bt.width; i++) { if (v4l2_valid_dv_timings(v4l2_dv_timings_presets + i, cap,
fnc, fnc_handle) &&
idx++ == t->index) {
t->timings = v4l2_dv_timings_presets[i]; return 0;
}
} return -EINVAL;
}
EXPORT_SYMBOL_GPL(v4l2_enum_dv_timings_cap);
/** v4l2_calc_timeperframe - helper function to calculate timeperframe based * v4l2_dv_timings fields. * @t - Timings for the video mode. * * Calculates the expected timeperframe using the pixel clock value and * horizontal/vertical measures. This means that v4l2_dv_timings structure * must be correctly and fully filled.
*/ struct v4l2_fract v4l2_calc_timeperframe(conststruct v4l2_dv_timings *t)
{ conststruct v4l2_bt_timings *bt = &t->bt; struct v4l2_fract fps_fract = { 1, 1 }; unsignedlong n, d;
u32 htot, vtot, fps;
u64 pclk;
if (t->type != V4L2_DV_BT_656_1120) return fps_fract;
/* Normal blanking */ #define CVT_MIN_V_BPORCH 7 /* lines */ #define CVT_MIN_V_PORCH_RND 3 /* lines */ #define CVT_MIN_VSYNC_BP 550 /* min time of vsync + back porch (us) */ #define CVT_HSYNC_PERCENT 8 /* nominal hsync as percentage of line */
/* Normal blanking for CVT uses GTF to calculate horizontal blanking */ #define CVT_CELL_GRAN 8 /* character cell granularity */ #define CVT_M 600 /* blanking formula gradient */ #define CVT_C 40 /* blanking formula offset */ #define CVT_K 128 /* blanking formula scaling factor */ #define CVT_J 20 /* blanking formula scaling factor */ #define CVT_C_PRIME (((CVT_C - CVT_J) * CVT_K / 256) + CVT_J) #define CVT_M_PRIME (CVT_K * CVT_M / 256)
/** v4l2_detect_cvt - detect if the given timings follow the CVT standard * @frame_height - the total height of the frame (including blanking) in lines. * @hfreq - the horizontal frequency in Hz. * @vsync - the height of the vertical sync in lines. * @active_width - active width of image (does not include blanking). This * information is needed only in case of version 2 of reduced blanking. * In other cases, this parameter does not have any effect on timings. * @polarities - the horizontal and vertical polarities (same as struct * v4l2_bt_timings polarities). * @interlaced - if this flag is true, it indicates interlaced format * @cap - the v4l2_dv_timings_cap capabilities. * @timings - the resulting timings. * * This function will attempt to detect if the given values correspond to a * valid CVT format. If so, then it will return true, and fmt will be filled * in with the found CVT timings.
*/ bool v4l2_detect_cvt(unsignedint frame_height, unsignedint hfreq, unsignedint vsync, unsignedint active_width,
u32 polarities, bool interlaced, conststruct v4l2_dv_timings_cap *cap, struct v4l2_dv_timings *timings)
{ struct v4l2_dv_timings t = {}; int v_fp, v_bp, h_fp, h_bp, hsync; int frame_width, image_height, image_width; bool reduced_blanking; bool rb_v2 = false; unsignedint pix_clk;
#define GTF_MIN_VSYNC_BP 550 /* min time of vsync + back porch (us) */ #define GTF_V_FP 1 /* vertical front porch (lines) */ #define GTF_CELL_GRAN 8 /* character cell granularity */
/** v4l2_detect_gtf - detect if the given timings follow the GTF standard * @frame_height - the total height of the frame (including blanking) in lines. * @hfreq - the horizontal frequency in Hz. * @vsync - the height of the vertical sync in lines. * @polarities - the horizontal and vertical polarities (same as struct * v4l2_bt_timings polarities). * @interlaced - if this flag is true, it indicates interlaced format * @aspect - preferred aspect ratio. GTF has no method of determining the * aspect ratio in order to derive the image width from the * image height, so it has to be passed explicitly. Usually * the native screen aspect ratio is used for this. If it * is not filled in correctly, then 16:9 will be assumed. * @cap - the v4l2_dv_timings_cap capabilities. * @timings - the resulting timings. * * This function will attempt to detect if the given values correspond to a * valid GTF format. If so, then it will return true, and fmt will be filled * in with the found GTF timings.
*/ bool v4l2_detect_gtf(unsignedint frame_height, unsignedint hfreq, unsignedint vsync,
u32 polarities, bool interlaced, struct v4l2_fract aspect, conststruct v4l2_dv_timings_cap *cap, struct v4l2_dv_timings *timings)
{ struct v4l2_dv_timings t = {}; int pix_clk; int v_fp, v_bp, h_fp, hsync; int frame_width, image_height, image_width; bool default_gtf; int h_blank;
/** v4l2_calc_aspect_ratio - calculate the aspect ratio based on bytes * 0x15 and 0x16 from the EDID. * @hor_landscape - byte 0x15 from the EDID. * @vert_portrait - byte 0x16 from the EDID. * * Determines the aspect ratio from the EDID. * See VESA Enhanced EDID standard, release A, rev 2, section 3.6.2: * "Horizontal and Vertical Screen Size or Aspect Ratio"
*/ struct v4l2_fract v4l2_calc_aspect_ratio(u8 hor_landscape, u8 vert_portrait)
{ struct v4l2_fract aspect = { 16, 9 };
u8 ratio;
/* Nothing filled in, fallback to 16:9 */ if (!hor_landscape && !vert_portrait) return aspect; /* Both filled in, so they are interpreted as the screen size in cm */ if (hor_landscape && vert_portrait) {
aspect.numerator = hor_landscape;
aspect.denominator = vert_portrait; return aspect;
} /* Only one is filled in, so interpret them as a ratio:
(val + 99) / 100 */
ratio = hor_landscape | vert_portrait; /* Change some rounded values into the exact aspect ratio */ if (ratio == 79) {
aspect.numerator = 16;
aspect.denominator = 9;
} elseif (ratio == 34) {
aspect.numerator = 4;
aspect.denominator = 3;
} elseif (ratio == 68) {
aspect.numerator = 15;
aspect.denominator = 9;
} else {
aspect.numerator = hor_landscape + 99;
aspect.denominator = 100;
} if (hor_landscape) return aspect; /* The aspect ratio is for portrait, so swap numerator and denominator */
swap(aspect.denominator, aspect.numerator); return aspect;
}
EXPORT_SYMBOL_GPL(v4l2_calc_aspect_ratio);
/** v4l2_hdmi_rx_colorimetry - determine HDMI colorimetry information * based on various InfoFrames. * @avi: the AVI InfoFrame * @hdmi: the HDMI Vendor InfoFrame, may be NULL * @height: the frame height * * Determines the HDMI colorimetry information, i.e. how the HDMI * pixel color data should be interpreted. * * Note that some of the newer features (DCI-P3, HDR) are not yet * implemented: the hdmi.h header needs to be updated to the HDMI 2.0 * and CTA-861-G standards.
*/ struct v4l2_hdmi_colorimetry
v4l2_hdmi_rx_colorimetry(conststruct hdmi_avi_infoframe *avi, conststruct hdmi_vendor_infoframe *hdmi, unsignedint height)
{ struct v4l2_hdmi_colorimetry c = {
V4L2_COLORSPACE_SRGB,
V4L2_YCBCR_ENC_DEFAULT,
V4L2_QUANTIZATION_FULL_RANGE,
V4L2_XFER_FUNC_SRGB
}; bool is_ce = avi->video_code || (hdmi && hdmi->vic); bool is_sdtv = height <= 576; bool default_is_lim_range_rgb = avi->video_code > 1;
switch (avi->colorspace) { case HDMI_COLORSPACE_RGB: /* RGB pixel encoding */ switch (avi->colorimetry) { case HDMI_COLORIMETRY_EXTENDED: switch (avi->extended_colorimetry) { case HDMI_EXTENDED_COLORIMETRY_OPRGB:
c.colorspace = V4L2_COLORSPACE_OPRGB;
c.xfer_func = V4L2_XFER_FUNC_OPRGB; break; case HDMI_EXTENDED_COLORIMETRY_BT2020:
c.colorspace = V4L2_COLORSPACE_BT2020;
c.xfer_func = V4L2_XFER_FUNC_709; break; default: break;
} break; default: break;
} switch (avi->quantization_range) { case HDMI_QUANTIZATION_RANGE_LIMITED:
c.quantization = V4L2_QUANTIZATION_LIM_RANGE; break; case HDMI_QUANTIZATION_RANGE_FULL: break; default: if (default_is_lim_range_rgb)
c.quantization = V4L2_QUANTIZATION_LIM_RANGE; break;
} break;
/** * v4l2_num_edid_blocks() - return the number of EDID blocks * * @edid: pointer to the EDID data * @max_blocks: maximum number of supported EDID blocks * * Return: the number of EDID blocks based on the contents of the EDID. * This supports the HDMI Forum EDID Extension Override Data Block.
*/ unsignedint v4l2_num_edid_blocks(const u8 *edid, unsignedint max_blocks)
{ unsignedint blocks;
if (!edid || !max_blocks) return 0;
// The number of extension blocks is recorded at byte 126 of the // first 128-byte block in the EDID. // // If there is an HDMI Forum EDID Extension Override Data Block // present, then it is in bytes 4-6 of the first CTA-861 extension // block of the EDID.
blocks = edid[126] + 1; // Check for HDMI Forum EDID Extension Override Data Block if (blocks >= 2 && // The EDID must be at least 2 blocks
max_blocks >= 3 && // The caller supports at least 3 blocks
edid[128] == 2 && // The first extension block is type CTA-861
edid[133] == 0x78 && // Identifier for the EEODB
(edid[132] & 0xe0) == 0xe0 && // Tag Code == 7
(edid[132] & 0x1f) >= 2 && // Length >= 2
edid[134] > 1) // Number of extension blocks is sane
blocks = edid[134] + 1; return blocks > max_blocks ? max_blocks : blocks;
}
EXPORT_SYMBOL_GPL(v4l2_num_edid_blocks);
/** * v4l2_get_edid_phys_addr() - find and return the physical address * * @edid: pointer to the EDID data * @size: size in bytes of the EDID data * @offset: If not %NULL then the location of the physical address * bytes in the EDID will be returned here. This is set to 0 * if there is no physical address found. * * Return: the physical address or CEC_PHYS_ADDR_INVALID if there is none.
*/
u16 v4l2_get_edid_phys_addr(const u8 *edid, unsignedint size, unsignedint *offset)
{ unsignedint loc = cec_get_edid_spa_location(edid, size);
/** * v4l2_set_edid_phys_addr() - find and set the physical address * * @edid: pointer to the EDID data * @size: size in bytes of the EDID data * @phys_addr: the new physical address * * This function finds the location of the physical address in the EDID * and fills in the given physical address and updates the checksum * at the end of the EDID block. It does nothing if the EDID doesn't * contain a physical address.
*/ void v4l2_set_edid_phys_addr(u8 *edid, unsignedint size, u16 phys_addr)
{ unsignedint loc = cec_get_edid_spa_location(edid, size);
u8 sum = 0; unsignedint i;
if (loc == 0) return;
edid[loc] = phys_addr >> 8;
edid[loc + 1] = phys_addr & 0xff;
loc &= ~0x7f;
/* update the checksum */ for (i = loc; i < loc + 127; i++)
sum += edid[i];
edid[i] = 256 - sum;
}
EXPORT_SYMBOL_GPL(v4l2_set_edid_phys_addr);
/** * v4l2_phys_addr_for_input() - calculate the PA for an input * * @phys_addr: the physical address of the parent * @input: the number of the input port, must be between 1 and 15 * * This function calculates a new physical address based on the input * port number. For example: * * PA = 0.0.0.0 and input = 2 becomes 2.0.0.0 * * PA = 3.0.0.0 and input = 1 becomes 3.1.0.0 * * PA = 3.2.1.0 and input = 5 becomes 3.2.1.5 * * PA = 3.2.1.3 and input = 5 becomes f.f.f.f since it maxed out the depth. * * Return: the new physical address or CEC_PHYS_ADDR_INVALID.
*/
u16 v4l2_phys_addr_for_input(u16 phys_addr, u8 input)
{ /* Check if input is sane */ if (WARN_ON(input == 0 || input > 0xf)) return CEC_PHYS_ADDR_INVALID;
if ((phys_addr & 0x000f) == 0) return phys_addr | input;
/* * All nibbles are used so no valid physical addresses can be assigned * to the input.
*/ return CEC_PHYS_ADDR_INVALID;
}
EXPORT_SYMBOL_GPL(v4l2_phys_addr_for_input);
/** * v4l2_phys_addr_validate() - validate a physical address from an EDID * * @phys_addr: the physical address to validate * @parent: if not %NULL, then this is filled with the parents PA. * @port: if not %NULL, then this is filled with the input port. * * This validates a physical address as read from an EDID. If the * PA is invalid (such as 1.0.1.0 since '0' is only allowed at the end), * then it will return -EINVAL. * * The parent PA is passed into %parent and the input port is passed into * %port. For example: * * PA = 0.0.0.0: has parent 0.0.0.0 and input port 0. * * PA = 1.0.0.0: has parent 0.0.0.0 and input port 1. * * PA = 3.2.0.0: has parent 3.0.0.0 and input port 2. * * PA = f.f.f.f: has parent f.f.f.f and input port 0. * * Return: 0 if the PA is valid, -EINVAL if not.
*/ int v4l2_phys_addr_validate(u16 phys_addr, u16 *parent, u16 *port)
{ int i;
if (parent)
*parent = phys_addr; if (port)
*port = 0; if (phys_addr == CEC_PHYS_ADDR_INVALID) return 0; for (i = 0; i < 16; i += 4) if (phys_addr & (0xf << i)) break; if (i == 16) return 0; if (parent)
*parent = phys_addr & (0xfff0 << i); if (port)
*port = (phys_addr >> i) & 0xf; for (i += 4; i < 16; i += 4) if ((phys_addr & (0xf << i)) == 0) return -EINVAL; return 0;
}
EXPORT_SYMBOL_GPL(v4l2_phys_addr_validate);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.