2016년 11월 07일 17:05에 Andrzej Hajda 이(가) 쓴 글:
> 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.

As I mentioned, never return bigger than 0. Let's change it to !ret or ret == 0.

>>
>>> +           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'.

Because hdmi_avi_infoframe_pack returns 0 or bigger than 0. Anyway, seems you 
are saying exactly same thing.

> 
>>
>>> -           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.

Right. The condition, "ret >= 0" made me confusing.

> 
> 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