Skip to content

Commit

Permalink
Merge branch 'drm-intel-next' of git://people.freedesktop.org/~keithp…
Browse files Browse the repository at this point in the history
…/linux into drm-core-next

* 'drm-intel-next' of git://people.freedesktop.org/~keithp/linux:
  drm/i915: Dumb down the semaphore logic
  drm/i915: pass ELD to HDMI/DP audio driver
  drm: support routines for HDMI/DP ELD
  drm/i915: Enable dither whenever display bpc < frame buffer bpc
  drm/i915: Enable dither whenever display bpc < frame buffer bpc
  • Loading branch information
airlied committed Oct 10, 2011
2 parents 5438ae8 + 64a742f commit 62addcb
Show file tree
Hide file tree
Showing 13 changed files with 490 additions and 53 deletions.
171 changes: 171 additions & 0 deletions drivers/gpu/drm/drm_edid.c
Original file line number Diff line number Diff line change
Expand Up @@ -1319,6 +1319,7 @@ add_detailed_modes(struct drm_connector *connector, struct edid *edid,
#define HDMI_IDENTIFIER 0x000C03
#define AUDIO_BLOCK 0x01
#define VENDOR_BLOCK 0x03
#define SPEAKER_BLOCK 0x04
#define EDID_BASIC_AUDIO (1 << 6)

/**
Expand Down Expand Up @@ -1347,6 +1348,176 @@ u8 *drm_find_cea_extension(struct edid *edid)
}
EXPORT_SYMBOL(drm_find_cea_extension);

static void
parse_hdmi_vsdb(struct drm_connector *connector, uint8_t *db)
{
connector->eld[5] |= (db[6] >> 7) << 1; /* Supports_AI */

connector->dvi_dual = db[6] & 1;
connector->max_tmds_clock = db[7] * 5;

connector->latency_present[0] = db[8] >> 7;
connector->latency_present[1] = (db[8] >> 6) & 1;
connector->video_latency[0] = db[9];
connector->audio_latency[0] = db[10];
connector->video_latency[1] = db[11];
connector->audio_latency[1] = db[12];

DRM_LOG_KMS("HDMI: DVI dual %d, "
"max TMDS clock %d, "
"latency present %d %d, "
"video latency %d %d, "
"audio latency %d %d\n",
connector->dvi_dual,
connector->max_tmds_clock,
(int) connector->latency_present[0],
(int) connector->latency_present[1],
connector->video_latency[0],
connector->video_latency[1],
connector->audio_latency[0],
connector->audio_latency[1]);
}

static void
monitor_name(struct detailed_timing *t, void *data)
{
if (t->data.other_data.type == EDID_DETAIL_MONITOR_NAME)
*(u8 **)data = t->data.other_data.data.str.str;
}

/**
* drm_edid_to_eld - build ELD from EDID
* @connector: connector corresponding to the HDMI/DP sink
* @edid: EDID to parse
*
* Fill the ELD (EDID-Like Data) buffer for passing to the audio driver.
* Some ELD fields are left to the graphics driver caller:
* - Conn_Type
* - HDCP
* - Port_ID
*/
void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid)
{
uint8_t *eld = connector->eld;
u8 *cea;
u8 *name;
u8 *db;
int sad_count = 0;
int mnl;
int dbl;

memset(eld, 0, sizeof(connector->eld));

cea = drm_find_cea_extension(edid);
if (!cea) {
DRM_DEBUG_KMS("ELD: no CEA Extension found\n");
return;
}

name = NULL;
drm_for_each_detailed_block((u8 *)edid, monitor_name, &name);
for (mnl = 0; name && mnl < 13; mnl++) {
if (name[mnl] == 0x0a)
break;
eld[20 + mnl] = name[mnl];
}
eld[4] = (cea[1] << 5) | mnl;
DRM_DEBUG_KMS("ELD monitor %s\n", eld + 20);

eld[0] = 2 << 3; /* ELD version: 2 */

eld[16] = edid->mfg_id[0];
eld[17] = edid->mfg_id[1];
eld[18] = edid->prod_code[0];
eld[19] = edid->prod_code[1];

for (db = cea + 4; db < cea + cea[2]; db += dbl + 1) {
dbl = db[0] & 0x1f;

switch ((db[0] & 0xe0) >> 5) {
case AUDIO_BLOCK: /* Audio Data Block, contains SADs */
sad_count = dbl / 3;
memcpy(eld + 20 + mnl, &db[1], dbl);
break;
case SPEAKER_BLOCK: /* Speaker Allocation Data Block */
eld[7] = db[1];
break;
case VENDOR_BLOCK:
/* HDMI Vendor-Specific Data Block */
if (db[1] == 0x03 && db[2] == 0x0c && db[3] == 0)
parse_hdmi_vsdb(connector, db);
break;
default:
break;
}
}
eld[5] |= sad_count << 4;
eld[2] = (20 + mnl + sad_count * 3 + 3) / 4;

DRM_DEBUG_KMS("ELD size %d, SAD count %d\n", (int)eld[2], sad_count);
}
EXPORT_SYMBOL(drm_edid_to_eld);

/**
* drm_av_sync_delay - HDMI/DP sink audio-video sync delay in millisecond
* @connector: connector associated with the HDMI/DP sink
* @mode: the display mode
*/
int drm_av_sync_delay(struct drm_connector *connector,
struct drm_display_mode *mode)
{
int i = !!(mode->flags & DRM_MODE_FLAG_INTERLACE);
int a, v;

if (!connector->latency_present[0])
return 0;
if (!connector->latency_present[1])
i = 0;

a = connector->audio_latency[i];
v = connector->video_latency[i];

/*
* HDMI/DP sink doesn't support audio or video?
*/
if (a == 255 || v == 255)
return 0;

/*
* Convert raw EDID values to millisecond.
* Treat unknown latency as 0ms.
*/
if (a)
a = min(2 * (a - 1), 500);
if (v)
v = min(2 * (v - 1), 500);

return max(v - a, 0);
}
EXPORT_SYMBOL(drm_av_sync_delay);

/**
* drm_select_eld - select one ELD from multiple HDMI/DP sinks
* @encoder: the encoder just changed display mode
* @mode: the adjusted display mode
*
* It's possible for one encoder to be associated with multiple HDMI/DP sinks.
* The policy is now hard coded to simply use the first HDMI/DP sink's ELD.
*/
struct drm_connector *drm_select_eld(struct drm_encoder *encoder,
struct drm_display_mode *mode)
{
struct drm_connector *connector;
struct drm_device *dev = encoder->dev;

list_for_each_entry(connector, &dev->mode_config.connector_list, head)
if (connector->encoder == encoder && connector->eld[0])
return connector;

return NULL;
}
EXPORT_SYMBOL(drm_select_eld);

/**
* drm_detect_hdmi_monitor - detect whether monitor is hdmi.
* @edid: monitor EDID information
Expand Down
2 changes: 2 additions & 0 deletions drivers/gpu/drm/i915/i915_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,8 @@ struct drm_i915_display_funcs {
struct drm_display_mode *adjusted_mode,
int x, int y,
struct drm_framebuffer *old_fb);
void (*write_eld)(struct drm_connector *connector,
struct drm_crtc *crtc);
void (*fdi_link_train)(struct drm_crtc *crtc);
void (*init_clock_gating)(struct drm_device *dev);
void (*init_pch_clock_gating)(struct drm_device *dev);
Expand Down
3 changes: 2 additions & 1 deletion drivers/gpu/drm/i915/i915_gem_execbuffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -784,7 +784,8 @@ i915_gem_execbuffer_sync_rings(struct drm_i915_gem_object *obj,
}

from->sync_seqno[idx] = seqno;
return intel_ring_sync(to, from, seqno - 1);

return to->sync_to(to, from, seqno - 1);
}

static int
Expand Down
38 changes: 38 additions & 0 deletions drivers/gpu/drm/i915/i915_reg.h
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,13 @@
#define MI_SEMAPHORE_UPDATE (1<<21)
#define MI_SEMAPHORE_COMPARE (1<<20)
#define MI_SEMAPHORE_REGISTER (1<<18)
#define MI_SEMAPHORE_SYNC_RV (2<<16)
#define MI_SEMAPHORE_SYNC_RB (0<<16)
#define MI_SEMAPHORE_SYNC_VR (0<<16)
#define MI_SEMAPHORE_SYNC_VB (2<<16)
#define MI_SEMAPHORE_SYNC_BR (2<<16)
#define MI_SEMAPHORE_SYNC_BV (0<<16)
#define MI_SEMAPHORE_SYNC_INVALID (1<<0)
/*
* 3D instructions used by the kernel
*/
Expand Down Expand Up @@ -296,6 +303,12 @@
#define RING_CTL(base) ((base)+0x3c)
#define RING_SYNC_0(base) ((base)+0x40)
#define RING_SYNC_1(base) ((base)+0x44)
#define GEN6_RVSYNC (RING_SYNC_0(RENDER_RING_BASE))
#define GEN6_RBSYNC (RING_SYNC_1(RENDER_RING_BASE))
#define GEN6_VRSYNC (RING_SYNC_1(GEN6_BSD_RING_BASE))
#define GEN6_VBSYNC (RING_SYNC_0(GEN6_BSD_RING_BASE))
#define GEN6_BRSYNC (RING_SYNC_0(BLT_RING_BASE))
#define GEN6_BVSYNC (RING_SYNC_1(BLT_RING_BASE))
#define RING_MAX_IDLE(base) ((base)+0x54)
#define RING_HWS_PGA(base) ((base)+0x80)
#define RING_HWS_PGA_GEN6(base) ((base)+0x2080)
Expand Down Expand Up @@ -3470,4 +3483,29 @@
#define GEN6_PCODE_DATA 0x138128
#define GEN6_PCODE_FREQ_IA_RATIO_SHIFT 8

#define G4X_AUD_VID_DID 0x62020
#define INTEL_AUDIO_DEVCL 0x808629FB
#define INTEL_AUDIO_DEVBLC 0x80862801
#define INTEL_AUDIO_DEVCTG 0x80862802

#define G4X_AUD_CNTL_ST 0x620B4
#define G4X_ELDV_DEVCL_DEVBLC (1 << 13)
#define G4X_ELDV_DEVCTG (1 << 14)
#define G4X_ELD_ADDR (0xf << 5)
#define G4X_ELD_ACK (1 << 4)
#define G4X_HDMIW_HDMIEDID 0x6210C

#define GEN5_HDMIW_HDMIEDID_A 0xE2050
#define GEN5_AUD_CNTL_ST_A 0xE20B4
#define GEN5_ELD_BUFFER_SIZE (0x1f << 10)
#define GEN5_ELD_ADDRESS (0x1f << 5)
#define GEN5_ELD_ACK (1 << 4)
#define GEN5_AUD_CNTL_ST2 0xE20C0
#define GEN5_ELD_VALIDB (1 << 0)
#define GEN5_CP_READYB (1 << 1)

#define GEN7_HDMIW_HDMIEDID_A 0xE5050
#define GEN7_AUD_CNTRL_ST_A 0xE50B4
#define GEN7_AUD_CNTRL_ST2 0xE50C0

#endif /* _I915_REG_H_ */
Loading

0 comments on commit 62addcb

Please sign in to comment.