static enum drm_connector_status intel_hdmi_detect(struct drm_connector *connector, bool force) { struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector); struct drm_i915_private *dev_priv = connector->dev->dev_private; struct edid *edid; enum drm_connector_status status = connector_status_disconnected; intel_hdmi->has_hdmi_sink = false; intel_hdmi->has_audio = false; edid = drm_get_edid(connector, intel_gmbus_get_adapter(dev_priv, intel_hdmi->ddc_bus)); if (edid) { if (edid->input & DRM_EDID_INPUT_DIGITAL) { status = connector_status_connected; if (intel_hdmi->force_audio != HDMI_AUDIO_OFF_DVI) intel_hdmi->has_hdmi_sink = drm_detect_hdmi_monitor(edid); intel_hdmi->has_audio = drm_detect_monitor_audio(edid); } kfree(edid); } if (status == connector_status_connected) { if (intel_hdmi->force_audio != HDMI_AUDIO_AUTO) intel_hdmi->has_audio = (intel_hdmi->force_audio == HDMI_AUDIO_ON); } return status; }
static int tda998x_connector_get_modes(struct drm_connector *connector) { struct tda998x_priv *priv = conn_to_tda998x_priv(connector); struct edid *edid; int n; /* * If we get killed while waiting for the HPD timeout, return * no modes found: we are not in a restartable path, so we * can't handle signals gracefully. */ if (tda998x_edid_delay_wait(priv)) return 0; if (priv->rev == TDA19988) reg_clear(priv, REG_TX4, TX4_PD_RAM); edid = drm_do_get_edid(connector, read_edid_block, priv); if (priv->rev == TDA19988) reg_set(priv, REG_TX4, TX4_PD_RAM); if (!edid) { dev_warn(&priv->hdmi->dev, "failed to read EDID\n"); return 0; } drm_mode_connector_update_edid_property(connector, edid); n = drm_add_edid_modes(connector, edid); priv->is_hdmi_sink = drm_detect_hdmi_monitor(edid); kfree(edid); return n; }
static enum drm_connector_status cdv_hdmi_detect( struct drm_connector *connector, bool force) { struct psb_intel_encoder *psb_intel_encoder = psb_intel_attached_encoder(connector); struct psb_intel_connector *psb_intel_connector = to_psb_intel_connector(connector); struct mid_intel_hdmi_priv *hdmi_priv = psb_intel_encoder->dev_priv; struct edid *edid = NULL; enum drm_connector_status status = connector_status_disconnected; edid = drm_get_edid(connector, &psb_intel_encoder->i2c_bus->adapter); hdmi_priv->has_hdmi_sink = false; hdmi_priv->has_hdmi_audio = false; if (edid) { if (edid->input & DRM_EDID_INPUT_DIGITAL) { status = connector_status_connected; hdmi_priv->has_hdmi_sink = drm_detect_hdmi_monitor(edid); hdmi_priv->has_hdmi_audio = drm_detect_monitor_audio(edid); } psb_intel_connector->base.display_info.raw_edid = NULL; kfree(edid); } return status; }
static int tda998x_encoder_get_modes(struct tda998x_priv *priv, struct drm_connector *connector) { struct edid *edid; int n; if (priv->rev == TDA19988) reg_clear(priv, REG_TX4, TX4_PD_RAM); edid = drm_do_get_edid(connector, read_edid_block, priv); if (priv->rev == TDA19988) reg_set(priv, REG_TX4, TX4_PD_RAM); if (!edid) { dev_warn(&priv->hdmi->dev, "failed to read EDID\n"); return 0; } drm_mode_connector_update_edid_property(connector, edid); n = drm_add_edid_modes(connector, edid); priv->is_hdmi_sink = drm_detect_hdmi_monitor(edid); kfree(edid); return n; }
static int msm_hdmi_connector_get_modes(struct drm_connector *connector) { struct hdmi_connector *hdmi_connector = to_hdmi_connector(connector); struct hdmi *hdmi = hdmi_connector->hdmi; struct edid *edid; uint32_t hdmi_ctrl; int ret = 0; hdmi_ctrl = hdmi_read(hdmi, REG_HDMI_CTRL); hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl | HDMI_CTRL_ENABLE); edid = drm_get_edid(connector, hdmi->i2c); hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl); hdmi->hdmi_mode = drm_detect_hdmi_monitor(edid); drm_connector_update_edid_property(connector, edid); if (edid) { ret = drm_add_edid_modes(connector, edid); kfree(edid); } return ret; }
static int omap_connector_get_modes(struct drm_connector *connector) { struct omap_connector *omap_connector = to_omap_connector(connector); struct omap_dss_device *dssdev = omap_connector->dssdev; struct omap_dss_driver *dssdrv = dssdev->driver; struct drm_device *dev = connector->dev; int n = 0; DBG("%s", omap_connector->dssdev->name); /* if display exposes EDID, then we parse that in the normal way to * build table of supported modes.. otherwise (ie. fixed resolution * LCD panels) we just return a single mode corresponding to the * currently configured timings: */ if (dssdrv->read_edid) { void *edid = kzalloc(MAX_EDID, GFP_KERNEL); if ((dssdrv->read_edid(dssdev, edid, MAX_EDID) > 0) && drm_edid_is_valid(edid)) { drm_mode_connector_update_edid_property( connector, edid); n = drm_add_edid_modes(connector, edid); omap_connector->hdmi_mode = drm_detect_hdmi_monitor(edid); } else { drm_mode_connector_update_edid_property( connector, NULL); } kfree(edid); } else { struct drm_display_mode *mode = drm_mode_create(dev); struct videomode vm = {0}; dssdrv->get_timings(dssdev, &vm); drm_display_mode_from_videomode(&vm, mode); mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; drm_mode_set_name(mode); drm_mode_probed_add(connector, mode); n = 1; } return n; }
static void intel_hdmi_sink_detect(struct drm_connector *connector) { struct intel_output *intel_output = to_intel_output(connector); struct intel_hdmi_priv *hdmi_priv = intel_output->dev_priv; struct edid *edid = NULL; edid = drm_get_edid(&intel_output->base, &intel_output->ddc_bus->adapter); if (edid != NULL) { hdmi_priv->has_hdmi_sink = drm_detect_hdmi_monitor(edid); kfree(edid); intel_output->base.display_info.raw_edid = NULL; } }
static enum drm_connector_status intel_hdmi_detect(struct drm_connector *connector, bool force) { struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector); struct drm_i915_private *dev_priv = connector->dev->dev_private; struct edid *edid; enum drm_connector_status status = connector_status_disconnected; if (IS_G4X(connector->dev) && !g4x_hdmi_connected(intel_hdmi)) return status; #if 0 /* HOTPLUG Detect is not working in some of VLV A0 * boards. For those boards enable this WA */ if (IS_VALLEYVIEW(connector->dev)) return connector_status_connected; #endif intel_hdmi->has_hdmi_sink = false; intel_hdmi->has_audio = false; edid = drm_get_edid(connector, intel_gmbus_get_adapter(dev_priv, intel_hdmi->ddc_bus)); if (edid) { if (edid->input & DRM_EDID_INPUT_DIGITAL) { status = connector_status_connected; if (intel_hdmi->force_audio != HDMI_AUDIO_OFF_DVI) intel_hdmi->has_hdmi_sink = drm_detect_hdmi_monitor(edid); intel_hdmi->has_audio = drm_detect_monitor_audio(edid); } connector->display_info.raw_edid = NULL; kfree(edid); } if (status == connector_status_connected) { if (intel_hdmi->force_audio != HDMI_AUDIO_AUTO) intel_hdmi->has_audio = (intel_hdmi->force_audio == HDMI_AUDIO_ON); } return status; }
static enum drm_connector_status intel_hdmi_detect(struct drm_connector *connector, bool force) { struct drm_device *dev = connector->dev; struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector); struct intel_digital_port *intel_dig_port = hdmi_to_dig_port(intel_hdmi); struct intel_encoder *intel_encoder = &intel_dig_port->base; struct drm_i915_private *dev_priv = dev->dev_private; struct edid *edid; enum drm_connector_status status = connector_status_disconnected; DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", connector->base.id, drm_get_connector_name(connector)); intel_hdmi->has_hdmi_sink = false; intel_hdmi->has_audio = false; intel_hdmi->rgb_quant_range_selectable = false; edid = drm_get_edid(connector, intel_gmbus_get_adapter(dev_priv, intel_hdmi->ddc_bus)); if (edid) { if (edid->input & DRM_EDID_INPUT_DIGITAL) { status = connector_status_connected; if (intel_hdmi->force_audio != HDMI_AUDIO_OFF_DVI) intel_hdmi->has_hdmi_sink = drm_detect_hdmi_monitor(edid); intel_hdmi->has_audio = drm_detect_monitor_audio(edid); intel_hdmi->rgb_quant_range_selectable = drm_rgb_quant_range_selectable(edid); } kfree(edid); } if (status == connector_status_connected) { if (intel_hdmi->force_audio != HDMI_AUDIO_AUTO) intel_hdmi->has_audio = (intel_hdmi->force_audio == HDMI_AUDIO_ON); intel_encoder->type = INTEL_OUTPUT_HDMI; } return status; }
void nouveau_hdmi_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode) { struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); struct nouveau_connector *nv_connector; struct drm_device *dev = encoder->dev; u32 max_ac_packet, rekey; nv_connector = nouveau_encoder_connector_get(nv_encoder); if (!mode || !nv_connector || !nv_connector->edid || !drm_detect_hdmi_monitor(nv_connector->edid)) { nouveau_hdmi_disconnect(encoder); return; } nouveau_hdmi_video_infoframe(encoder, mode); nouveau_hdmi_audio_infoframe(encoder, mode); hdmi_mask(encoder, 0x0d0, 0x00070001, 0x00010001); /* SPARE, HW_CTS */ hdmi_mask(encoder, 0x068, 0x00010101, 0x00000000); /* ACR_CTRL, ?? */ hdmi_mask(encoder, 0x078, 0x80000000, 0x80000000); /* ACR_0441_ENABLE */ nv_mask(dev, 0x61733c, 0x00100000, 0x00100000); /* RESETF */ nv_mask(dev, 0x61733c, 0x10000000, 0x10000000); /* LOOKUP_EN */ nv_mask(dev, 0x61733c, 0x00100000, 0x00000000); /* !RESETF */ /* value matches nvidia binary driver, and tegra constant */ rekey = 56; max_ac_packet = mode->htotal - mode->hdisplay; max_ac_packet -= rekey; max_ac_packet -= 18; /* constant from tegra */ max_ac_packet /= 32; /* enable hdmi */ hdmi_mask(encoder, 0x0a4, 0x5f1f003f, 0x40000000 | /* enable */ 0x1f000000 | /* unknown */ max_ac_packet << 16 | rekey); nouveau_audio_mode_set(encoder, mode); }
static int sun4i_hdmi_get_modes(struct drm_connector *connector) { struct sun4i_hdmi *hdmi = drm_connector_to_sun4i_hdmi(connector); struct edid *edid; int ret; edid = drm_get_edid(connector, hdmi->i2c); if (!edid) return 0; hdmi->hdmi_monitor = drm_detect_hdmi_monitor(edid); DRM_DEBUG_DRIVER("Monitor is %s monitor\n", hdmi->hdmi_monitor ? "an HDMI" : "a DVI"); drm_mode_connector_update_edid_property(connector, edid); cec_s_phys_addr_from_edid(hdmi->cec_adap, edid); ret = drm_add_edid_modes(connector, edid); kfree(edid); return ret; }
static enum drm_connector_status intel_hdmi_detect(struct drm_connector *connector, bool force) { struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector); struct intel_digital_port *intel_dig_port = hdmi_to_dig_port(intel_hdmi); struct intel_encoder *intel_encoder = &intel_dig_port->base; struct drm_i915_private *dev_priv = connector->dev->dev_private; struct edid *edid; enum drm_connector_status status = connector_status_disconnected; if (IS_G4X(connector->dev) && !g4x_hdmi_connected(intel_hdmi)) return status; intel_hdmi->has_hdmi_sink = false; intel_hdmi->has_audio = false; edid = drm_get_edid(connector, intel_gmbus_get_adapter(dev_priv, intel_hdmi->ddc_bus)); if (edid) { if (edid->input & DRM_EDID_INPUT_DIGITAL) { status = connector_status_connected; if (intel_hdmi->force_audio != HDMI_AUDIO_OFF_DVI) intel_hdmi->has_hdmi_sink = drm_detect_hdmi_monitor(edid); intel_hdmi->has_audio = drm_detect_monitor_audio(edid); } free(edid, DRM_MEM_KMS); } if (status == connector_status_connected) { if (intel_hdmi->force_audio != HDMI_AUDIO_AUTO) intel_hdmi->has_audio = (intel_hdmi->force_audio == HDMI_AUDIO_ON); intel_encoder->type = INTEL_OUTPUT_HDMI; } return status; }
static enum drm_connector_status intel_hdmi_detect(struct drm_connector *connector) { struct intel_output *intel_output = to_intel_output(connector); struct intel_hdmi_priv *hdmi_priv = intel_output->dev_priv; struct edid *edid = NULL; enum drm_connector_status status = connector_status_disconnected; hdmi_priv->has_hdmi_sink = false; edid = drm_get_edid(&intel_output->base, intel_output->ddc_bus); if (edid) { if (edid->input & DRM_EDID_INPUT_DIGITAL) { status = connector_status_connected; hdmi_priv->has_hdmi_sink = drm_detect_hdmi_monitor(edid); } intel_output->base.display_info.raw_edid = NULL; kfree(edid); } return status; }
/* dm_helpers_parse_edid_caps * * Parse edid caps * * @edid: [in] pointer to edid * edid_caps: [in] pointer to edid caps * @return * void * */ enum dc_edid_status dm_helpers_parse_edid_caps( struct dc_context *ctx, const struct dc_edid *edid, struct dc_edid_caps *edid_caps) { struct edid *edid_buf = (struct edid *) edid->raw_edid; struct cea_sad *sads; int sad_count = -1; int sadb_count = -1; int i = 0; int j = 0; uint8_t *sadb = NULL; enum dc_edid_status result = EDID_OK; if (!edid_caps || !edid) return EDID_BAD_INPUT; if (!drm_edid_is_valid(edid_buf)) result = EDID_BAD_CHECKSUM; edid_caps->manufacturer_id = (uint16_t) edid_buf->mfg_id[0] | ((uint16_t) edid_buf->mfg_id[1])<<8; edid_caps->product_id = (uint16_t) edid_buf->prod_code[0] | ((uint16_t) edid_buf->prod_code[1])<<8; edid_caps->serial_number = edid_buf->serial; edid_caps->manufacture_week = edid_buf->mfg_week; edid_caps->manufacture_year = edid_buf->mfg_year; /* One of the four detailed_timings stores the monitor name. It's * stored in an array of length 13. */ for (i = 0; i < 4; i++) { if (edid_buf->detailed_timings[i].data.other_data.type == 0xfc) { while (j < 13 && edid_buf->detailed_timings[i].data.other_data.data.str.str[j]) { if (edid_buf->detailed_timings[i].data.other_data.data.str.str[j] == '\n') break; edid_caps->display_name[j] = edid_buf->detailed_timings[i].data.other_data.data.str.str[j]; j++; } } } edid_caps->edid_hdmi = drm_detect_hdmi_monitor( (struct edid *) edid->raw_edid); sad_count = drm_edid_to_sad((struct edid *) edid->raw_edid, &sads); if (sad_count <= 0) { DRM_INFO("SADs count is: %d, don't need to read it\n", sad_count); return result; } edid_caps->audio_mode_count = sad_count < DC_MAX_AUDIO_DESC_COUNT ? sad_count : DC_MAX_AUDIO_DESC_COUNT; for (i = 0; i < edid_caps->audio_mode_count; ++i) { struct cea_sad *sad = &sads[i]; edid_caps->audio_modes[i].format_code = sad->format; edid_caps->audio_modes[i].channel_count = sad->channels + 1; edid_caps->audio_modes[i].sample_rate = sad->freq; edid_caps->audio_modes[i].sample_size = sad->byte2; } sadb_count = drm_edid_to_speaker_allocation((struct edid *) edid->raw_edid, &sadb); if (sadb_count < 0) { DRM_ERROR("Couldn't read Speaker Allocation Data Block: %d\n", sadb_count); sadb_count = 0; } if (sadb_count) edid_caps->speaker_flags = sadb[0]; else edid_caps->speaker_flags = DEFAULT_SPEAKER_LOCATION; kfree(sads); kfree(sadb); return result; }
void nv50_head_flush_clr(struct nv50_head *head, struct nv50_head_atom *asyh, bool flush) { union nv50_head_atom_mask clr = { .mask = asyh->clr.mask & ~(flush ? 0 : asyh->set.mask), }; if (clr.olut) head->func->olut_clr(head); if (clr.core) head->func->core_clr(head); if (clr.curs) head->func->curs_clr(head); } void nv50_head_flush_set(struct nv50_head *head, struct nv50_head_atom *asyh) { if (asyh->set.view ) head->func->view (head, asyh); if (asyh->set.mode ) head->func->mode (head, asyh); if (asyh->set.core ) head->func->core_set(head, asyh); if (asyh->set.olut ) { asyh->olut.offset = nv50_lut_load(&head->olut, asyh->olut.buffer, asyh->state.gamma_lut, asyh->olut.load); head->func->olut_set(head, asyh); } if (asyh->set.curs ) head->func->curs_set(head, asyh); if (asyh->set.base ) head->func->base (head, asyh); if (asyh->set.ovly ) head->func->ovly (head, asyh); if (asyh->set.dither ) head->func->dither (head, asyh); if (asyh->set.procamp) head->func->procamp (head, asyh); if (asyh->set.or ) head->func->or (head, asyh); } static void nv50_head_atomic_check_procamp(struct nv50_head_atom *armh, struct nv50_head_atom *asyh, struct nouveau_conn_atom *asyc) { const int vib = asyc->procamp.color_vibrance - 100; const int hue = asyc->procamp.vibrant_hue - 90; const int adj = (vib > 0) ? 50 : 0; asyh->procamp.sat.cos = ((vib * 2047 + adj) / 100) & 0xfff; asyh->procamp.sat.sin = ((hue * 2047) / 100) & 0xfff; asyh->set.procamp = true; } static void nv50_head_atomic_check_dither(struct nv50_head_atom *armh, struct nv50_head_atom *asyh, struct nouveau_conn_atom *asyc) { struct drm_connector *connector = asyc->state.connector; u32 mode = 0x00; if (asyc->dither.mode == DITHERING_MODE_AUTO) { if (asyh->base.depth > connector->display_info.bpc * 3) mode = DITHERING_MODE_DYNAMIC2X2; } else { mode = asyc->dither.mode; } if (asyc->dither.depth == DITHERING_DEPTH_AUTO) { if (connector->display_info.bpc >= 8) mode |= DITHERING_DEPTH_8BPC; } else { mode |= asyc->dither.depth; } asyh->dither.enable = mode; asyh->dither.bits = mode >> 1; asyh->dither.mode = mode >> 3; asyh->set.dither = true; } static void nv50_head_atomic_check_view(struct nv50_head_atom *armh, struct nv50_head_atom *asyh, struct nouveau_conn_atom *asyc) { struct drm_connector *connector = asyc->state.connector; struct drm_display_mode *omode = &asyh->state.adjusted_mode; struct drm_display_mode *umode = &asyh->state.mode; int mode = asyc->scaler.mode; struct edid *edid; int umode_vdisplay, omode_hdisplay, omode_vdisplay; if (connector->edid_blob_ptr) edid = (struct edid *)connector->edid_blob_ptr->data; else edid = NULL; if (!asyc->scaler.full) { if (mode == DRM_MODE_SCALE_NONE) omode = umode; } else { /* Non-EDID LVDS/eDP mode. */ mode = DRM_MODE_SCALE_FULLSCREEN; } /* For the user-specified mode, we must ignore doublescan and * the like, but honor frame packing. */ umode_vdisplay = umode->vdisplay; if ((umode->flags & DRM_MODE_FLAG_3D_MASK) == DRM_MODE_FLAG_3D_FRAME_PACKING) umode_vdisplay += umode->vtotal; asyh->view.iW = umode->hdisplay; asyh->view.iH = umode_vdisplay; /* For the output mode, we can just use the stock helper. */ drm_mode_get_hv_timing(omode, &omode_hdisplay, &omode_vdisplay); asyh->view.oW = omode_hdisplay; asyh->view.oH = omode_vdisplay; /* Add overscan compensation if necessary, will keep the aspect * ratio the same as the backend mode unless overridden by the * user setting both hborder and vborder properties. */ if ((asyc->scaler.underscan.mode == UNDERSCAN_ON || (asyc->scaler.underscan.mode == UNDERSCAN_AUTO && drm_detect_hdmi_monitor(edid)))) { u32 bX = asyc->scaler.underscan.hborder; u32 bY = asyc->scaler.underscan.vborder; u32 r = (asyh->view.oH << 19) / asyh->view.oW; if (bX) { asyh->view.oW -= (bX * 2); if (bY) asyh->view.oH -= (bY * 2); else asyh->view.oH = ((asyh->view.oW * r) + (r / 2)) >> 19; } else { asyh->view.oW -= (asyh->view.oW >> 4) + 32; if (bY) asyh->view.oH -= (bY * 2); else asyh->view.oH = ((asyh->view.oW * r) + (r / 2)) >> 19; } }