static DFBResult drmkmsSetEncoderConfig( CoreScreen *screen, void *driver_data, void *screen_data, int encoder, const DFBScreenEncoderConfig *config ) { int ret = 0; DRMKMSData *drmkms = driver_data; DRMKMSDataShared *shared = drmkms->shared; DFBScreenEncoderFrequency dse_freq; DFBScreenOutputResolution dso_res; D_DEBUG_AT( DRMKMS_Screen, "%s()\n", __FUNCTION__ ); if (!(config->flags & (DSECONF_FREQUENCY | DSECONF_RESOLUTION))) return DFB_INVARG; drmkms_mode_to_dsor_dsef( &shared->mode[encoder], &dso_res, &dse_freq ); if (config->flags & DSECONF_FREQUENCY) { D_DEBUG_AT( DRMKMS_Screen, " -> requested frequency change \n" ); dse_freq = config->frequency; } if (config->flags & DSECONF_RESOLUTION) { D_DEBUG_AT( DRMKMS_Screen, " -> requested resolution change \n" ); dso_res = config->resolution; } drmModeModeInfo *videomode = drmkms_dsor_freq_to_mode( encoder, dso_res, dse_freq ); if (!videomode) return DFB_INVARG; if ((shared->primary_dimension[encoder].w && (shared->primary_dimension[encoder].w < videomode->hdisplay) ) || (shared->primary_dimension[encoder].h && (shared->primary_dimension[encoder].h < videomode->vdisplay ))) { D_DEBUG_AT( DRMKMS_Screen, " -> cannot switch to mode to something that is bigger than the current primary layer\n" ); return DFB_INVARG; } if (shared->primary_fb) ret = drmModeSetCrtc( drmkms->fd, drmkms->encoder[encoder]->crtc_id, shared->primary_fb, shared->primary_rect.x, shared->primary_rect.y, &drmkms->connector[encoder]->connector_id, 1, videomode ); if (ret) { D_DEBUG_AT( DRMKMS_Screen, " crtc_id: %d connector_id %d, mode %dx%d\n", drmkms->encoder[encoder]->crtc_id, drmkms->connector[encoder]->connector_id, shared->mode[encoder].hdisplay, shared->mode[encoder].vdisplay ); D_PERROR( "DirectFB/DRMKMS: drmModeSetCrtc() failed! (%d)\n", ret ); return DFB_FAILURE; } shared->mode[encoder] = *videomode; return DFB_OK; }
static DFBResult drmkmsInitOutput( CoreScreen *screen, void *driver_data, void *screen_data, int output, DFBScreenOutputDescription *description, DFBScreenOutputConfig *config ) { DRMKMSData *drmkms = driver_data; DRMKMSDataShared *shared = drmkms->shared; D_DEBUG_AT( DRMKMS_Screen, "%s()\n", __FUNCTION__ ); direct_snputs( description->name, "DRMKMS Output", DFB_SCREEN_OUTPUT_DESC_NAME_LENGTH ); description->caps = DSOCAPS_RESOLUTION; switch (drmkms->connector[output]->connector_type) { case DRM_MODE_CONNECTOR_VGA: description->all_connectors = DSOC_VGA; description->all_signals = DSOS_VGA; break; case DRM_MODE_CONNECTOR_SVIDEO: description->all_connectors = DSOC_YC; description->all_signals = DSOS_YC; break; case DRM_MODE_CONNECTOR_Composite: description->all_connectors = DSOC_CVBS; description->all_signals = DSOS_CVBS; break; case DRM_MODE_CONNECTOR_Component: description->all_connectors = DSOC_COMPONENT; description->all_signals = DSOS_YCBCR; break; case DRM_MODE_CONNECTOR_HDMIA: case DRM_MODE_CONNECTOR_HDMIB: description->all_connectors = DSOC_HDMI; description->all_signals = DSOS_HDMI; break; default: description->all_connectors = DSOC_UNKNOWN; description->all_signals = DSOC_UNKNOWN; } description->all_resolutions = drmkms_modes_to_dsor_bitmask( output ); config->flags = DSOCONF_RESOLUTION; drmkms_mode_to_dsor_dsef( &shared->mode[output], &config->resolution, NULL ); return DFB_OK; }
static DFBResult drmkmsInitEncoder( CoreScreen *screen, void *driver_data, void *screen_data, int encoder, DFBScreenEncoderDescription *description, DFBScreenEncoderConfig *config ) { DRMKMSData *drmkms = driver_data; DRMKMSDataShared *shared = drmkms->shared; D_DEBUG_AT( DRMKMS_Screen, "%s()\n", __FUNCTION__ ); direct_snputs( description->name, "DRMKMS Encoder", DFB_SCREEN_ENCODER_DESC_NAME_LENGTH ); description->caps = DSECAPS_RESOLUTION | DSECAPS_FREQUENCY; config->flags = DSECONF_RESOLUTION | DSECONF_FREQUENCY | DSECONF_MIXER; config->mixer = encoder; if (drmkms->encoder[encoder]) { switch (drmkms->encoder[encoder]->encoder_type) { case DRM_MODE_ENCODER_DAC: description->type = DSET_CRTC; break; case DRM_MODE_ENCODER_LVDS: case DRM_MODE_ENCODER_TMDS: description->type = DSET_DIGITAL; break; case DRM_MODE_ENCODER_TVDAC: description->type = DSET_TV; break; default: description->type = DSET_UNKNOWN; } drmkms_mode_to_dsor_dsef( &shared->mode[encoder], &config->resolution, &config->frequency ); description->all_resolutions = drmkms_modes_to_dsor_bitmask( encoder ); } else { description->type = DSET_DIGITAL; description->all_resolutions = DSOR_1280_720; config->resolution = DSOR_1280_720; config->frequency = DSEF_60HZ; } return DFB_OK; }
static DFBResult drmkmsTestEncoderConfig( CoreScreen *screen, void *driver_data, void *screen_data, int encoder, const DFBScreenEncoderConfig *config, DFBScreenEncoderConfigFlags *failed ) { DRMKMSData *drmkms = driver_data; DRMKMSDataShared *shared = drmkms->shared; DFBScreenEncoderFrequency dse_freq; DFBScreenOutputResolution dso_res; D_DEBUG_AT( DRMKMS_Screen, "%s()\n", __FUNCTION__ ); if (!(config->flags & (DSECONF_FREQUENCY | DSECONF_RESOLUTION))) return DFB_UNSUPPORTED; if (!drmkms->resources) return DFB_OK; drmkms_mode_to_dsor_dsef( &shared->mode[encoder], &dso_res, &dse_freq ); if (config->flags & DSECONF_FREQUENCY) dse_freq = config->frequency; if (config->flags & DSECONF_RESOLUTION) dso_res = config->resolution; drmModeModeInfo *videomode = drmkms_dsor_freq_to_mode( encoder, dso_res, dse_freq ); if (!videomode) { *failed = config->flags & (DSECONF_RESOLUTION | DSECONF_FREQUENCY); return DFB_UNSUPPORTED; } if ((shared->primary_dimension[encoder].w && (shared->primary_dimension[encoder].w < videomode->hdisplay) ) || (shared->primary_dimension[encoder].h && (shared->primary_dimension[encoder].h < videomode->vdisplay ))) { D_DEBUG_AT( DRMKMS_Screen, " -> cannot switch to mode to something that is bigger than the current primary layer\n" ); *failed = config->flags & (DSECONF_RESOLUTION | DSECONF_FREQUENCY); return DFB_UNSUPPORTED; } return DFB_OK; }