Advertisement
Guest User

Untitled

a guest
Sep 24th, 2017
80
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Diff 17.80 KB | None | 0 0
  1. Subject: pass ELD to HDMI/DP audio driver
  2. Date: Fri May 20 19:59:33 CST 2011
  3.  
  4. Add ELD support for Eaglelake, IbexPeak/Ironlake and SandyBridge/CougarPoint.
  5.  
  6. ELD (EDID-Like Data) describes to the HDMI/DP audio driver the audio
  7. capabilities of the plugged monitor. It's built and passed to audio
  8. driver in 2 steps:
  9.  
  10. (1) at get_modes time, parse EDID and save ELD to drm_connector.eld[]
  11.  
  12. (2) at mode_set time, write drm_connector.eld[] to the Transcoder's hw
  13.     ELD buffer and set the ELD_valid bit to inform HDMI/DP audio driver
  14.  
  15. ELD selection policy: it's possible for one encoder to be associated
  16. with multiple connectors (ie. monitors), in which case the first found
  17. ELD will be used. This policy may not be suitable for all users, but
  18. let's start it simple first.
  19.  
  20. The impact of ELD selection policy: assume there are two monitors, one
  21. supports stereo playback and the other has 8-channel output; cloned
  22. display mode is used, so that the two monitors are associated with the
  23. same internal encoder. If only the stereo playback capability is reported,
  24. the user won't be able to start 8-channel playback; if the 8-channel ELD
  25. is reported, then user space applications may send 8-channel samples
  26. down, however the user may actually be listening to the 2-channel
  27. monitor and not connecting speakers to the 8-channel monitor. Overall,
  28. it's more safe to report maximum profiles to the user space, so that
  29. the user can at least be able to do 8-channel playback if he want to.
  30.  
  31. This patch is tested OK on G45/HDMI and IbexPeak/HDMI. DisplayPort is
  32. tested on several IbexPeak and Sandybridge boxes, however not working,
  33. possibly due to hardware/monitor problems.
  34.  
  35. One known problem is that the GEN6_AUD_CNTL_ST/DIP_Port_Select field
  36. is always 0 (reserved). Without knowing the port number, I worked it
  37. around by setting the ELD_valid bit for ALL the three ports.
  38.  
  39. CC: Zhao Yakui <yakui.zhao@intel.com>
  40. CC: Wang Zhenyu <zhenyu.z.wang@intel.com>
  41. CC: Jeremy Bush <contractfrombelow@gmail.com>
  42. CC: Christopher White <c.white@pulseforce.com>
  43. CC: "Bossart, Pierre-louis" <pierre-louis.bossart@intel.com>
  44. Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
  45. Signed-off-by: Wu Fengguang <fengguang.wu@intel.com>
  46. ---
  47. drivers/gpu/drm/drm_edid.c           |  171 +++++++++++++++++++++++++
  48.  drivers/gpu/drm/i915/i915_drv.h      |    2
  49.  drivers/gpu/drm/i915/i915_reg.h      |   20 ++
  50.  drivers/gpu/drm/i915/intel_display.c |  118 +++++++++++++++++
  51.  drivers/gpu/drm/i915/intel_dp.c      |    2
  52.  drivers/gpu/drm/i915/intel_drv.h     |    3
  53.  drivers/gpu/drm/i915/intel_hdmi.c    |    2
  54.  drivers/gpu/drm/i915/intel_modes.c   |    2
  55.  include/drm/drm_crtc.h               |    9 +
  56.  include/drm/drm_edid.h               |    9 +
  57.  10 files changed, 338 insertions(+)
  58.  
  59. --- linux.orig/drivers/gpu/drm/drm_edid.c   2011-07-14 08:47:29.000000000 -0700
  60. +++ linux/drivers/gpu/drm/drm_edid.c    2011-07-15 09:16:08.000000000 -0700
  61. @@ -1307,6 +1307,7 @@ add_detailed_modes(struct drm_connector
  62.  #define HDMI_IDENTIFIER 0x000C03
  63.  #define AUDIO_BLOCK    0x01
  64.  #define VENDOR_BLOCK    0x03
  65. +#define SPEAKER_BLOCK  0x04
  66.  #define EDID_BASIC_AUDIO   (1 << 6)
  67.  
  68.  /**
  69. @@ -1335,6 +1336,176 @@ u8 *drm_find_cea_extension(struct edid *
  70.  }
  71.  EXPORT_SYMBOL(drm_find_cea_extension);
  72.  
  73. +static void
  74. +parse_hdmi_vsdb(struct drm_connector *connector, uint8_t *db)
  75. +{
  76. +   connector->eld[5] |= (db[6] >> 7) << 1;  /* Supports_AI */
  77. +
  78. +   connector->dvi_dual = db[6] & 1;
  79. +   connector->max_tmds_clock = db[7] * 5;
  80. +
  81. +   connector->latency_present[0] = db[8] >> 7;
  82. +   connector->latency_present[1] = (db[8] >> 6) & 1;
  83. +   connector->video_latency[0] = db[9];
  84. +   connector->audio_latency[0] = db[10];
  85. +   connector->video_latency[1] = db[11];
  86. +   connector->audio_latency[1] = db[12];
  87. +
  88. +   DRM_LOG_KMS("HDMI: DVI dual %d, "
  89. +           "max TMDS clock %d, "
  90. +           "latency present %d %d, "
  91. +           "video latency %d %d, "
  92. +           "audio latency %d %d\n",
  93. +           connector->dvi_dual,
  94. +           connector->max_tmds_clock,
  95. +         (int) connector->latency_present[0],
  96. +         (int) connector->latency_present[1],
  97. +           connector->video_latency[0],
  98. +           connector->video_latency[1],
  99. +           connector->audio_latency[0],
  100. +           connector->audio_latency[1]);
  101. +}
  102. +
  103. +static void
  104. +monitor_name(struct detailed_timing *t, void *data)
  105. +{
  106. +   if (t->data.other_data.type == EDID_DETAIL_MONITOR_NAME)
  107. +       *(u8 **)data = t->data.other_data.data.str.str;
  108. +}
  109. +
  110. +/**
  111. + * drm_edid_to_eld - build ELD from EDID
  112. + * @connector: connector corresponding to the HDMI/DP sink
  113. + * @edid: EDID to parse
  114. + *
  115. + * Fill the ELD (EDID-Like Data) buffer for passing to the audio driver.
  116. + * Some ELD fields are left to the graphics driver caller:
  117. + * - Conn_Type
  118. + * - HDCP
  119. + * - Port_ID
  120. + */
  121. +void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid)
  122. +{
  123. +   uint8_t *eld = connector->eld;
  124. +   u8 *cea;
  125. +   u8 *name;
  126. +   u8 *db;
  127. +   int sad_count = 0;
  128. +   int mnl;
  129. +   int dbl;
  130. +
  131. +   memset(eld, 0, sizeof(connector->eld));
  132. +
  133. +   cea = drm_find_cea_extension(edid);
  134. +   if (!cea) {
  135. +       DRM_DEBUG_KMS("ELD: no CEA Extension found\n");
  136. +       return;
  137. +   }
  138. +
  139. +   name = NULL;
  140. +   drm_for_each_detailed_block((u8 *)edid, monitor_name, &name);
  141. +   for (mnl = 0; name && mnl < 13; mnl++) {
  142. +       if (name[mnl] == 0x0a)
  143. +           break;
  144. +       eld[20 + mnl] = name[mnl];
  145. +   }
  146. +   eld[4] = (cea[1] << 5) | mnl;
  147. +   DRM_DEBUG_KMS("ELD monitor %s\n", eld + 20);
  148. +
  149. +   eld[0] = 2 << 3;        /* ELD version: 2 */
  150. +
  151. +   eld[16] = edid->mfg_id[0];
  152. +   eld[17] = edid->mfg_id[1];
  153. +   eld[18] = edid->prod_code[0];
  154. +   eld[19] = edid->prod_code[1];
  155. +
  156. +   for (db = cea + 4; db < cea + cea[2]; db += dbl + 1) {
  157. +       dbl = db[0] & 0x1f;
  158. +
  159. +       switch ((db[0] & 0xe0) >> 5) {
  160. +       case AUDIO_BLOCK:   /* Audio Data Block, contains SADs */
  161. +           sad_count = dbl / 3;
  162. +           memcpy(eld + 20 + mnl, &db[1], dbl);
  163. +           break;
  164. +       case SPEAKER_BLOCK: /* Speaker Allocation Data Block */
  165. +           eld[7] = db[1];
  166. +           break;
  167. +       case VENDOR_BLOCK:
  168. +           /* HDMI Vendor-Specific Data Block */
  169. +           if (db[1] == 0x03 && db[2] == 0x0c && db[3] == 0)
  170. +               parse_hdmi_vsdb(connector, db);
  171. +           break;
  172. +       default:
  173. +           break;
  174. +       }
  175. +   }
  176. +   eld[5] |= sad_count << 4;
  177. +   eld[2] = (20 + mnl + sad_count * 3 + 3) / 4;
  178. +
  179. +   DRM_DEBUG_KMS("ELD size %d, SAD count %d\n", (int)eld[2], sad_count);
  180. +}
  181. +EXPORT_SYMBOL(drm_edid_to_eld);
  182. +
  183. +/**
  184. + * drm_av_sync_delay - HDMI/DP sink audio-video sync delay in milli-seconds
  185. + * @connector: connector associated with the HDMI/DP sink
  186. + * @mode: the display mode
  187. + */
  188. +int drm_av_sync_delay(struct drm_connector *connector,
  189. +             struct drm_display_mode *mode)
  190. +{
  191. +   int i = !!(mode->flags & DRM_MODE_FLAG_INTERLACE);
  192. +   int a, v;
  193. +
  194. +   if (!connector->latency_present[0])
  195. +       return 0;
  196. +   if (!connector->latency_present[1])
  197. +       i = 0;
  198. +
  199. +   a = connector->audio_latency[i];
  200. +   v = connector->video_latency[i];
  201. +
  202. +   /*
  203. +    * HDMI/DP sink doesn't support audio or video?
  204. +    */
  205. +   if (a == 255 || v == 255)
  206. +       return 0;
  207. +
  208. +   /*
  209. +    * Convert raw edid values to milli-seconds.
  210. +    * Treat unknown latency as 0ms.
  211. +    */
  212. +   if (a)
  213. +       a = min(2 * (a - 1), 500);
  214. +   if (v)
  215. +       v = min(2 * (v - 1), 500);
  216. +
  217. +   return max(v - a, 0);
  218. +}
  219. +EXPORT_SYMBOL(drm_av_sync_delay);
  220. +
  221. +/**
  222. + * drm_select_eld - select one ELD from multiple HDMI/DP sinks
  223. + * @encoder: the encoder just changed display mode
  224. + * @mode: the adjusted display mode
  225. + *
  226. + * It's possible for one encoder to be associated with multiple HDMI/DP sinks.
  227. + * The policy is now hard coded to simply use the first HDMI/DP sink's ELD.
  228. + */
  229. +struct drm_connector *drm_select_eld(struct drm_encoder *encoder,
  230. +                    struct drm_display_mode *mode)
  231. +{
  232. +   struct drm_connector *connector;
  233. +   struct drm_device *dev = encoder->dev;
  234. +
  235. +   list_for_each_entry(connector, &dev->mode_config.connector_list, head)
  236. +       if (connector->encoder == encoder)
  237. +           return connector;
  238. +
  239. +   return NULL;
  240. +}
  241. +EXPORT_SYMBOL(drm_select_eld);
  242. +
  243.  /**
  244.   * drm_detect_hdmi_monitor - detect whether monitor is hdmi.
  245.   * @edid: monitor EDID information
  246. --- linux.orig/drivers/gpu/drm/i915/intel_hdmi.c    2011-07-14 08:47:29.000000000 -0700
  247. +++ linux/drivers/gpu/drm/i915/intel_hdmi.c 2011-07-15 09:16:08.000000000 -0700
  248. @@ -150,6 +150,8 @@ static void intel_hdmi_mode_set(struct d
  249.     POSTING_READ(intel_hdmi->sdvox_reg);
  250.  
  251.     intel_hdmi_set_avi_infoframe(encoder);
  252. +
  253. +   intel_write_eld(encoder, crtc, adjusted_mode);
  254.  }
  255.  
  256.  static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode)
  257. --- linux.orig/include/drm/drm_edid.h   2011-07-14 08:47:38.000000000 -0700
  258. +++ linux/include/drm/drm_edid.h    2011-07-15 09:16:08.000000000 -0700
  259. @@ -230,4 +230,13 @@ struct edid {
  260.  
  261.  #define EDID_PRODUCT_ID(e) ((e)->prod_code[0] | ((e)->prod_code[1] << 8))
  262.  
  263. +struct drm_encoder;
  264. +struct drm_connector;
  265. +struct drm_display_mode;
  266. +void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid);
  267. +int drm_av_sync_delay(struct drm_connector *connector,
  268. +             struct drm_display_mode *mode);
  269. +struct drm_connector *drm_select_eld(struct drm_encoder *encoder,
  270. +                    struct drm_display_mode *mode);
  271. +
  272.  #endif /* __DRM_EDID_H__ */
  273. --- linux.orig/drivers/gpu/drm/i915/intel_display.c 2011-07-14 08:47:29.000000000 -0700
  274. +++ linux/drivers/gpu/drm/i915/intel_display.c  2011-07-15 09:16:08.000000000 -0700
  275. @@ -30,6 +30,7 @@
  276.  #include <linux/kernel.h>
  277.  #include <linux/slab.h>
  278.  #include <linux/vgaarb.h>
  279. +#include <drm/drm_edid.h>
  280.  #include "drmP.h"
  281.  #include "intel_drv.h"
  282.  #include "i915_drm.h"
  283. @@ -5248,6 +5249,120 @@ static int intel_crtc_mode_set(struct dr
  284.     return ret;
  285.  }
  286.  
  287. +static void g4x_write_eld(struct drm_connector *connector,
  288. +             struct drm_crtc *crtc)
  289. +{
  290. +   struct drm_i915_private *dev_priv = connector->dev->dev_private;
  291. +   uint8_t *eld = connector->eld;
  292. +   uint32_t eldv;
  293. +   uint32_t len;
  294. +   uint32_t i;
  295. +
  296. +   i = I915_READ(G4X_AUD_VID_DID);
  297. +
  298. +   if (i == INTEL_AUDIO_DEVBLC || i == INTEL_AUDIO_DEVCL)
  299. +       eldv = G4X_ELDV_DEVCL_DEVBLC;
  300. +   else
  301. +       eldv = G4X_ELDV_DEVCTG;
  302. +
  303. +   i = I915_READ(G4X_AUD_CNTL_ST);
  304. +   i &= ~(eldv | G4X_ELD_ADDR);
  305. +   len = (i >> 9) & 0x1f;      /* ELD buffer size */
  306. +   I915_WRITE(G4X_AUD_CNTL_ST, i);
  307. +
  308. +   if (!eld[0])
  309. +       return;
  310. +
  311. +   len = min_t(uint8_t, eld[2], len);
  312. +   for (i = 0; i < len; i++)
  313. +       I915_WRITE(G4X_HDMIW_HDMIEDID, *((uint32_t *)eld + i));
  314. +
  315. +   i = I915_READ(G4X_AUD_CNTL_ST);
  316. +   i |= eldv;
  317. +   I915_WRITE(G4X_AUD_CNTL_ST, i);
  318. +}
  319. +
  320. +static void ironlake_write_eld(struct drm_connector *connector,
  321. +                    struct drm_crtc *crtc)
  322. +{
  323. +   struct drm_i915_private *dev_priv = connector->dev->dev_private;
  324. +   uint8_t *eld = connector->eld;
  325. +   uint32_t eldv;
  326. +   uint32_t i;
  327. +   int len;
  328. +   int hdmiw_hdmiedid;
  329. +   int aud_cntl_st;
  330. +
  331. +   i = to_intel_crtc(crtc)->pipe;
  332. +   hdmiw_hdmiedid = GEN6_HDMIW_HDMIEDID_A + i * 0x100;
  333. +   aud_cntl_st = GEN6_AUD_CNTL_ST_A + i * 0x100;
  334. +
  335. +   DRM_DEBUG_DRIVER("ELD on pipe %c\n", pipe_name(i));
  336. +
  337. +   i = I915_READ(aud_cntl_st);
  338. +   i = (i >> 29) & 0x3;        /* DIP_Port_Select, 0x1 = PortB */
  339. +   if (!i) {
  340. +       DRM_DEBUG_DRIVER("Audio directed to unknown port\n");
  341. +       /* operate blindly on all ports */
  342. +       eldv = GEN6_ELD_VALIDB;
  343. +       eldv |= GEN6_ELD_VALIDB << 4;
  344. +       eldv |= GEN6_ELD_VALIDB << 8;
  345. +   } else {
  346. +       DRM_DEBUG_DRIVER("ELD on port %c\n", 'A' + i);
  347. +       eldv = GEN6_ELD_VALIDB << ((i - 1) * 4);
  348. +   }
  349. +
  350. +   i = I915_READ(GEN6_AUD_CNTL_ST2);
  351. +   i &= ~eldv;
  352. +   I915_WRITE(GEN6_AUD_CNTL_ST2, i);
  353. +
  354. +   if (!eld[0])
  355. +       return;
  356. +
  357. +   if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) {
  358. +       DRM_DEBUG_DRIVER("ELD: DisplayPort detected\n");
  359. +       eld[5] |= (1 << 2); /* Conn_Type, 0x1 = DisplayPort */
  360. +   }
  361. +
  362. +   i = I915_READ(aud_cntl_st);
  363. +   i &= ~GEN6_ELD_ADDRESS;
  364. +   len = (i & GEN6_ELD_BUFFER_SIZE) >> 10;
  365. +   len = min_t(uint8_t, eld[2], len);
  366. +   DRM_DEBUG_DRIVER("ELD size %d\n", len);
  367. +   I915_WRITE(aud_cntl_st, i);
  368. +
  369. +   for (i = 0; i < len; i++)
  370. +       I915_WRITE(hdmiw_hdmiedid, *((uint32_t *)eld + i));
  371. +
  372. +   i = I915_READ(GEN6_AUD_CNTL_ST2);
  373. +   i |= eldv;
  374. +   I915_WRITE(GEN6_AUD_CNTL_ST2, i);
  375. +}
  376. +
  377. +void intel_write_eld(struct drm_encoder *encoder,
  378. +            struct drm_crtc *crtc,
  379. +            struct drm_display_mode *mode)
  380. +{
  381. +   struct drm_connector *connector;
  382. +   struct drm_device *dev = encoder->dev;
  383. +   struct drm_i915_private *dev_priv = dev->dev_private;
  384. +
  385. +   connector = drm_select_eld(encoder, mode);
  386. +   if (!connector)
  387. +       return;
  388. +
  389. +   DRM_DEBUG_DRIVER("ELD on [CONNECTOR:%d:%s], [ENCODER:%d:%s]\n",
  390. +            connector->base.id,
  391. +            drm_get_connector_name(connector),
  392. +            connector->encoder->base.id,
  393. +            drm_get_encoder_name(connector->encoder));
  394. +
  395. +   connector->eld[6] = drm_av_sync_delay(connector, mode) / 2;
  396. +
  397. +   if (dev_priv->display.write_eld)
  398. +       dev_priv->display.write_eld(connector, crtc);
  399. +}
  400. +
  401.  /** Loads the palette/gamma unit for the CRTC with the prepared values */
  402.  void intel_crtc_load_lut(struct drm_crtc *crtc)
  403.  {
  404. @@ -7701,6 +7816,7 @@ static void intel_init_display(struct dr
  405.             }
  406.             dev_priv->display.fdi_link_train = ironlake_fdi_link_train;
  407.             dev_priv->display.init_clock_gating = ironlake_init_clock_gating;
  408. +           dev_priv->display.write_eld = ironlake_write_eld;
  409.         } else if (IS_GEN6(dev)) {
  410.             if (SNB_READ_WM0_LATENCY()) {
  411.                 dev_priv->display.update_wm = sandybridge_update_wm;
  412. @@ -7711,6 +7827,7 @@ static void intel_init_display(struct dr
  413.             }
  414.             dev_priv->display.fdi_link_train = gen6_fdi_link_train;
  415.             dev_priv->display.init_clock_gating = gen6_init_clock_gating;
  416. +           dev_priv->display.write_eld = ironlake_write_eld;
  417.         } else if (IS_IVYBRIDGE(dev)) {
  418.             /* FIXME: detect B0+ stepping and use auto training */
  419.             dev_priv->display.fdi_link_train = ivb_manual_fdi_link_train;
  420. @@ -7742,6 +7859,7 @@ static void intel_init_display(struct dr
  421.             dev_priv->display.update_wm = pineview_update_wm;
  422.         dev_priv->display.init_clock_gating = gen3_init_clock_gating;
  423.     } else if (IS_G4X(dev)) {
  424. +       dev_priv->display.write_eld = g4x_write_eld;
  425.         dev_priv->display.update_wm = g4x_update_wm;
  426.         dev_priv->display.init_clock_gating = g4x_init_clock_gating;
  427.     } else if (IS_GEN4(dev)) {
  428. --- linux.orig/drivers/gpu/drm/i915/i915_reg.h  2011-07-14 08:47:29.000000000 -0700
  429. +++ linux/drivers/gpu/drm/i915/i915_reg.h   2011-07-15 09:16:08.000000000 -0700
  430. @@ -3437,4 +3437,24 @@
  431.  #define   GEN6_PCODE_WRITE_MIN_FREQ_TABLE  0x9
  432.  #define GEN6_PCODE_DATA                0x138128
  433.  
  434. +#define G4X_AUD_VID_DID            0x62020
  435. +#define INTEL_AUDIO_DEVCL      0x808629FB
  436. +#define INTEL_AUDIO_DEVBLC     0x80862801
  437. +#define INTEL_AUDIO_DEVCTG     0x80862802
  438. +
  439. +#define G4X_AUD_CNTL_ST            0x620B4
  440. +#define G4X_ELDV_DEVCL_DEVBLC      (1 << 13)
  441. +#define G4X_ELDV_DEVCTG            (1 << 14)
  442. +#define G4X_ELD_ADDR           (0xf << 5)
  443. +#define G4X_ELD_ACK            (1 << 4)
  444. +#define G4X_HDMIW_HDMIEDID     0x6210C
  445. +#define GEN6_HDMIW_HDMIEDID_A      0xE2050
  446. +#define GEN6_AUD_CNTL_ST_A     0xE20B4
  447. +#define GEN6_ELD_BUFFER_SIZE       (0x1f << 10)
  448. +#define GEN6_ELD_ADDRESS       (0x1f << 5)
  449. +#define GEN6_ELD_ACK           (1 << 4)
  450. +#define GEN6_AUD_CNTL_ST2      0xE20C0
  451. +#define GEN6_ELD_VALIDB            (1 << 0)
  452. +#define GEN6_CP_READYB         (1 << 1)
  453. +
  454.  #endif /* _I915_REG_H_ */
  455. --- linux.orig/drivers/gpu/drm/i915/intel_drv.h 2011-07-14 08:47:29.000000000 -0700
  456. +++ linux/drivers/gpu/drm/i915/intel_drv.h  2011-07-15 09:16:08.000000000 -0700
  457. @@ -347,4 +347,7 @@ extern void intel_fb_output_poll_changed
  458.  extern void intel_fb_restore_mode(struct drm_device *dev);
  459.  
  460.  extern void intel_init_clock_gating(struct drm_device *dev);
  461. +extern void intel_write_eld(struct drm_encoder *encoder,
  462. +               struct drm_crtc *crtc,
  463. +               struct drm_display_mode *mode);
  464.  #endif /* __INTEL_DRV_H__ */
  465. --- linux.orig/drivers/gpu/drm/i915/intel_modes.c   2011-07-14 08:47:29.000000000 -0700
  466. +++ linux/drivers/gpu/drm/i915/intel_modes.c    2011-07-15 09:16:08.000000000 -0700
  467. @@ -26,6 +26,7 @@
  468.  #include <linux/slab.h>
  469.  #include <linux/i2c.h>
  470.  #include <linux/fb.h>
  471. +#include <drm/drm_edid.h>
  472.  #include "drmP.h"
  473.  #include "intel_drv.h"
  474.  #include "i915_drv.h"
  475. @@ -74,6 +75,7 @@ int intel_ddc_get_modes(struct drm_conne
  476.     if (edid) {
  477.         drm_mode_connector_update_edid_property(connector, edid);
  478.         ret = drm_add_edid_modes(connector, edid);
  479. +       drm_edid_to_eld(connector, edid);
  480.         connector->display_info.raw_edid = NULL;
  481.         kfree(edid);
  482.     }
  483. --- linux.orig/include/drm/drm_crtc.h   2011-07-14 08:47:38.000000000 -0700
  484. +++ linux/include/drm/drm_crtc.h    2011-07-15 09:16:08.000000000 -0700
  485. @@ -464,6 +464,8 @@ enum drm_connector_force {
  486.  /* DACs should rarely do this without a lot of testing */
  487.  #define DRM_CONNECTOR_POLL_DISCONNECT (1 << 2)
  488.  
  489. +#define MAX_ELD_BYTES  128
  490. +
  491.  /**
  492.   * drm_connector - central DRM connector control structure
  493.   * @crtc: CRTC this connector is currently connected to, NULL if none
  494. @@ -521,6 +523,13 @@ struct drm_connector {
  495.     uint32_t force_encoder_id;
  496.     struct drm_encoder *encoder; /* currently active encoder */
  497.  
  498. +   /* EDID bits */
  499. +   uint8_t eld[MAX_ELD_BYTES];
  500. +   bool dvi_dual;
  501. +   int max_tmds_clock; /* in MHz */
  502. +   bool latency_present[2];
  503. +   int video_latency[2];   /* [0]: progressive, [1]: interlaced */
  504. +   int audio_latency[2];
  505.     int null_edid_counter; /* needed to workaround some HW bugs where we get all 0s */
  506.  };
  507.  
  508. --- linux.orig/drivers/gpu/drm/i915/intel_dp.c  2011-07-14 08:47:29.000000000 -0700
  509. +++ linux/drivers/gpu/drm/i915/intel_dp.c   2011-07-15 09:16:08.000000000 -0700
  510. @@ -791,6 +791,8 @@ intel_dp_mode_set(struct drm_encoder *en
  511.         else
  512.             intel_dp->DP |= DP_PLL_FREQ_270MHZ;
  513.     }
  514. +
  515. +   intel_write_eld(encoder, crtc, adjusted_mode);
  516.  }
  517.  
  518.  static void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp)
  519. --- linux.orig/drivers/gpu/drm/i915/i915_drv.h  2011-07-14 08:47:29.000000000 -0700
  520. +++ linux/drivers/gpu/drm/i915/i915_drv.h   2011-07-15 09:16:08.000000000 -0700
  521. @@ -208,6 +208,8 @@ struct drm_i915_display_funcs {
  522.                  struct drm_display_mode *adjusted_mode,
  523.                  int x, int y,
  524.                  struct drm_framebuffer *old_fb);
  525. +   void (*write_eld)(struct drm_connector *connector,
  526. +             struct drm_crtc *crtc);
  527.     void (*fdi_link_train)(struct drm_crtc *crtc);
  528.     void (*init_clock_gating)(struct drm_device *dev);
  529.     void (*init_pch_clock_gating)(struct drm_device *dev);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement