[alsa-devel] [PATCH v2 3/4] media: i2c: Add TDA1997x HDMI receiver driver

Tim Harvey tharvey at gateworks.com
Fri Oct 20 16:00:07 CEST 2017


On Thu, Oct 19, 2017 at 12:39 AM, Hans Verkuil <hverkuil at xs4all.nl> wrote:
<snip>
>>> What I am missing here is handling of the RGB quantization range.
>>> An HDMI receiver will typically send full range RGB or limited range YUV
>>> to the SoC. The HDMI source can however send full or limited range RGB
>>> or limited range YUV (full range YUV is theoretically possible, but nobody
>>> does that).
>>>
>>
>> isn't this quantization range a function of the colorspace and
>> colorimetry dictated by the AVI infoframe? I'm taking these into
>> consideration when setting up the conversion matrix in
>> tda1997x_configure_conv().
>
> No, it's independent of that.

and from another reply:
> A small correction here: while ideally you should indeed check if the current
> EDID supports selectable RGB Quantization Range, in practice you don't need
> to. If the source explicitly sets the RGB quantization range, then just use
> that.
>
> Note: some hardware can do this automatically (adv7604) by detecting what is
> transmitted in the AVI InfoFrame. That's probably not the case here since you
> have to provide a conversion matrix.

I see the AVI infoframe has hdmi_quantization_range and
hdmi_ycc_quantization_range along with vid_code.

I'm not at all clear what to do with this information. Is there
anything you see in the datasheet [1] that points to something I need
to be doing?

>
>>
>>> For a Full HD receiver the rules when receiving RGB video are as follows:
>>>
>>> If the EDID supports selectable RGB Quantization Range, then check if the
>>> source explicitly sets the RGB quantization range in the AVI InfoFrame and
>>> use that value.
>>>
>>> Otherwise fall back to the default rules:
>>>
>>> if VIC == 0, then expect full range RGB, otherwise expect limited range RGB.
>>
>> Are you referring to the video_code field of the AVI infoframe or vic
>> from a vendor infoframe?
>
> AVI InfoFrame.
>
> The HDMI VIC codes in the vendor InfoFrame are only valid for 4k formats. And
> that's not supported by this device, right?

Right, the TDA1997x supports 1080p only.

>
>>
>>>
>>> It gets even more complicated with 4k video, but this is full HD only.
>>>
>>> In addition, you may also want to implement the V4L2_CID_DV_RX_RGB_RANGE control
>>> to let userspace override the autodetection.
>>
>> I'll add that as an additional patch. Are there other V4L2_CID's that
>> I should be adding here?
>
> V4L2_CID_DV_RX_POWER_PRESENT (if possible) and optionally V4L2_CID_DV_RX_IT_CONTENT_TYPE.
>

It looks like there is a register for 5V_HPD detect.

I assume the content type to return is the value reported from the AVI frame?

<snip>
>>
>> Regarding video standard detection where this chip provides me with
>> vertical-period, horizontal-period, and horizontal-pulse-width I
>> should be able to detect the standard simply based off of
>> vertical-period (framerate) and horizontal-period (line width
>> including blanking) right? I wasn't sure if my method of matching
>> these within 14% tolerance made sense. I will be removing the hsmatch
>> logic from that as it seems the horizontal-pulse-width should be
>> irrelevant.
>
> For proper video detection you ideally need:
>
> h/v sync size
> h/v back/front porch size
> h/v polarity
> pixelclock (usually an approximation)
>
> The v4l2_find_dv_timings_cap() helper can help you find the corresponding
> timings, allowing for pixelclock variation.
>
> That function assumes that the sync/back/frontporch values are all known.
> But not all devices can actually discover those values. What can your
> hardware detect? Can it tell front and backporch apart? Can it determine
> the sync size?
>
> I've been considering for some time to improve that helper function to be
> able to handle hardware that isn't able separate sync/back/frontporch values.
>

