mirror of
https://gitlab.freedesktop.org/mesa/drm.git
synced 2026-01-01 07:10:15 +01:00
fb: make fb interface use user mode attach/detach for adding modes
This commit is contained in:
parent
362f428320
commit
f9ac54b031
3 changed files with 104 additions and 59 deletions
|
|
@ -1722,6 +1722,70 @@ int drm_mode_rmmode(struct drm_device *dev, struct drm_display_mode *mode)
|
|||
}
|
||||
EXPORT_SYMBOL(drm_mode_rmmode);
|
||||
|
||||
static int drm_mode_attachmode(struct drm_device *dev,
|
||||
struct drm_output *output,
|
||||
struct drm_display_mode *mode)
|
||||
{
|
||||
int ret = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < DRM_OUTPUT_MAX_UMODES; i++) {
|
||||
if (output->user_mode_ids[i] == 0) {
|
||||
output->user_mode_ids[i] = mode->mode_id;
|
||||
mode->output_count++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == DRM_OUTPUT_MAX_UMODES)
|
||||
ret = -ENOSPC;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int drm_mode_attachmode_crtc(struct drm_device *dev, struct drm_crtc *crtc,
|
||||
struct drm_display_mode *mode)
|
||||
{
|
||||
struct drm_output *output;
|
||||
|
||||
list_for_each_entry(output, &dev->mode_config.output_list, head) {
|
||||
if (output->crtc == crtc)
|
||||
drm_mode_attachmode(dev, output, mode);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(drm_mode_attachmode_crtc);
|
||||
|
||||
static int drm_mode_detachmode(struct drm_device *dev,
|
||||
struct drm_output *output,
|
||||
struct drm_display_mode *mode)
|
||||
{
|
||||
int found = 0;
|
||||
int ret = 0, i;
|
||||
|
||||
for (i = 0; i < DRM_OUTPUT_MAX_UMODES; i++) {
|
||||
if (output->user_mode_ids[i] == mode->mode_id) {
|
||||
output->user_mode_ids[i] = 0;
|
||||
mode->output_count--;
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
ret = -EINVAL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int drm_mode_detachmode_crtc(struct drm_device *dev, struct drm_display_mode *mode)
|
||||
{
|
||||
struct drm_output *output;
|
||||
|
||||
list_for_each_entry(output, &dev->mode_config.output_list, head) {
|
||||
drm_mode_detachmode(dev, output, mode);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(drm_mode_detachmode_crtc);
|
||||
|
||||
/**
|
||||
* drm_fb_addmode - adds a user defined mode
|
||||
* @inode: inode from the ioctl
|
||||
|
|
@ -1822,7 +1886,7 @@ int drm_mode_attachmode_ioctl(struct drm_device *dev,
|
|||
struct drm_mode_mode_cmd *mode_cmd = data;
|
||||
struct drm_output *output;
|
||||
struct drm_display_mode *mode;
|
||||
int i, ret = 0;
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&dev->mode_config.mutex);
|
||||
|
||||
|
|
@ -1838,17 +1902,7 @@ int drm_mode_attachmode_ioctl(struct drm_device *dev,
|
|||
goto out;
|
||||
}
|
||||
|
||||
for (i = 0; i < DRM_OUTPUT_MAX_UMODES; i++) {
|
||||
if (output->user_mode_ids[i] == 0) {
|
||||
output->user_mode_ids[i] = mode->mode_id;
|
||||
mode->output_count++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == DRM_OUTPUT_MAX_UMODES)
|
||||
ret = -ENOSPC;
|
||||
|
||||
ret = drm_mode_attachmode(dev, output, mode);
|
||||
out:
|
||||
mutex_unlock(&dev->mode_config.mutex);
|
||||
return ret;
|
||||
|
|
@ -1873,7 +1927,7 @@ int drm_mode_detachmode_ioctl(struct drm_device *dev,
|
|||
struct drm_mode_mode_cmd *mode_cmd = data;
|
||||
struct drm_output *output;
|
||||
struct drm_display_mode *mode;
|
||||
int i, found = 0, ret = 0;
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&dev->mode_config.mutex);
|
||||
|
||||
|
|
@ -1890,17 +1944,7 @@ int drm_mode_detachmode_ioctl(struct drm_device *dev,
|
|||
}
|
||||
|
||||
|
||||
for (i = 0; i < DRM_OUTPUT_MAX_UMODES; i++) {
|
||||
if (output->user_mode_ids[i] == mode->mode_id) {
|
||||
output->user_mode_ids[i] = 0;
|
||||
mode->output_count--;
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
ret = -EINVAL;
|
||||
|
||||
ret = drm_mode_detachmode(dev, output, mode);
|
||||
out:
|
||||
mutex_unlock(&dev->mode_config.mutex);
|
||||
return ret;
|
||||
|
|
|
|||
|
|
@ -497,6 +497,12 @@ extern void drm_disable_unused_functions(struct drm_device *dev);
|
|||
extern void drm_mode_addmode(struct drm_device *dev, struct drm_display_mode *user_mode);
|
||||
extern int drm_mode_rmmode(struct drm_device *dev, struct drm_display_mode *mode);
|
||||
|
||||
/* for us by fb module */
|
||||
extern int drm_mode_attachmode_crtc(struct drm_device *dev,
|
||||
struct drm_crtc *crtc,
|
||||
struct drm_display_mode *mode);
|
||||
extern int drm_mode_detachmode_crtc(struct drm_device *dev, struct drm_display_mode *mode);
|
||||
|
||||
extern struct drm_display_mode *drm_mode_create(struct drm_device *dev);
|
||||
extern void drm_mode_destroy(struct drm_device *dev, struct drm_display_mode *mode);
|
||||
extern void drm_mode_list_concat(struct list_head *head,
|
||||
|
|
|
|||
|
|
@ -223,7 +223,7 @@ static int intelfb_set_par(struct fb_info *info)
|
|||
struct intelfb_par *par = info->par;
|
||||
struct drm_framebuffer *fb = par->crtc->fb;
|
||||
struct drm_device *dev = par->dev;
|
||||
struct drm_display_mode *drm_mode;
|
||||
struct drm_display_mode *drm_mode, *search_mode;
|
||||
struct drm_output *output;
|
||||
struct fb_var_screeninfo *var = &info->var;
|
||||
int found = 0;
|
||||
|
|
@ -248,34 +248,7 @@ static int intelfb_set_par(struct fb_info *info)
|
|||
|
||||
info->screen_size = info->fix.smem_len; /* ??? */
|
||||
|
||||
/* Should we walk the output's modelist or just create our own ???
|
||||
* For now, we create and destroy a mode based on the incoming
|
||||
* parameters. But there's commented out code below which scans
|
||||
* the output list too.
|
||||
*/
|
||||
#if 0
|
||||
list_for_each_entry(output, &dev->mode_config.output_list, head) {
|
||||
if (output->crtc == par->crtc)
|
||||
break;
|
||||
}
|
||||
|
||||
list_for_each_entry(drm_mode, &output->modes, head) {
|
||||
if (drm_mode->hdisplay == var->xres &&
|
||||
drm_mode->vdisplay == var->yres &&
|
||||
(((PICOS2KHZ(var->pixclock))/1000) >= ((drm_mode->clock/1000)-1)) &&
|
||||
(((PICOS2KHZ(var->pixclock))/1000) <= ((drm_mode->clock/1000)+1))) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
DRM_ERROR("Couldn't find a mode for requested %dx%d-%d\n",
|
||||
var->xres,var->yres,var_to_refresh(var));
|
||||
return -EINVAL;
|
||||
}
|
||||
#else
|
||||
|
||||
/* create a drm mode */
|
||||
drm_mode = drm_mode_create(dev);
|
||||
drm_mode->hdisplay = var->xres;
|
||||
drm_mode->hsync_start = drm_mode->hdisplay + var->right_margin;
|
||||
|
|
@ -289,14 +262,36 @@ static int intelfb_set_par(struct fb_info *info)
|
|||
drm_mode->vrefresh = drm_mode_vrefresh(drm_mode);
|
||||
drm_mode_set_name(drm_mode);
|
||||
drm_mode_set_crtcinfo(drm_mode, CRTC_INTERLACE_HALVE_V);
|
||||
#endif
|
||||
|
||||
drm_mode_addmode(dev, drm_mode);
|
||||
if (par->fb_mode)
|
||||
drm_mode_rmmode(dev, par->fb_mode);
|
||||
list_for_each_entry(output, &dev->mode_config.output_list, head) {
|
||||
if (output->crtc == par->crtc)
|
||||
break;
|
||||
}
|
||||
|
||||
drm_mode_debug_printmodeline(dev, drm_mode);
|
||||
list_for_each_entry(search_mode, &output->modes, head) {
|
||||
DRM_ERROR("mode %s : %s\n", drm_mode->name, search_mode->name);
|
||||
drm_mode_debug_printmodeline(dev, search_mode);
|
||||
if (drm_mode_equal(drm_mode, search_mode)) {
|
||||
drm_mode_destroy(dev, drm_mode);
|
||||
drm_mode = search_mode;
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
par->fb_mode = drm_mode;
|
||||
drm_mode_debug_printmodeline(dev, drm_mode);
|
||||
if (!found) {
|
||||
drm_mode_addmode(dev, drm_mode);
|
||||
if (par->fb_mode) {
|
||||
drm_mode_detachmode_crtc(dev, par->fb_mode);
|
||||
drm_mode_rmmode(dev, par->fb_mode);
|
||||
}
|
||||
|
||||
par->fb_mode = drm_mode;
|
||||
drm_mode_debug_printmodeline(dev, drm_mode);
|
||||
/* attach mode */
|
||||
drm_mode_attachmode_crtc(dev, par->crtc, par->fb_mode);
|
||||
}
|
||||
|
||||
if (!drm_crtc_set_mode(par->crtc, drm_mode, 0, 0))
|
||||
return -EINVAL;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue