if (!ptr)
return;
- drmFree(ptr->modes);
drmFree(ptr);
}
res.crtc_id = drmMalloc(res.count_crtcs*sizeof(uint32_t));
if (res.count_outputs)
res.output_id = drmMalloc(res.count_outputs*sizeof(uint32_t));
- if (res.count_modes)
- res.modes = drmMalloc(res.count_modes*sizeof(*res.modes));
if (ioctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res)) {
r = NULL;
r->count_fbs = res.count_fbs;
r->count_crtcs = res.count_crtcs;
r->count_outputs = res.count_outputs;
- r->count_modes = res.count_modes;
/* TODO we realy should test if these allocs fails. */
r->fbs = drmAllocCpy(res.fb_id, res.count_fbs, sizeof(uint32_t));
r->crtcs = drmAllocCpy(res.crtc_id, res.count_crtcs, sizeof(uint32_t));
r->outputs = drmAllocCpy(res.output_id, res.count_outputs, sizeof(uint32_t));
- r->modes = drmAllocCpy(res.modes, res.count_modes, sizeof(struct drm_mode_modeinfo));
err_allocs:
drmFree(res.fb_id);
drmFree(res.crtc_id);
drmFree(res.output_id);
- drmFree(res.modes);
return r;
}
int drmModeSetCrtc(int fd, uint32_t crtcId, uint32_t bufferId,
- uint32_t x, uint32_t y, uint32_t modeId,
- uint32_t *outputs, int count)
+ uint32_t x, uint32_t y, uint32_t *outputs, int count,
+ struct drm_mode_modeinfo *mode)
{
struct drm_mode_crtc crtc;
crtc.fb_id = bufferId;
crtc.set_outputs = outputs;
crtc.count_outputs = count;
- crtc.mode = modeId;
+ if (mode) {
+ memcpy(&crtc.mode, mode, sizeof(struct drm_mode_modeinfo));
+ crtc.mode_valid = 1;
+ } else
+ crtc.mode_valid = 0;
return ioctl(fd, DRM_IOCTL_MODE_SETCRTC, &crtc);
}
}
if (out.count_modes)
- out.modes = drmMalloc(out.count_modes*sizeof(uint32_t));
+ out.modes = drmMalloc(out.count_modes*sizeof(struct drm_mode_modeinfo));
if (ioctl(fd, DRM_IOCTL_MODE_GETOUTPUT, &out))
goto err_allocs;
r->count_props = out.count_props;
r->props = drmAllocCpy(out.props, out.count_props, sizeof(uint32_t));
r->prop_values = drmAllocCpy(out.prop_values, out.count_props, sizeof(uint32_t));
- r->modes = drmAllocCpy(out.modes, out.count_modes, sizeof(uint32_t));
+ r->modes = drmAllocCpy(out.modes, out.count_modes, sizeof(struct drm_mode_modeinfo));
strncpy(r->name, out.name, DRM_OUTPUT_NAME_LEN);
r->name[DRM_OUTPUT_NAME_LEN-1] = 0;
return r;
}
+#if 0
uint32_t drmModeAddMode(int fd, struct drm_mode_modeinfo *mode_info)
{
if (ioctl(fd, DRM_IOCTL_MODE_ADDMODE, mode_info))
{
return ioctl(fd, DRM_IOCTL_MODE_RMMODE, &mode_id);
}
+#endif
int drmModeAttachMode(int fd, uint32_t output_id, uint32_t mode_id)
{
*
* FIXME: take into account monitor limits
*/
-void drm_crtc_probe_output_modes(struct drm_device *dev, int maxX, int maxY)
+void drm_crtc_probe_single_output_modes(struct drm_output *output, int maxX, int maxY)
{
- struct drm_output *output;
+ struct drm_device *dev = output->dev;
struct drm_display_mode *mode, *t;
int ret;
//if (maxX == 0 || maxY == 0)
// TODO
- list_for_each_entry(output, &dev->mode_config.output_list, head) {
-
- /* set all modes to the unverified state */
- list_for_each_entry_safe(mode, t, &output->modes, head)
- mode->status = MODE_UNVERIFIED;
+ /* set all modes to the unverified state */
+ list_for_each_entry_safe(mode, t, &output->modes, head)
+ mode->status = MODE_UNVERIFIED;
- output->status = (*output->funcs->detect)(output);
-
- if (output->status == output_status_disconnected) {
- DRM_DEBUG("%s is disconnected\n", output->name);
- /* TODO set EDID to NULL */
- continue;
- }
-
- ret = (*output->funcs->get_modes)(output);
-
- if (ret) {
- drm_mode_output_list_update(output);
- }
-
- if (maxX && maxY)
- drm_mode_validate_size(dev, &output->modes, maxX,
- maxY, 0);
- list_for_each_entry_safe(mode, t, &output->modes, head) {
- if (mode->status == MODE_OK)
- mode->status = (*output->funcs->mode_valid)(output,mode);
- }
+ output->status = (*output->funcs->detect)(output);
+
+ if (output->status == output_status_disconnected) {
+ DRM_DEBUG("%s is disconnected\n", output->name);
+ /* TODO set EDID to NULL */
+ return;
+ }
+
+ ret = (*output->funcs->get_modes)(output);
+
+ if (ret) {
+ drm_mode_output_list_update(output);
+ }
+
+ if (maxX && maxY)
+ drm_mode_validate_size(dev, &output->modes, maxX,
+ maxY, 0);
+ list_for_each_entry_safe(mode, t, &output->modes, head) {
+ if (mode->status == MODE_OK)
+ mode->status = (*output->funcs->mode_valid)(output,mode);
+ }
+
+
+ drm_mode_prune_invalid(dev, &output->modes, TRUE);
+
+ if (list_empty(&output->modes)) {
+ struct drm_display_mode *stdmode;
+ DRM_DEBUG("No valid modes on %s\n", output->name);
+
+ /* Should we do this here ???
+ * When no valid EDID modes are available we end up
+ * here and bailed in the past, now we add a standard
+ * 640x480@60Hz mode and carry on.
+ */
+ stdmode = drm_mode_duplicate(dev, &std_mode[0]);
+ drm_mode_probed_add(output, stdmode);
+ drm_mode_list_concat(&output->probed_modes,
+ &output->modes);
+
+ DRM_DEBUG("Adding standard 640x480 @ 60Hz to %s\n",
+ output->name);
+ }
+
+ drm_mode_sort(&output->modes);
+
+ DRM_DEBUG("Probed modes for %s\n", output->name);
+ list_for_each_entry_safe(mode, t, &output->modes, head) {
+ mode->vrefresh = drm_mode_vrefresh(mode);
+
+ drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
+ drm_mode_debug_printmodeline(dev, mode);
+ }
+}
- drm_mode_prune_invalid(dev, &output->modes, TRUE);
-
- if (list_empty(&output->modes)) {
- struct drm_display_mode *stdmode;
-
- DRM_DEBUG("No valid modes on %s\n", output->name);
-
- /* Should we do this here ???
- * When no valid EDID modes are available we end up
- * here and bailed in the past, now we add a standard
- * 640x480@60Hz mode and carry on.
- */
- stdmode = drm_mode_duplicate(dev, &std_mode[0]);
- drm_mode_probed_add(output, stdmode);
- drm_mode_list_concat(&output->probed_modes,
- &output->modes);
-
- DRM_DEBUG("Adding standard 640x480 @ 60Hz to %s\n",
- output->name);
- }
-
- drm_mode_sort(&output->modes);
-
- DRM_DEBUG("Probed modes for %s\n", output->name);
- list_for_each_entry_safe(mode, t, &output->modes, head) {
- mode->vrefresh = drm_mode_vrefresh(mode);
+void drm_crtc_probe_output_modes(struct drm_device *dev, int maxX, int maxY)
+{
+ struct drm_output *output;
- drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
- drm_mode_debug_printmodeline(dev, mode);
- }
+ list_for_each_entry(output, &dev->mode_config.output_list, head) {
+ drm_crtc_probe_single_output_modes(output, maxX, maxY);
}
}
*/
void drm_crtc_convert_to_umode(struct drm_mode_modeinfo *out, struct drm_display_mode *in)
{
-
- out->id = in->mode_id;
out->clock = in->clock;
out->hdisplay = in->hdisplay;
out->hsync_start = in->hsync_start;
struct drm_framebuffer *fb;
struct drm_output *output;
struct drm_crtc *crtc;
- struct drm_mode_modeinfo u_mode;
- struct drm_display_mode *mode;
int ret = 0;
- int mode_count= 0;
int output_count = 0;
int crtc_count = 0;
int fb_count = 0;
int copied = 0;
- memset(&u_mode, 0, sizeof(struct drm_mode_modeinfo));
-
mutex_lock(&dev->mode_config.mutex);
list_for_each(lh, &dev->mode_config.fb_list)
list_for_each(lh, &dev->mode_config.crtc_list)
crtc_count++;
- list_for_each_entry(output, &dev->mode_config.output_list,
- head) {
+ list_for_each(lh, &dev->mode_config.output_list)
output_count++;
- list_for_each(lh, &output->modes)
- mode_count++;
- }
- list_for_each(lh, &dev->mode_config.usermode_list)
- mode_count++;
-
- if (card_res->count_modes == 0) {
- DRM_DEBUG("probing modes %dx%d\n", dev->mode_config.max_width, dev->mode_config.max_height);
- drm_crtc_probe_output_modes(dev, dev->mode_config.max_width, dev->mode_config.max_height);
- mode_count = 0;
- list_for_each_entry(output, &dev->mode_config.output_list, head) {
- list_for_each(lh, &output->modes)
- mode_count++;
- }
- list_for_each(lh, &dev->mode_config.usermode_list)
- mode_count++;
- }
/* handle this in 4 parts */
/* FBs */
if (card_res->count_fbs >= fb_count) {
copied = 0;
list_for_each_entry(fb, &dev->mode_config.fb_list, head) {
- if (put_user(fb->id, card_res->fb_id + copied))
- return -EFAULT;
+ if (put_user(fb->id, card_res->fb_id + copied)) {
+ ret = -EFAULT;
+ goto out;
+ }
copied++;
}
}
copied = 0;
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head){
DRM_DEBUG("CRTC ID is %d\n", crtc->id);
- if (put_user(crtc->id, card_res->crtc_id + copied))
- return -EFAULT;
+ if (put_user(crtc->id, card_res->crtc_id + copied)) {
+ ret = -EFAULT;
+ goto out;
+ }
copied++;
}
}
list_for_each_entry(output, &dev->mode_config.output_list,
head) {
DRM_DEBUG("OUTPUT ID is %d\n", output->id);
- if (put_user(output->id, card_res->output_id + copied))
- return -EFAULT;
+ if (put_user(output->id, card_res->output_id + copied)) {
+ ret = -EFAULT;
+ goto out;
+ }
copied++;
}
}
card_res->count_outputs = output_count;
- /* Modes */
- if (card_res->count_modes >= mode_count) {
- copied = 0;
- list_for_each_entry(output, &dev->mode_config.output_list,
- head) {
- list_for_each_entry(mode, &output->modes, head) {
- drm_crtc_convert_to_umode(&u_mode, mode);
- if (copy_to_user(card_res->modes + copied,
- &u_mode, sizeof(u_mode)))
- return -EFAULT;
- copied++;
- }
- }
- /* add in user modes */
- list_for_each_entry(mode, &dev->mode_config.usermode_list, head) {
- drm_crtc_convert_to_umode(&u_mode, mode);
- if (copy_to_user(card_res->modes + copied, &u_mode,
- sizeof(u_mode)))
- return -EFAULT;
- copied++;
- }
- }
- card_res->count_modes = mode_count;
+ DRM_DEBUG("Counted %d %d\n", card_res->count_crtcs,
+ card_res->count_outputs);
- DRM_DEBUG("Counted %d %d %d\n", card_res->count_crtcs,
- card_res->count_outputs,
- card_res->count_modes);
-
+
+out:
mutex_unlock(&dev->mode_config.mutex);
return ret;
}
crtc_resp->outputs = 0;
if (crtc->enabled) {
- crtc_resp->mode = crtc->mode.mode_id;
+ drm_crtc_convert_to_umode(&crtc_resp->mode, &crtc->mode);
+ crtc_resp->mode_valid = 1;
ocount = 0;
list_for_each_entry(output, &dev->mode_config.output_list, head) {
if (output->crtc == crtc)
crtc_resp->outputs |= 1 << (ocount++);
}
+
} else {
- crtc_resp->mode = 0;
+ crtc_resp->mode_valid = 0;
}
out:
int ret = 0;
int copied = 0;
int i;
+ struct drm_mode_modeinfo u_mode;
+
+ memset(&u_mode, 0, sizeof(struct drm_mode_modeinfo));
DRM_DEBUG("output id %d:\n", out_resp->output);
}
}
+ if (out_resp->count_modes == 0) {
+ drm_crtc_probe_single_output_modes(output, dev->mode_config.max_width, dev->mode_config.max_height);
+ }
+
strncpy(out_resp->name, output->name, DRM_OUTPUT_NAME_LEN);
out_resp->name[DRM_OUTPUT_NAME_LEN-1] = 0;
if ((out_resp->count_modes >= mode_count) && mode_count) {
copied = 0;
list_for_each_entry(mode, &output->modes, head) {
- out_resp->modes[copied++] = mode->mode_id;
+ drm_crtc_convert_to_umode(&u_mode, mode);
+ if (copy_to_user(out_resp->modes + copied,
+ &u_mode, sizeof(u_mode))) {
+ ret = -EFAULT;
+ goto out;
+ }
+ copied++;
+
}
for (i = 0; i < DRM_OUTPUT_MAX_UMODES; i++) {
- if (output->user_mode_ids[i] != 0) {
- if (put_user(output->user_mode_ids[i], out_resp->modes + copied))
- return -EFAULT;
+ if (!output->user_mode_ids[i])
+ continue;
+ mode = idr_find(&dev->mode_config.crtc_idr, output->user_mode_ids[i]);
+ if (mode && (mode->mode_id == output->user_mode_ids[i])) {
+ drm_crtc_convert_to_umode(&u_mode, mode);
+ if (copy_to_user(out_resp->modes + copied,
+ &u_mode, sizeof(u_mode))) {
+ ret = -EFAULT;
+ goto out;
+ }
copied++;
}
}
struct drm_mode_crtc *crtc_req = data;
struct drm_crtc *crtc;
struct drm_output **output_set = NULL, *output;
- struct drm_display_mode *mode;
struct drm_framebuffer *fb = NULL;
+ struct drm_display_mode mode;
+ int mode_valid = 0;
int ret = 0;
int i;
goto out;
}
- if (crtc_req->mode) {
+ if (crtc_req->mode_valid) {
/* if we have a mode we need a framebuffer */
if (crtc_req->fb_id) {
fb = idr_find(&dev->mode_config.crtc_idr, crtc_req->fb_id);
goto out;
}
}
- mode = idr_find(&dev->mode_config.crtc_idr, crtc_req->mode);
- if (!mode || (mode->mode_id != crtc_req->mode)) {
- struct drm_output *output;
-
- list_for_each_entry(output,
- &dev->mode_config.output_list,
- head) {
- list_for_each_entry(mode, &output->modes,
- head) {
- drm_mode_debug_printmodeline(dev,
- mode);
- }
- }
- DRM_DEBUG("Unknown mode id %d, %p\n", crtc_req->mode, mode);
- ret = -EINVAL;
- goto out;
- }
+ mode_valid = 1;
+ drm_crtc_convert_umode(&mode, &crtc_req->mode);
} else
- mode = NULL;
+ mode_valid = 0;
- if (crtc_req->count_outputs == 0 && mode) {
+ if (crtc_req->count_outputs == 0 && mode_valid) {
DRM_DEBUG("Count outputs is 0 but mode set\n");
ret = -EINVAL;
goto out;
}
- if (crtc_req->count_outputs > 0 && !mode && !fb) {
+ if (crtc_req->count_outputs > 0 && !mode_valid && !fb) {
DRM_DEBUG("Count outputs is %d but no mode or fb set\n", crtc_req->count_outputs);
ret = -EINVAL;
goto out;
output_set[i] = output;
}
}
-
- ret = drm_crtc_set_config(crtc, crtc_req, mode, output_set, fb);
+
+ if (mode_valid) {
+ ret = drm_crtc_set_config(crtc, crtc_req, &mode, output_set, fb);
+ } else {
+ ret = drm_crtc_set_config(crtc, crtc_req, NULL, output_set, fb);
+ }
out:
mutex_unlock(&dev->mode_config.mutex);
drm_crtc_convert_umode(user_mode, new_mode);
drm_mode_addmode(dev, user_mode);
- new_mode->id = user_mode->mode_id;
out:
mutex_unlock(&dev->mode_config.mutex);