The TDA1997x provides only the vertical/horizontal periods and the
horizontal pulse
width (section 8.3.4 of datasheet [1]).

Can you point me to a good primer on the relationship between these
values and the h/v back/front porch?

Currently I iterate over the list of known formats calculating hper
(bt->pixelclock / V4L2_DV_BT_FRAME_WIDTH(bt)) and vper (hper /
V4L2_DV_BT_FRAME_HEIGHT(bt)) (framerate) and find the closest match
within +/- 7% tolerance. The list of supported formats is sorted by
framerate then width.

        /* look for matching timings */
        for (i = 0; i < ARRAY_SIZE(tda1997x_hdmi_modes); i++) {
                const struct tda1997x_video_std *std = &tda1997x_hdmi_modes[i];
                const struct v4l2_bt_timings *bt = &std->timings.bt;
                int _hper, _vper, _hsper;
                int vmin, vmax, hmin, hmax, hsmin, hsmax;
                int vmatch, hsmatch;

                width = V4L2_DV_BT_FRAME_WIDTH(bt);
                lines = V4L2_DV_BT_FRAME_HEIGHT(bt);

                _hper = (int)bt->pixelclock / (int)width;
                _vper = _hper / lines;
                _hsper = (int)bt->pixelclock / (int)bt->hsync;
                if (bt->interlaced)
                        _vper *= 2;
                /* vper +/- 0.7% */
                vmin = 993 * (27000000 / _vper) / 1000;
                vmax = 1007 * (27000000 / _vper) / 1000;
                _hsper = (int)bt->pixelclock / (int)bt->hsync;
                if (bt->interlaced)
                        _vper *= 2;
                /* vper +/- 0.7% */
                vmin = 993 * (27000000 / _vper) / 1000;
                vmax = 1007 * (27000000 / _vper) / 1000;
                /* hper +/- 0.7% */
                hmin = 993 * (27000000 / _hper) / 1000;
                hmax = 1007 * (27000000 / _hper) / 1000;

                /* vmatch matches the framerate */
                vmatch = ((vper <= vmax) && (vper >= vmin)) ? 1 : 0;
                /* hmatch matches the width */
                hmatch = ((hper <= hmax) && (hper >= hmin)) ? 1 : 0;
                if (vmatch && hsmatch) {
                        v4l_info(state->client,
                                 "resolution: %dx%d%c@%d (%d/%d/%d) %dMHz %d\n",
                                 bt->width, bt->height, bt->interlaced?'i':'p',
                                 _vper, vper, hper, hsper, pixrate, hsmatch);
                        state->fps = (int)bt->pixelclock / (width * lines);
                        state->std = std;
                        return 0;
                }
        }

Note that I've thrown out any comparisons based on horizontal pulse
width from my first patch as that didn't appear to fit well. So far
the above works well however I do fail to recognize the following
modes (using a Marshall SG4K HDMI test generator):

VESA640x480P_60HZ v4l2 defines this as 4L2_DV_BT_CEA_640X480P59_94
which fails vmatch
VESA1400x1050P_60HZ should match V4L2_DV_BT_DMT_1400X1050P60_RB but it
calculates 59Hz and fails vmatch
VESA1920x1200P_60HZ should match V4L2_DV_BT_DMT_1920X1200P60_RB but it
calculates 59Hz and fails vmatch
CEAVIC1440x480I_60HZ not in v4l2-dv-timings.h
CEAVIC720x480P_60HZ not in v4l2-dv-timings.h (there's a 720x480p59)
CEAVIC1440x576I_50HZ not in v4l2-dv-timings.h

I should have mentioned in my cover letter that I only have a
datasheet for this device and some fairly obfuscated vendor example
code - I don't have proper register set documentation.

Regards,

Tim

[1] http://dev.gateworks.com/datasheets/TDA19971-datasheet-rev3.pdf


More information about the Alsa-devel mailing list