On 07.11.2016 02:45, Inki Dae wrote:
>
> 2016년 10월 26일 21:36에 Andrzej Hajda 이(가) 쓴 글:
>> Use core helpers to generate infoframes and generate vendor frame if 
>> necessary.
>>
>> Signed-off-by: Andrzej Hajda <a.hajda at samsung.com>
>> ---
>>  drivers/gpu/drm/exynos/exynos_hdmi.c | 141 
>> ++++++++++-------------------------
>>  drivers/gpu/drm/exynos/regs-hdmi.h   |   2 +
>>  2 files changed, 42 insertions(+), 101 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c 
>> b/drivers/gpu/drm/exynos/exynos_hdmi.c
>> index e8fb6ef..1bb2df7 100644
>> --- a/drivers/gpu/drm/exynos/exynos_hdmi.c
>> +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
>> @@ -47,19 +47,6 @@
>>  
>>  #define HOTPLUG_DEBOUNCE_MS         1100
>>  
>> -/* AVI header and aspect ratio */
>> -#define HDMI_AVI_VERSION            0x02
>> -#define HDMI_AVI_LENGTH                     0x0d
>> -
>> -/* AUI header info */
>> -#define HDMI_AUI_VERSION            0x01
>> -#define HDMI_AUI_LENGTH                     0x0a
>> -
>> -/* AVI active format aspect ratio */
>> -#define AVI_SAME_AS_PIC_ASPECT_RATIO        0x08
>> -#define AVI_4_3_CENTER_RATIO                0x09
>> -#define AVI_16_9_CENTER_RATIO               0x0a
>> -
>>  enum hdmi_type {
>>      HDMI_TYPE13,
>>      HDMI_TYPE14,
>> @@ -131,7 +118,6 @@ struct hdmi_context {
>>      bool                            dvi_mode;
>>      struct delayed_work             hotplug_work;
>>      struct drm_display_mode         current_mode;
>> -    u8                              cea_video_id;
>>      const struct hdmi_driver_data   *drv_data;
>>  
>>      void __iomem                    *regs;
>> @@ -681,6 +667,13 @@ static inline void hdmi_reg_writev(struct hdmi_context 
>> *hdata, u32 reg_id,
>>      }
>>  }
>>  
>> +static inline void hdmi_reg_write_buf(struct hdmi_context *hdata, u32 
>> reg_id,
>> +                                  u8 *buf, int size)
>> +{
>> +    for (reg_id = hdmi_map_reg(hdata, reg_id); size; --size, reg_id += 4)
>> +            writel(*buf++, hdata->regs + reg_id);
>> +}
>> +
>>  static inline void hdmi_reg_writemask(struct hdmi_context *hdata,
>>                               u32 reg_id, u32 value, u32 mask)
>>  {
>> @@ -762,93 +755,50 @@ static int hdmi_clk_set_parents(struct hdmi_context 
>> *hdata, bool to_phy)
>>      return ret;
>>  }
>>  
>> -static u8 hdmi_chksum(struct hdmi_context *hdata,
>> -                    u32 start, u8 len, u32 hdr_sum)
>> -{
>> -    int i;
>> -
>> -    /* hdr_sum : header0 + header1 + header2
>> -    * start : start address of packet byte1
>> -    * len : packet bytes - 1 */
>> -    for (i = 0; i < len; ++i)
>> -            hdr_sum += 0xff & hdmi_reg_read(hdata, start + i * 4);
>> -
>> -    /* return 2's complement of 8 bit hdr_sum */
>> -    return (u8)(~(hdr_sum & 0xff) + 1);
>> -}
>> -
>> -static void hdmi_reg_infoframe(struct hdmi_context *hdata,
>> -                    union hdmi_infoframe *infoframe)
>> +static void hdmi_reg_infoframes(struct hdmi_context *hdata)
>>  {
>> -    u32 hdr_sum;
>> -    u8 chksum;
>> -    u8 ar;
>> +    union hdmi_infoframe frm;
>> +    u8 buf[25];
>> +    int ret;
>>  
>>      if (hdata->dvi_mode) {
>> -            hdmi_reg_writeb(hdata, HDMI_VSI_CON,
>> -                            HDMI_VSI_CON_DO_NOT_TRANSMIT);
>>              hdmi_reg_writeb(hdata, HDMI_AVI_CON,
>>                              HDMI_AVI_CON_DO_NOT_TRANSMIT);
>> +            hdmi_reg_writeb(hdata, HDMI_VSI_CON,
>> +                            HDMI_VSI_CON_DO_NOT_TRANSMIT);
>>              hdmi_reg_writeb(hdata, HDMI_AUI_CON, HDMI_AUI_CON_NO_TRAN);
>>              return;
>>      }
>>  
>> -    switch (infoframe->any.type) {
>> -    case HDMI_INFOFRAME_TYPE_AVI:
>> +    ret = drm_hdmi_avi_infoframe_from_display_mode(&frm.avi,
>> +                    &hdata->current_mode);
>> +    if (ret >= 0)
> Seems above condition is not clear becuase 
> drm_hdmi_avi_infoframe_from_display_mode function returns 0 or negative value.

So it means 'there is no error', I can change it to '!ret' or 'ret == 0'
if you prefer, I have just used '>= 0' to be more concise with next
error check.
>
>> +            ret = hdmi_avi_infoframe_pack(&frm.avi, buf, sizeof(buf));
>> +    if (ret > 0) {
>>              hdmi_reg_writeb(hdata, HDMI_AVI_CON, HDMI_AVI_CON_EVERY_VSYNC);
> I think above code should be called when 
> drm_hdmi_avi_infoframe_from_display_mode function returned 0 and the value 
> from hdmi_avi_infoframe_pack function is more than 1.

Why do you think 'more than 1' is better than 'more than 0' in this
case? hdmi_avi_infoframe_pack returns length of generated frame or
negative value in case of error,
so any positive value is OK, there is no special meaning for '1'.

>
>> -            hdmi_reg_writeb(hdata, HDMI_AVI_HEADER0, infoframe->any.type);
>> -            hdmi_reg_writeb(hdata, HDMI_AVI_HEADER1,
>> -                            infoframe->any.version);
>> -            hdmi_reg_writeb(hdata, HDMI_AVI_HEADER2, infoframe->any.length);
>> -            hdr_sum = infoframe->any.type + infoframe->any.version +
>> -                      infoframe->any.length;
>> -
>> -            /* Output format zero hardcoded ,RGB YBCR selection */
>> -            hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(1), 0 << 5 |
>> -                    AVI_ACTIVE_FORMAT_VALID |
>> -                    AVI_UNDERSCANNED_DISPLAY_VALID);
>> -
>> -            /*
>> -             * Set the aspect ratio as per the mode, mentioned in
>> -             * Table 9 AVI InfoFrame Data Byte 2 of CEA-861-D Standard
>> -             */
>> -            ar = hdata->current_mode.picture_aspect_ratio;
>> -            switch (ar) {
>> -            case HDMI_PICTURE_ASPECT_4_3:
>> -                    ar |= AVI_4_3_CENTER_RATIO;
>> -                    break;
>> -            case HDMI_PICTURE_ASPECT_16_9:
>> -                    ar |= AVI_16_9_CENTER_RATIO;
>> -                    break;
>> -            case HDMI_PICTURE_ASPECT_NONE:
>> -            default:
>> -                    ar |= AVI_SAME_AS_PIC_ASPECT_RATIO;
>> -                    break;
>> -            }
>> -            hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(2), ar);
>> +            hdmi_reg_write_buf(hdata, HDMI_AVI_HEADER0, buf, ret);
>> +    } else {
>> +            DRM_INFO("%s: invalid AVI infoframe (%d)\n", __func__, ret);
> If drm_hdmi_avi_infoframe_from_display_mode function returns 0 on success, 
> then above message will be printed out. Seems not reasonable.

If drm_hdmi_avi_infoframe_from_display_mode returns 0, then
hdmi_avi_infoframe_pack is called and if the latter
fails (practically impossible) this message will be printed which is
correct behavior.

The same answer is for your next comments.

Regards
Andrzej

>
>> +    }
>>  
>> -            hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(4), hdata->cea_video_id);
>> +    ret = drm_hdmi_vendor_infoframe_from_display_mode(&frm.vendor.hdmi,
>> +                    &hdata->current_mode);
>> +    if (ret >= 0)
> Ditto.
>
>> +            ret = hdmi_vendor_infoframe_pack(&frm.vendor.hdmi, buf,
>> +                            sizeof(buf));
>> +    if (ret > 0) {
>> +            hdmi_reg_writeb(hdata, HDMI_VSI_CON, HDMI_VSI_CON_EVERY_VSYNC);
>> +            hdmi_reg_write_buf(hdata, HDMI_VSI_HEADER0, buf, ret);
> Also above codes should be called when 
> drm_hdmi_vendor_infoframe_from_display_mode function returned 0 and the value 
> from hdmi_vendor_infoframe_pack function is more than 1.
>
>> +    }
>>  
>> -            chksum = hdmi_chksum(hdata, HDMI_AVI_BYTE(1),
>> -                                    infoframe->any.length, hdr_sum);
>> -            DRM_DEBUG_KMS("AVI checksum = 0x%x\n", chksum);
>> -            hdmi_reg_writeb(hdata, HDMI_AVI_CHECK_SUM, chksum);
>> -            break;
>> -    case HDMI_INFOFRAME_TYPE_AUDIO:
>> -            hdmi_reg_writeb(hdata, HDMI_AUI_CON, 0x02);
>> -            hdmi_reg_writeb(hdata, HDMI_AUI_HEADER0, infoframe->any.type);
>> -            hdmi_reg_writeb(hdata, HDMI_AUI_HEADER1,
>> -                            infoframe->any.version);
>> -            hdmi_reg_writeb(hdata, HDMI_AUI_HEADER2, infoframe->any.length);
>> -            hdr_sum = infoframe->any.type + infoframe->any.version +
>> -                      infoframe->any.length;
>> -            chksum = hdmi_chksum(hdata, HDMI_AUI_BYTE(1),
>> -                                    infoframe->any.length, hdr_sum);
>> -            DRM_DEBUG_KMS("AUI checksum = 0x%x\n", chksum);
>> -            hdmi_reg_writeb(hdata, HDMI_AUI_CHECK_SUM, chksum);
>> -            break;
>> -    default:
>> -            break;
>> +    ret = hdmi_audio_infoframe_init(&frm.audio);
>> +    if (ret >= 0) {
> Ditto.
>
>> +            frm.audio.channels = 2;
>> +            ret = hdmi_audio_infoframe_pack(&frm.audio, buf, sizeof(buf));
>> +    }
>> +    if (ret > 0) {
>> +            hdmi_reg_writeb(hdata, HDMI_AUI_CON, HDMI_AUI_CON_EVERY_VSYNC);
>> +            hdmi_reg_write_buf(hdata, HDMI_AUI_HEADER0, buf, ret);
> Also above codes should be called when hdmi_audio_infoframe_init function 
> returned 0 and the value from hdmi_audio_infoframe_pack function is more than 
> 1.
>
>>      }
>>  }
>>  
>> @@ -1127,8 +1077,6 @@ static void hdmi_start(struct hdmi_context *hdata, 
>> bool start)
>>  
>>  static void hdmi_conf_init(struct hdmi_context *hdata)
>>  {
>> -    union hdmi_infoframe infoframe;
>> -
>>      /* disable HPD interrupts from HDMI IP block, use GPIO instead */
>>      hdmi_reg_writemask(hdata, HDMI_INTC_CON, 0, HDMI_INTC_EN_GLOBAL |
>>              HDMI_INTC_EN_HPD_PLUG | HDMI_INTC_EN_HPD_UNPLUG);
>> @@ -1164,15 +1112,7 @@ static void hdmi_conf_init(struct hdmi_context *hdata)
>>              hdmi_reg_writeb(hdata, HDMI_V13_AUI_CON, 0x02);
>>              hdmi_reg_writeb(hdata, HDMI_V13_ACR_CON, 0x04);
>>      } else {
>> -            infoframe.any.type = HDMI_INFOFRAME_TYPE_AVI;
>> -            infoframe.any.version = HDMI_AVI_VERSION;
>> -            infoframe.any.length = HDMI_AVI_LENGTH;
>> -            hdmi_reg_infoframe(hdata, &infoframe);
>> -
>> -            infoframe.any.type = HDMI_INFOFRAME_TYPE_AUDIO;
>> -            infoframe.any.version = HDMI_AUI_VERSION;
>> -            infoframe.any.length = HDMI_AUI_LENGTH;
>> -            hdmi_reg_infoframe(hdata, &infoframe);
>> +            hdmi_reg_infoframes(hdata);
>>  
>>              /* enable AVI packet every vsync, fixes purple line problem */
>>              hdmi_reg_writemask(hdata, HDMI_CON_1, 2, 3 << 5);
>> @@ -1458,7 +1398,6 @@ static void hdmi_mode_set(struct drm_encoder *encoder,
>>              "INTERLACED" : "PROGRESSIVE");
>>  
>>      drm_mode_copy(&hdata->current_mode, m);
>> -    hdata->cea_video_id = drm_match_cea_mode(mode);
>>  }
>>  
>>  static void hdmi_set_refclk(struct hdmi_context *hdata, bool on)
>> diff --git a/drivers/gpu/drm/exynos/regs-hdmi.h 
>> b/drivers/gpu/drm/exynos/regs-hdmi.h
>> index 169667a..a0507dc 100644
>> --- a/drivers/gpu/drm/exynos/regs-hdmi.h
>> +++ b/drivers/gpu/drm/exynos/regs-hdmi.h
>> @@ -361,9 +361,11 @@
>>  
>>  /* AUI bit definition */
>>  #define HDMI_AUI_CON_NO_TRAN                (0 << 0)
>> +#define HDMI_AUI_CON_EVERY_VSYNC    (1 << 1)
>>  
>>  /* VSI bit definition */
>>  #define HDMI_VSI_CON_DO_NOT_TRANSMIT        (0 << 0)
>> +#define HDMI_VSI_CON_EVERY_VSYNC    (1 << 1)
>>  
>>  /* HDCP related registers */
>>  #define HDMI_HDCP_SHA1(n)           HDMI_CORE_BASE(0x7000 + 4 * (n))
>>
>

Reply via email to