void evdi_painter_mode_changed_notify(struct evdi_device *evdi, struct drm_framebuffer *fb, struct drm_display_mode *new_mode) { struct evdi_painter *painter = evdi->painter; if (evdi_painter_replace_mode(painter, new_mode)) { EVDI_DEBUG( "(dev=%d) Notifying mode changed: %dx%d@%d; bpp %d; ", evdi->dev_index, new_mode->hdisplay, new_mode->vdisplay, drm_mode_vrefresh(new_mode), fb->bits_per_pixel); EVDI_DEBUG("pixel format %d\n", fb->pixel_format); evdi_painter_send_mode_changed(painter, fb->bits_per_pixel, fb->pixel_format); } else { EVDI_WARN("(dev=%d) Change mode duplicated - ignoring\n", evdi->dev_index); } }
void evdi_painter_crtc_state_notify(struct evdi_device *evdi, int state) { struct evdi_painter *painter = evdi->painter; if (painter) { EVDI_DEBUG("(dev=%d) Notifying crtc state: %d\n", evdi->dev_index, state); evdi_painter_send_crtc_state(painter, state); } else { EVDI_WARN("Painter does not exist!"); } }
void evdi_painter_dpms_notify(struct evdi_device *evdi, int mode) { struct evdi_painter *painter = evdi->painter; if (painter) { EVDI_DEBUG("(dev=%d) Notifying dpms mode: %d\n", evdi->dev_index, mode); evdi_painter_send_dpms(painter, mode); } else { EVDI_WARN("Painter does not exist!"); } }
struct drm_encoder *evdi_encoder_init(struct drm_device *dev) { struct drm_encoder *encoder; int status = 0; encoder = kzalloc(sizeof(struct drm_encoder), GFP_KERNEL); if (!encoder) { return NULL; } status = drm_encoder_init(dev, encoder, &evdi_enc_funcs, DRM_MODE_ENCODER_TMDS); EVDI_DEBUG("drm_encoder_init: %d\n", status); drm_encoder_helper_add(encoder, &evdi_helper_funcs); encoder->possible_crtcs = 1; return encoder; }
void evdi_painter_disconnect(struct evdi_device *evdi, struct drm_file *file) { struct evdi_painter *painter = evdi->painter; EVDI_CHECKPT(); painter_lock(painter); if (file != painter->drm_filp) { EVDI_WARN ("(dev=%d) An unknown connection to %p tries to close us", evdi->dev_index, file); EVDI_WARN(" - ignoring\n"); painter_unlock(painter); return; } if (painter->new_scanout_fb) { drm_framebuffer_unreference(&painter->new_scanout_fb->base); painter->new_scanout_fb = NULL; } if (painter->scanout_fb) { drm_framebuffer_unreference(&painter->scanout_fb->base); painter->scanout_fb = NULL; } painter->is_connected = false; EVDI_DEBUG("(dev=%d) Disconnected from %p\n", evdi->dev_index, painter->drm_filp); painter->drm_filp = NULL; evdi->dev_index = -1; memset(&painter->current_mode, '\0', sizeof(struct drm_display_mode)); painter->was_update_requested = false; painter_unlock(painter); drm_helper_hpd_irq_event(evdi->ddev); }
u8 *evdi_painter_get_edid_copy(struct evdi_device *evdi) { u8 *block = NULL; EVDI_CHECKPT(); painter_lock(evdi->painter); if (evdi_painter_is_connected(evdi) && evdi->painter->edid && evdi->painter->edid_length) { block = kmalloc(evdi->painter->edid_length, GFP_KERNEL); if (block) { memcpy(block, evdi->painter->edid, evdi->painter->edid_length); EVDI_DEBUG("(dev=%d) %02x %02x %02x\n", evdi->dev_index, block[0], block[1], block[2]); } } painter_unlock(evdi->painter); return block; }
int evdi_painter_connect(struct evdi_device *evdi, void const __user *edid_data, unsigned int edid_length, struct drm_file *file, int dev_index) { struct evdi_painter *painter = evdi->painter; struct edid *new_edid = NULL; int expected_edid_size = 0; EVDI_CHECKPT(); if (edid_length < sizeof(struct edid)) { EVDI_ERROR("Edid length too small\n"); return -EINVAL; } if (edid_length > MAX_EDID_SIZE) { EVDI_ERROR("Edid length too large\n"); return -EINVAL; } new_edid = kzalloc(edid_length, GFP_KERNEL); if (!new_edid) return -ENOMEM; if (copy_from_user(new_edid, edid_data, edid_length)) { EVDI_ERROR("(dev=%d) LSP Failed to read edid\n", dev_index); kfree(new_edid); return -EFAULT; } expected_edid_size = sizeof(struct edid) + new_edid->extensions * EDID_EXT_BLOCK_SIZE; if (expected_edid_size != edid_length) { EVDI_ERROR("Wrong edid size. Expected %d but is %d\n", expected_edid_size, edid_length); kfree(new_edid); return -EINVAL; } if (painter->drm_filp) EVDI_WARN("(dev=%d) Double connect - replacing %p with %p\n", dev_index, painter->drm_filp, file); EVDI_DEBUG("(dev=%d) Connected with %p\n", evdi->dev_index, painter->drm_filp); painter_lock(painter); evdi->dev_index = dev_index; painter->drm_filp = file; kfree(painter->edid); painter->edid_length = edid_length; painter->edid = new_edid; painter->is_connected = true; painter_unlock(painter); drm_helper_hpd_irq_event(evdi->ddev); drm_helper_resume_force_mode(evdi->ddev); return 0; }