forked from KolibriOS/kolibrios
i915-4.4 set active connector and mode from command line.
git-svn-id: svn://kolibrios.org@6088 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
parent
44e780f476
commit
3f61ba72bb
@ -1065,7 +1065,7 @@ int drm_atomic_helper_commit(struct drm_device *dev,
|
|||||||
|
|
||||||
drm_atomic_helper_commit_modeset_enables(dev, state);
|
drm_atomic_helper_commit_modeset_enables(dev, state);
|
||||||
|
|
||||||
// drm_atomic_helper_wait_for_vblanks(dev, state);
|
drm_atomic_helper_wait_for_vblanks(dev, state);
|
||||||
|
|
||||||
drm_atomic_helper_cleanup_planes(dev, state);
|
drm_atomic_helper_cleanup_planes(dev, state);
|
||||||
|
|
||||||
|
@ -818,8 +818,6 @@ static void drm_connector_get_cmdline_mode(struct drm_connector *connector)
|
|||||||
struct drm_cmdline_mode *mode = &connector->cmdline_mode;
|
struct drm_cmdline_mode *mode = &connector->cmdline_mode;
|
||||||
char *option = NULL;
|
char *option = NULL;
|
||||||
|
|
||||||
return;
|
|
||||||
#if 0
|
|
||||||
if (fb_get_options(connector->name, &option))
|
if (fb_get_options(connector->name, &option))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -855,7 +853,6 @@ static void drm_connector_get_cmdline_mode(struct drm_connector *connector)
|
|||||||
mode->rb ? " reduced blanking" : "",
|
mode->rb ? " reduced blanking" : "",
|
||||||
mode->margins ? " with margins" : "",
|
mode->margins ? " with margins" : "",
|
||||||
mode->interlace ? " interlaced" : "");
|
mode->interlace ? " interlaced" : "");
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
//#include <linux/delay.h>
|
//#include <linux/delay.h>
|
||||||
//#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
#include <linux/i2c.h>
|
#include <linux/i2c.h>
|
||||||
@ -215,7 +215,7 @@ static int drm_dp_dpcd_access(struct drm_dp_aux *aux, u8 request,
|
|||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
case DP_AUX_NATIVE_REPLY_DEFER:
|
case DP_AUX_NATIVE_REPLY_DEFER:
|
||||||
usleep(500);
|
usleep_range(AUX_RETRY_INTERVAL, AUX_RETRY_INTERVAL + 100);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -349,7 +349,7 @@ int drm_dp_link_power_up(struct drm_dp_aux *aux, struct drm_dp_link *link)
|
|||||||
* power saving state within 1 ms" (Section 2.5.3.1, Table 5-52, "Sink
|
* power saving state within 1 ms" (Section 2.5.3.1, Table 5-52, "Sink
|
||||||
* Control Field" (register 0x600).
|
* Control Field" (register 0x600).
|
||||||
*/
|
*/
|
||||||
usleep(2000);
|
usleep_range(1000, 2000);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -578,7 +578,7 @@ static int drm_dp_i2c_do_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
|
|||||||
* For now just defer for long enough to hopefully be
|
* For now just defer for long enough to hopefully be
|
||||||
* safe for all use-cases.
|
* safe for all use-cases.
|
||||||
*/
|
*/
|
||||||
usleep_range(500, 600);
|
usleep_range(AUX_RETRY_INTERVAL, AUX_RETRY_INTERVAL + 100);
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -610,7 +610,7 @@ static int drm_dp_i2c_do_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
|
|||||||
aux->i2c_defer_count++;
|
aux->i2c_defer_count++;
|
||||||
if (defer_i2c < 7)
|
if (defer_i2c < 7)
|
||||||
defer_i2c++;
|
defer_i2c++;
|
||||||
usleep_range(400, 500);
|
usleep_range(AUX_RETRY_INTERVAL, AUX_RETRY_INTERVAL + 100);
|
||||||
drm_dp_i2c_msg_write_status_update(msg);
|
drm_dp_i2c_msg_write_status_update(msg);
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include <linux/wait.h>
|
#include <linux/wait.h>
|
||||||
#include <linux/workqueue.h>
|
#include <linux/workqueue.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
|
#include <linux/init.h>
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
#include <linux/seq_file.h>
|
#include <linux/seq_file.h>
|
||||||
@ -2651,7 +2652,7 @@ int drm_dp_mst_topology_mgr_init(struct drm_dp_mst_topology_mgr *mgr,
|
|||||||
INIT_LIST_HEAD(&mgr->destroy_connector_list);
|
INIT_LIST_HEAD(&mgr->destroy_connector_list);
|
||||||
INIT_WORK(&mgr->work, drm_dp_mst_link_probe_work);
|
INIT_WORK(&mgr->work, drm_dp_mst_link_probe_work);
|
||||||
INIT_WORK(&mgr->tx_work, drm_dp_tx_work);
|
INIT_WORK(&mgr->tx_work, drm_dp_tx_work);
|
||||||
// init_waitqueue_head(&mgr->tx_waitq);
|
init_waitqueue_head(&mgr->tx_waitq);
|
||||||
mgr->dev = dev;
|
mgr->dev = dev;
|
||||||
mgr->aux = aux;
|
mgr->aux = aux;
|
||||||
mgr->max_dpcd_transaction_bytes = max_dpcd_transaction_bytes;
|
mgr->max_dpcd_transaction_bytes = max_dpcd_transaction_bytes;
|
||||||
|
@ -1324,8 +1324,6 @@ struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_connector *f
|
|||||||
struct drm_display_mode *mode;
|
struct drm_display_mode *mode;
|
||||||
bool prefer_non_interlace;
|
bool prefer_non_interlace;
|
||||||
|
|
||||||
return NULL;
|
|
||||||
#if 0
|
|
||||||
cmdline_mode = &fb_helper_conn->connector->cmdline_mode;
|
cmdline_mode = &fb_helper_conn->connector->cmdline_mode;
|
||||||
if (cmdline_mode->specified == false)
|
if (cmdline_mode->specified == false)
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -1369,7 +1367,6 @@ create_mode:
|
|||||||
cmdline_mode);
|
cmdline_mode);
|
||||||
list_add(&mode->head, &fb_helper_conn->connector->modes);
|
list_add(&mode->head, &fb_helper_conn->connector->modes);
|
||||||
return mode;
|
return mode;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(drm_pick_cmdline_mode);
|
EXPORT_SYMBOL(drm_pick_cmdline_mode);
|
||||||
|
|
||||||
|
@ -751,10 +751,6 @@ void drm_gem_vm_open(struct vm_area_struct *vma)
|
|||||||
struct drm_gem_object *obj = vma->vm_private_data;
|
struct drm_gem_object *obj = vma->vm_private_data;
|
||||||
|
|
||||||
drm_gem_object_reference(obj);
|
drm_gem_object_reference(obj);
|
||||||
|
|
||||||
mutex_lock(&obj->dev->struct_mutex);
|
|
||||||
drm_vm_open_locked(obj->dev, vma);
|
|
||||||
mutex_unlock(&obj->dev->struct_mutex);
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(drm_gem_vm_open);
|
EXPORT_SYMBOL(drm_gem_vm_open);
|
||||||
|
|
||||||
|
@ -370,8 +370,8 @@ int drm_vblank_init(struct drm_device *dev, unsigned int num_crtcs)
|
|||||||
vblank->dev = dev;
|
vblank->dev = dev;
|
||||||
vblank->pipe = i;
|
vblank->pipe = i;
|
||||||
init_waitqueue_head(&vblank->queue);
|
init_waitqueue_head(&vblank->queue);
|
||||||
// setup_timer(&vblank->disable_timer, vblank_disable_fn,
|
setup_timer(&vblank->disable_timer, vblank_disable_fn,
|
||||||
// (unsigned long)vblank);
|
(unsigned long)vblank);
|
||||||
}
|
}
|
||||||
|
|
||||||
DRM_INFO("Supports vblank timestamp caching Rev 2 (21.10.2013).\n");
|
DRM_INFO("Supports vblank timestamp caching Rev 2 (21.10.2013).\n");
|
||||||
@ -829,6 +829,140 @@ u32 drm_vblank_count_and_time(struct drm_device *dev, unsigned int pipe,
|
|||||||
return cur_vblank;
|
return cur_vblank;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(drm_vblank_count_and_time);
|
EXPORT_SYMBOL(drm_vblank_count_and_time);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* drm_crtc_vblank_count_and_time - retrieve "cooked" vblank counter value
|
||||||
|
* and the system timestamp corresponding to that vblank counter value
|
||||||
|
* @crtc: which counter to retrieve
|
||||||
|
* @vblanktime: Pointer to struct timeval to receive the vblank timestamp.
|
||||||
|
*
|
||||||
|
* Fetches the "cooked" vblank count value that represents the number of
|
||||||
|
* vblank events since the system was booted, including lost events due to
|
||||||
|
* modesetting activity. Returns corresponding system timestamp of the time
|
||||||
|
* of the vblank interval that corresponds to the current vblank counter value.
|
||||||
|
*
|
||||||
|
* This is the native KMS version of drm_vblank_count_and_time().
|
||||||
|
*/
|
||||||
|
u32 drm_crtc_vblank_count_and_time(struct drm_crtc *crtc,
|
||||||
|
struct timeval *vblanktime)
|
||||||
|
{
|
||||||
|
return drm_vblank_count_and_time(crtc->dev, drm_crtc_index(crtc),
|
||||||
|
vblanktime);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(drm_crtc_vblank_count_and_time);
|
||||||
|
|
||||||
|
static void send_vblank_event(struct drm_device *dev,
|
||||||
|
struct drm_pending_vblank_event *e,
|
||||||
|
unsigned long seq, struct timeval *now)
|
||||||
|
{
|
||||||
|
assert_spin_locked(&dev->event_lock);
|
||||||
|
|
||||||
|
e->event.sequence = seq;
|
||||||
|
e->event.tv_sec = now->tv_sec;
|
||||||
|
e->event.tv_usec = now->tv_usec;
|
||||||
|
|
||||||
|
list_add_tail(&e->base.link,
|
||||||
|
&e->base.file_priv->event_list);
|
||||||
|
wake_up_interruptible(&e->base.file_priv->event_wait);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* drm_arm_vblank_event - arm vblank event after pageflip
|
||||||
|
* @dev: DRM device
|
||||||
|
* @pipe: CRTC index
|
||||||
|
* @e: the event to prepare to send
|
||||||
|
*
|
||||||
|
* A lot of drivers need to generate vblank events for the very next vblank
|
||||||
|
* interrupt. For example when the page flip interrupt happens when the page
|
||||||
|
* flip gets armed, but not when it actually executes within the next vblank
|
||||||
|
* period. This helper function implements exactly the required vblank arming
|
||||||
|
* behaviour.
|
||||||
|
*
|
||||||
|
* Caller must hold event lock. Caller must also hold a vblank reference for
|
||||||
|
* the event @e, which will be dropped when the next vblank arrives.
|
||||||
|
*
|
||||||
|
* This is the legacy version of drm_crtc_arm_vblank_event().
|
||||||
|
*/
|
||||||
|
void drm_arm_vblank_event(struct drm_device *dev, unsigned int pipe,
|
||||||
|
struct drm_pending_vblank_event *e)
|
||||||
|
{
|
||||||
|
assert_spin_locked(&dev->event_lock);
|
||||||
|
|
||||||
|
e->pipe = pipe;
|
||||||
|
e->event.sequence = drm_vblank_count(dev, pipe);
|
||||||
|
list_add_tail(&e->base.link, &dev->vblank_event_list);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(drm_arm_vblank_event);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* drm_crtc_arm_vblank_event - arm vblank event after pageflip
|
||||||
|
* @crtc: the source CRTC of the vblank event
|
||||||
|
* @e: the event to send
|
||||||
|
*
|
||||||
|
* A lot of drivers need to generate vblank events for the very next vblank
|
||||||
|
* interrupt. For example when the page flip interrupt happens when the page
|
||||||
|
* flip gets armed, but not when it actually executes within the next vblank
|
||||||
|
* period. This helper function implements exactly the required vblank arming
|
||||||
|
* behaviour.
|
||||||
|
*
|
||||||
|
* Caller must hold event lock. Caller must also hold a vblank reference for
|
||||||
|
* the event @e, which will be dropped when the next vblank arrives.
|
||||||
|
*
|
||||||
|
* This is the native KMS version of drm_arm_vblank_event().
|
||||||
|
*/
|
||||||
|
void drm_crtc_arm_vblank_event(struct drm_crtc *crtc,
|
||||||
|
struct drm_pending_vblank_event *e)
|
||||||
|
{
|
||||||
|
drm_arm_vblank_event(crtc->dev, drm_crtc_index(crtc), e);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(drm_crtc_arm_vblank_event);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* drm_send_vblank_event - helper to send vblank event after pageflip
|
||||||
|
* @dev: DRM device
|
||||||
|
* @pipe: CRTC index
|
||||||
|
* @e: the event to send
|
||||||
|
*
|
||||||
|
* Updates sequence # and timestamp on event, and sends it to userspace.
|
||||||
|
* Caller must hold event lock.
|
||||||
|
*
|
||||||
|
* This is the legacy version of drm_crtc_send_vblank_event().
|
||||||
|
*/
|
||||||
|
void drm_send_vblank_event(struct drm_device *dev, unsigned int pipe,
|
||||||
|
struct drm_pending_vblank_event *e)
|
||||||
|
{
|
||||||
|
struct timeval now;
|
||||||
|
unsigned int seq;
|
||||||
|
|
||||||
|
if (dev->num_crtcs > 0) {
|
||||||
|
seq = drm_vblank_count_and_time(dev, pipe, &now);
|
||||||
|
} else {
|
||||||
|
seq = 0;
|
||||||
|
|
||||||
|
now = get_drm_timestamp();
|
||||||
|
}
|
||||||
|
e->pipe = pipe;
|
||||||
|
send_vblank_event(dev, e, seq, &now);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(drm_send_vblank_event);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* drm_crtc_send_vblank_event - helper to send vblank event after pageflip
|
||||||
|
* @crtc: the source CRTC of the vblank event
|
||||||
|
* @e: the event to send
|
||||||
|
*
|
||||||
|
* Updates sequence # and timestamp on event, and sends it to userspace.
|
||||||
|
* Caller must hold event lock.
|
||||||
|
*
|
||||||
|
* This is the native KMS version of drm_send_vblank_event().
|
||||||
|
*/
|
||||||
|
void drm_crtc_send_vblank_event(struct drm_crtc *crtc,
|
||||||
|
struct drm_pending_vblank_event *e)
|
||||||
|
{
|
||||||
|
drm_send_vblank_event(crtc->dev, drm_crtc_index(crtc), e);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(drm_crtc_send_vblank_event);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* drm_vblank_enable - enable the vblank interrupt on a CRTC
|
* drm_vblank_enable - enable the vblank interrupt on a CRTC
|
||||||
* @dev: DRM device
|
* @dev: DRM device
|
||||||
@ -952,11 +1086,8 @@ void drm_vblank_put(struct drm_device *dev, unsigned int pipe)
|
|||||||
if (atomic_dec_and_test(&vblank->refcount)) {
|
if (atomic_dec_and_test(&vblank->refcount)) {
|
||||||
if (drm_vblank_offdelay == 0)
|
if (drm_vblank_offdelay == 0)
|
||||||
return;
|
return;
|
||||||
else if (dev->vblank_disable_immediate || drm_vblank_offdelay < 0)
|
|
||||||
vblank_disable_fn((unsigned long)vblank);
|
|
||||||
else
|
else
|
||||||
mod_timer(&vblank->disable_timer,
|
vblank_disable_fn((unsigned long)vblank);
|
||||||
jiffies + ((drm_vblank_offdelay * HZ)/1000));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(drm_vblank_put);
|
EXPORT_SYMBOL(drm_vblank_put);
|
||||||
@ -987,24 +1118,26 @@ EXPORT_SYMBOL(drm_crtc_vblank_put);
|
|||||||
*/
|
*/
|
||||||
void drm_wait_one_vblank(struct drm_device *dev, unsigned int pipe)
|
void drm_wait_one_vblank(struct drm_device *dev, unsigned int pipe)
|
||||||
{
|
{
|
||||||
#if 0
|
struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
|
||||||
int ret;
|
int ret;
|
||||||
u32 last;
|
u32 last;
|
||||||
|
|
||||||
ret = drm_vblank_get(dev, crtc);
|
if (WARN_ON(pipe >= dev->num_crtcs))
|
||||||
if (WARN(ret, "vblank not available on crtc %i, ret=%i\n", crtc, ret))
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
last = drm_vblank_count(dev, crtc);
|
ret = drm_vblank_get(dev, pipe);
|
||||||
|
if (WARN(ret, "vblank not available on crtc %i, ret=%i\n", pipe, ret))
|
||||||
|
return;
|
||||||
|
|
||||||
ret = wait_event_timeout(dev->vblank[crtc].queue,
|
last = drm_vblank_count(dev, pipe);
|
||||||
last != drm_vblank_count(dev, crtc),
|
|
||||||
|
ret = wait_event_timeout(vblank->queue,
|
||||||
|
last != drm_vblank_count(dev, pipe),
|
||||||
msecs_to_jiffies(100));
|
msecs_to_jiffies(100));
|
||||||
|
|
||||||
WARN(ret == 0, "vblank wait timed out on crtc %i\n", crtc);
|
WARN(ret == 0, "vblank wait timed out on crtc %i\n", pipe);
|
||||||
|
|
||||||
drm_vblank_put(dev, crtc);
|
drm_vblank_put(dev, pipe);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(drm_wait_one_vblank);
|
EXPORT_SYMBOL(drm_wait_one_vblank);
|
||||||
|
|
||||||
@ -1044,7 +1177,39 @@ void drm_vblank_off(struct drm_device *dev, unsigned int pipe)
|
|||||||
unsigned long irqflags;
|
unsigned long irqflags;
|
||||||
unsigned int seq;
|
unsigned int seq;
|
||||||
|
|
||||||
|
if (WARN_ON(pipe >= dev->num_crtcs))
|
||||||
|
return;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&dev->event_lock, irqflags);
|
||||||
|
|
||||||
|
spin_lock(&dev->vbl_lock);
|
||||||
|
vblank_disable_and_save(dev, pipe);
|
||||||
|
wake_up(&vblank->queue);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Prevent subsequent drm_vblank_get() from re-enabling
|
||||||
|
* the vblank interrupt by bumping the refcount.
|
||||||
|
*/
|
||||||
|
if (!vblank->inmodeset) {
|
||||||
|
atomic_inc(&vblank->refcount);
|
||||||
|
vblank->inmodeset = 1;
|
||||||
|
}
|
||||||
|
spin_unlock(&dev->vbl_lock);
|
||||||
|
|
||||||
|
/* Send any queued vblank events, lest the natives grow disquiet */
|
||||||
|
seq = drm_vblank_count_and_time(dev, pipe, &now);
|
||||||
|
|
||||||
|
list_for_each_entry_safe(e, t, &dev->vblank_event_list, base.link) {
|
||||||
|
if (e->pipe != pipe)
|
||||||
|
continue;
|
||||||
|
DRM_DEBUG("Sending premature vblank event on disable: "
|
||||||
|
"wanted %d, current %d\n",
|
||||||
|
e->event.sequence, seq);
|
||||||
|
list_del(&e->base.link);
|
||||||
|
drm_vblank_put(dev, pipe);
|
||||||
|
send_vblank_event(dev, e, seq, &now);
|
||||||
|
}
|
||||||
|
spin_unlock_irqrestore(&dev->event_lock, irqflags);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(drm_vblank_off);
|
EXPORT_SYMBOL(drm_vblank_off);
|
||||||
|
|
||||||
@ -1116,8 +1281,6 @@ void drm_vblank_on(struct drm_device *dev, unsigned int pipe)
|
|||||||
struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
|
struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
|
||||||
unsigned long irqflags;
|
unsigned long irqflags;
|
||||||
|
|
||||||
dbgprintf("%s pipe %d dev->num_crtcs %d\n", pipe,dev->num_crtcs);\
|
|
||||||
|
|
||||||
if (WARN_ON(pipe >= dev->num_crtcs))
|
if (WARN_ON(pipe >= dev->num_crtcs))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -1240,6 +1403,115 @@ void drm_vblank_post_modeset(struct drm_device *dev, unsigned int pipe)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(drm_vblank_post_modeset);
|
EXPORT_SYMBOL(drm_vblank_post_modeset);
|
||||||
|
|
||||||
|
static void drm_handle_vblank_events(struct drm_device *dev, unsigned int pipe)
|
||||||
|
{
|
||||||
|
struct drm_pending_vblank_event *e, *t;
|
||||||
|
struct timeval now;
|
||||||
|
unsigned int seq;
|
||||||
|
|
||||||
|
assert_spin_locked(&dev->event_lock);
|
||||||
|
|
||||||
|
seq = drm_vblank_count_and_time(dev, pipe, &now);
|
||||||
|
|
||||||
|
list_for_each_entry_safe(e, t, &dev->vblank_event_list, base.link) {
|
||||||
|
if (e->pipe != pipe)
|
||||||
|
continue;
|
||||||
|
if ((seq - e->event.sequence) > (1<<23))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
DRM_DEBUG("vblank event on %d, current %d\n",
|
||||||
|
e->event.sequence, seq);
|
||||||
|
|
||||||
|
list_del(&e->base.link);
|
||||||
|
drm_vblank_put(dev, pipe);
|
||||||
|
send_vblank_event(dev, e, seq, &now);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* drm_handle_vblank - handle a vblank event
|
||||||
|
* @dev: DRM device
|
||||||
|
* @pipe: index of CRTC where this event occurred
|
||||||
|
*
|
||||||
|
* Drivers should call this routine in their vblank interrupt handlers to
|
||||||
|
* update the vblank counter and send any signals that may be pending.
|
||||||
|
*
|
||||||
|
* This is the legacy version of drm_crtc_handle_vblank().
|
||||||
|
*/
|
||||||
|
bool drm_handle_vblank(struct drm_device *dev, unsigned int pipe)
|
||||||
|
{
|
||||||
|
struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
|
||||||
|
unsigned long irqflags;
|
||||||
|
|
||||||
|
if (WARN_ON_ONCE(!dev->num_crtcs))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (WARN_ON(pipe >= dev->num_crtcs))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&dev->event_lock, irqflags);
|
||||||
|
|
||||||
|
/* Need timestamp lock to prevent concurrent execution with
|
||||||
|
* vblank enable/disable, as this would cause inconsistent
|
||||||
|
* or corrupted timestamps and vblank counts.
|
||||||
|
*/
|
||||||
|
spin_lock(&dev->vblank_time_lock);
|
||||||
|
|
||||||
|
/* Vblank irq handling disabled. Nothing to do. */
|
||||||
|
if (!vblank->enabled) {
|
||||||
|
spin_unlock(&dev->vblank_time_lock);
|
||||||
|
spin_unlock_irqrestore(&dev->event_lock, irqflags);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
drm_update_vblank_count(dev, pipe, DRM_CALLED_FROM_VBLIRQ);
|
||||||
|
|
||||||
|
spin_unlock(&dev->vblank_time_lock);
|
||||||
|
|
||||||
|
wake_up(&vblank->queue);
|
||||||
|
drm_handle_vblank_events(dev, pipe);
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&dev->event_lock, irqflags);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(drm_handle_vblank);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* drm_crtc_handle_vblank - handle a vblank event
|
||||||
|
* @crtc: where this event occurred
|
||||||
|
*
|
||||||
|
* Drivers should call this routine in their vblank interrupt handlers to
|
||||||
|
* update the vblank counter and send any signals that may be pending.
|
||||||
|
*
|
||||||
|
* This is the native KMS version of drm_handle_vblank().
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* True if the event was successfully handled, false on failure.
|
||||||
|
*/
|
||||||
|
bool drm_crtc_handle_vblank(struct drm_crtc *crtc)
|
||||||
|
{
|
||||||
|
return drm_handle_vblank(crtc->dev, drm_crtc_index(crtc));
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(drm_crtc_handle_vblank);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* drm_vblank_no_hw_counter - "No hw counter" implementation of .get_vblank_counter()
|
||||||
|
* @dev: DRM device
|
||||||
|
* @pipe: CRTC for which to read the counter
|
||||||
|
*
|
||||||
|
* Drivers can plug this into the .get_vblank_counter() function if
|
||||||
|
* there is no useable hardware frame counter available.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* 0
|
||||||
|
*/
|
||||||
|
u32 drm_vblank_no_hw_counter(struct drm_device *dev, unsigned int pipe)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(drm_vblank_no_hw_counter);
|
||||||
|
|
||||||
u64 div64_u64(u64 dividend, u64 divisor)
|
u64 div64_u64(u64 dividend, u64 divisor)
|
||||||
{
|
{
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
//#include <linux/of_device.h>
|
//#include <linux/of_device.h>
|
||||||
#include <linux/pm_runtime.h>
|
#include <linux/pm_runtime.h>
|
||||||
//#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
|
|
||||||
#include <video/mipi_display.h>
|
#include <video/mipi_display.h>
|
||||||
|
|
||||||
|
@ -1198,6 +1198,214 @@ void drm_mode_connector_list_update(struct drm_connector *connector,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(drm_mode_connector_list_update);
|
EXPORT_SYMBOL(drm_mode_connector_list_update);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* drm_mode_parse_command_line_for_connector - parse command line modeline for connector
|
||||||
|
* @mode_option: optional per connector mode option
|
||||||
|
* @connector: connector to parse modeline for
|
||||||
|
* @mode: preallocated drm_cmdline_mode structure to fill out
|
||||||
|
*
|
||||||
|
* This parses @mode_option command line modeline for modes and options to
|
||||||
|
* configure the connector. If @mode_option is NULL the default command line
|
||||||
|
* modeline in fb_mode_option will be parsed instead.
|
||||||
|
*
|
||||||
|
* This uses the same parameters as the fb modedb.c, except for an extra
|
||||||
|
* force-enable, force-enable-digital and force-disable bit at the end:
|
||||||
|
*
|
||||||
|
* <xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m][eDd]
|
||||||
|
*
|
||||||
|
* The intermediate drm_cmdline_mode structure is required to store additional
|
||||||
|
* options from the command line modline like the force-enable/disable flag.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* True if a valid modeline has been parsed, false otherwise.
|
||||||
|
*/
|
||||||
|
bool drm_mode_parse_command_line_for_connector(const char *mode_option,
|
||||||
|
struct drm_connector *connector,
|
||||||
|
struct drm_cmdline_mode *mode)
|
||||||
|
{
|
||||||
|
const char *name;
|
||||||
|
unsigned int namelen;
|
||||||
|
bool res_specified = false, bpp_specified = false, refresh_specified = false;
|
||||||
|
unsigned int xres = 0, yres = 0, bpp = 32, refresh = 0;
|
||||||
|
bool yres_specified = false, cvt = false, rb = false;
|
||||||
|
bool interlace = false, margins = false, was_digit = false;
|
||||||
|
int i;
|
||||||
|
enum drm_connector_force force = DRM_FORCE_UNSPECIFIED;
|
||||||
|
|
||||||
|
#ifdef CONFIG_FB
|
||||||
|
if (!mode_option)
|
||||||
|
mode_option = fb_mode_option;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!mode_option) {
|
||||||
|
mode->specified = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
name = mode_option;
|
||||||
|
namelen = strlen(name);
|
||||||
|
for (i = namelen-1; i >= 0; i--) {
|
||||||
|
switch (name[i]) {
|
||||||
|
case '@':
|
||||||
|
if (!refresh_specified && !bpp_specified &&
|
||||||
|
!yres_specified && !cvt && !rb && was_digit) {
|
||||||
|
refresh = simple_strtol(&name[i+1], NULL, 10);
|
||||||
|
refresh_specified = true;
|
||||||
|
was_digit = false;
|
||||||
|
} else
|
||||||
|
goto done;
|
||||||
|
break;
|
||||||
|
case '-':
|
||||||
|
if (!bpp_specified && !yres_specified && !cvt &&
|
||||||
|
!rb && was_digit) {
|
||||||
|
bpp = simple_strtol(&name[i+1], NULL, 10);
|
||||||
|
bpp_specified = true;
|
||||||
|
was_digit = false;
|
||||||
|
} else
|
||||||
|
goto done;
|
||||||
|
break;
|
||||||
|
case 'x':
|
||||||
|
if (!yres_specified && was_digit) {
|
||||||
|
yres = simple_strtol(&name[i+1], NULL, 10);
|
||||||
|
yres_specified = true;
|
||||||
|
was_digit = false;
|
||||||
|
} else
|
||||||
|
goto done;
|
||||||
|
break;
|
||||||
|
case '0' ... '9':
|
||||||
|
was_digit = true;
|
||||||
|
break;
|
||||||
|
case 'M':
|
||||||
|
if (yres_specified || cvt || was_digit)
|
||||||
|
goto done;
|
||||||
|
cvt = true;
|
||||||
|
break;
|
||||||
|
case 'R':
|
||||||
|
if (yres_specified || cvt || rb || was_digit)
|
||||||
|
goto done;
|
||||||
|
rb = true;
|
||||||
|
break;
|
||||||
|
case 'm':
|
||||||
|
if (cvt || yres_specified || was_digit)
|
||||||
|
goto done;
|
||||||
|
margins = true;
|
||||||
|
break;
|
||||||
|
case 'i':
|
||||||
|
if (cvt || yres_specified || was_digit)
|
||||||
|
goto done;
|
||||||
|
interlace = true;
|
||||||
|
break;
|
||||||
|
case 'e':
|
||||||
|
if (yres_specified || bpp_specified || refresh_specified ||
|
||||||
|
was_digit || (force != DRM_FORCE_UNSPECIFIED))
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
force = DRM_FORCE_ON;
|
||||||
|
break;
|
||||||
|
case 'D':
|
||||||
|
if (yres_specified || bpp_specified || refresh_specified ||
|
||||||
|
was_digit || (force != DRM_FORCE_UNSPECIFIED))
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
if ((connector->connector_type != DRM_MODE_CONNECTOR_DVII) &&
|
||||||
|
(connector->connector_type != DRM_MODE_CONNECTOR_HDMIB))
|
||||||
|
force = DRM_FORCE_ON;
|
||||||
|
else
|
||||||
|
force = DRM_FORCE_ON_DIGITAL;
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
if (yres_specified || bpp_specified || refresh_specified ||
|
||||||
|
was_digit || (force != DRM_FORCE_UNSPECIFIED))
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
force = DRM_FORCE_OFF;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i < 0 && yres_specified) {
|
||||||
|
char *ch;
|
||||||
|
xres = simple_strtol(name, &ch, 10);
|
||||||
|
if ((ch != NULL) && (*ch == 'x'))
|
||||||
|
res_specified = true;
|
||||||
|
else
|
||||||
|
i = ch - name;
|
||||||
|
} else if (!yres_specified && was_digit) {
|
||||||
|
/* catch mode that begins with digits but has no 'x' */
|
||||||
|
i = 0;
|
||||||
|
}
|
||||||
|
done:
|
||||||
|
if (i >= 0) {
|
||||||
|
printk(KERN_WARNING
|
||||||
|
"parse error at position %i in video mode '%s'\n",
|
||||||
|
i, name);
|
||||||
|
mode->specified = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res_specified) {
|
||||||
|
mode->specified = true;
|
||||||
|
mode->xres = xres;
|
||||||
|
mode->yres = yres;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (refresh_specified) {
|
||||||
|
mode->refresh_specified = true;
|
||||||
|
mode->refresh = refresh;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bpp_specified) {
|
||||||
|
mode->bpp_specified = true;
|
||||||
|
mode->bpp = bpp;
|
||||||
|
}
|
||||||
|
mode->rb = rb;
|
||||||
|
mode->cvt = cvt;
|
||||||
|
mode->interlace = interlace;
|
||||||
|
mode->margins = margins;
|
||||||
|
mode->force = force;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(drm_mode_parse_command_line_for_connector);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* drm_mode_create_from_cmdline_mode - convert a command line modeline into a DRM display mode
|
||||||
|
* @dev: DRM device to create the new mode for
|
||||||
|
* @cmd: input command line modeline
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* Pointer to converted mode on success, NULL on error.
|
||||||
|
*/
|
||||||
|
struct drm_display_mode *
|
||||||
|
drm_mode_create_from_cmdline_mode(struct drm_device *dev,
|
||||||
|
struct drm_cmdline_mode *cmd)
|
||||||
|
{
|
||||||
|
struct drm_display_mode *mode;
|
||||||
|
|
||||||
|
if (cmd->cvt)
|
||||||
|
mode = drm_cvt_mode(dev,
|
||||||
|
cmd->xres, cmd->yres,
|
||||||
|
cmd->refresh_specified ? cmd->refresh : 60,
|
||||||
|
cmd->rb, cmd->interlace,
|
||||||
|
cmd->margins);
|
||||||
|
else
|
||||||
|
mode = drm_gtf_mode(dev,
|
||||||
|
cmd->xres, cmd->yres,
|
||||||
|
cmd->refresh_specified ? cmd->refresh : 60,
|
||||||
|
cmd->interlace,
|
||||||
|
cmd->margins);
|
||||||
|
if (!mode)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
mode->type |= DRM_MODE_TYPE_USERDEF;
|
||||||
|
drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
|
||||||
|
return mode;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(drm_mode_create_from_cmdline_mode);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* drm_crtc_convert_to_umode - convert a drm_display_mode into a modeinfo
|
* drm_crtc_convert_to_umode - convert a drm_display_mode into a modeinfo
|
||||||
* @out: drm_mode_modeinfo struct to return to the user
|
* @out: drm_mode_modeinfo struct to return to the user
|
||||||
|
@ -189,6 +189,7 @@ static int drm_helper_probe_single_connector_modes_merge_bits(struct drm_connect
|
|||||||
|
|
||||||
if (count == 0 && connector->status == connector_status_connected)
|
if (count == 0 && connector->status == connector_status_connected)
|
||||||
count = drm_add_modes_noedid(connector, 1024, 768);
|
count = drm_add_modes_noedid(connector, 1024, 768);
|
||||||
|
count += drm_helper_probe_add_cmdline_mode(connector);
|
||||||
if (count == 0)
|
if (count == 0)
|
||||||
goto prune;
|
goto prune;
|
||||||
|
|
||||||
|
@ -10,15 +10,34 @@ dd mem
|
|||||||
dd cmdline
|
dd cmdline
|
||||||
dd path
|
dd path
|
||||||
|
|
||||||
|
SRV_CMDLINE equ 4
|
||||||
|
|
||||||
start:
|
start:
|
||||||
mov eax, 68
|
mov eax, 68
|
||||||
mov ebx, 16
|
mov ebx, 16
|
||||||
mov ecx, sz_display
|
mov ecx, sz_display
|
||||||
int 0x40
|
int 0x40
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jnz .done ; FIXME parse command line and
|
jz .load
|
||||||
; call service
|
|
||||||
|
|
||||||
|
xor ebx, ebx
|
||||||
|
|
||||||
|
push ebx ;.out_size
|
||||||
|
push ebx ;.output
|
||||||
|
push 4 ;.inp_size
|
||||||
|
push cmdline ;.input
|
||||||
|
push SRV_CMDLINE ;.code
|
||||||
|
push eax ;.handle
|
||||||
|
|
||||||
|
mov eax, 68
|
||||||
|
mov ebx, 17
|
||||||
|
mov ecx, esp ;[ioctl]
|
||||||
|
int 0x40
|
||||||
|
|
||||||
|
mov eax, -1
|
||||||
|
int 0x40
|
||||||
|
|
||||||
|
.load:
|
||||||
xor eax, eax
|
xor eax, eax
|
||||||
mov ecx, 1024
|
mov ecx, 1024
|
||||||
mov edi, path
|
mov edi, path
|
||||||
@ -32,7 +51,7 @@ start:
|
|||||||
mov ecx, path
|
mov ecx, path
|
||||||
mov edx, cmdline
|
mov edx, cmdline
|
||||||
int 0x40
|
int 0x40
|
||||||
.done:
|
|
||||||
mov eax, -1
|
mov eax, -1
|
||||||
int 0x40
|
int 0x40
|
||||||
|
|
||||||
|
@ -852,6 +852,14 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
|
|||||||
if (ret)
|
if (ret)
|
||||||
goto out_freecsr;
|
goto out_freecsr;
|
||||||
|
|
||||||
|
/* WARNING: Apparently we must kick fbdev drivers before vgacon,
|
||||||
|
* otherwise the vga fbdev driver falls over. */
|
||||||
|
ret = i915_kick_out_firmware_fb(dev_priv);
|
||||||
|
if (ret) {
|
||||||
|
DRM_ERROR("failed to remove conflicting framebuffer drivers\n");
|
||||||
|
goto out_gtt;
|
||||||
|
}
|
||||||
|
|
||||||
ret = i915_kick_out_vgacon(dev_priv);
|
ret = i915_kick_out_vgacon(dev_priv);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
DRM_ERROR("failed to remove conflicting VGA console\n");
|
DRM_ERROR("failed to remove conflicting VGA console\n");
|
||||||
@ -927,11 +935,11 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
|
|||||||
|
|
||||||
intel_init_dpio(dev_priv);
|
intel_init_dpio(dev_priv);
|
||||||
|
|
||||||
// if (INTEL_INFO(dev)->num_pipes) {
|
if (INTEL_INFO(dev)->num_pipes) {
|
||||||
// ret = drm_vblank_init(dev, INTEL_INFO(dev)->num_pipes);
|
ret = drm_vblank_init(dev, INTEL_INFO(dev)->num_pipes);
|
||||||
// if (ret)
|
if (ret)
|
||||||
// goto out_gem_unload;
|
goto out_gem_unload;
|
||||||
// }
|
}
|
||||||
|
|
||||||
intel_power_domains_init(dev_priv);
|
intel_power_domains_init(dev_priv);
|
||||||
|
|
||||||
|
@ -2691,6 +2691,10 @@ struct i915_params {
|
|||||||
bool verbose_state_checks;
|
bool verbose_state_checks;
|
||||||
bool nuclear_pageflip;
|
bool nuclear_pageflip;
|
||||||
int edp_vswing;
|
int edp_vswing;
|
||||||
|
/* Kolibri related */
|
||||||
|
int fbsize;
|
||||||
|
char *log_file;
|
||||||
|
char *cmdline_mode;
|
||||||
};
|
};
|
||||||
extern struct i915_params i915 __read_mostly;
|
extern struct i915_params i915 __read_mostly;
|
||||||
|
|
||||||
|
@ -1010,11 +1010,9 @@ int __i915_wait_request(struct drm_i915_gem_request *req,
|
|||||||
const bool irq_test_in_progress =
|
const bool irq_test_in_progress =
|
||||||
ACCESS_ONCE(dev_priv->gpu_error.test_irq_rings) & intel_ring_flag(ring);
|
ACCESS_ONCE(dev_priv->gpu_error.test_irq_rings) & intel_ring_flag(ring);
|
||||||
int state = interruptible ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE;
|
int state = interruptible ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE;
|
||||||
DEFINE_WAIT(wait);
|
wait_queue_t wait;
|
||||||
unsigned long timeout_expire;
|
unsigned long timeout_expire;
|
||||||
s64 before, now;
|
s64 before, now;
|
||||||
|
|
||||||
wait_queue_t __wait;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
WARN(!intel_irqs_enabled(dev_priv), "IRQs disabled");
|
WARN(!intel_irqs_enabled(dev_priv), "IRQs disabled");
|
||||||
@ -1053,9 +1051,8 @@ int __i915_wait_request(struct drm_i915_gem_request *req,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
INIT_LIST_HEAD(&__wait.task_list);
|
INIT_LIST_HEAD(&wait.task_list);
|
||||||
__wait.evnt = CreateEvent(NULL, MANUAL_DESTROY);
|
wait.evnt = CreateEvent(NULL, MANUAL_DESTROY);
|
||||||
|
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
@ -1082,25 +1079,25 @@ int __i915_wait_request(struct drm_i915_gem_request *req,
|
|||||||
}
|
}
|
||||||
|
|
||||||
spin_lock_irqsave(&ring->irq_queue.lock, flags);
|
spin_lock_irqsave(&ring->irq_queue.lock, flags);
|
||||||
if (list_empty(&__wait.task_list))
|
if (list_empty(&wait.task_list))
|
||||||
__add_wait_queue(&ring->irq_queue, &__wait);
|
__add_wait_queue(&ring->irq_queue, &wait);
|
||||||
spin_unlock_irqrestore(&ring->irq_queue.lock, flags);
|
spin_unlock_irqrestore(&ring->irq_queue.lock, flags);
|
||||||
|
|
||||||
WaitEventTimeout(__wait.evnt, 1);
|
WaitEventTimeout(wait.evnt, 1);
|
||||||
|
|
||||||
if (!list_empty(&__wait.task_list)) {
|
if (!list_empty(&wait.task_list)) {
|
||||||
spin_lock_irqsave(&ring->irq_queue.lock, flags);
|
spin_lock_irqsave(&ring->irq_queue.lock, flags);
|
||||||
list_del_init(&__wait.task_list);
|
list_del_init(&wait.task_list);
|
||||||
spin_unlock_irqrestore(&ring->irq_queue.lock, flags);
|
spin_unlock_irqrestore(&ring->irq_queue.lock, flags);
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
DestroyEvent(__wait.evnt);
|
};
|
||||||
|
|
||||||
if (!irq_test_in_progress)
|
if (!irq_test_in_progress)
|
||||||
ring->irq_put(ring);
|
ring->irq_put(ring);
|
||||||
|
|
||||||
// finish_wait(&ring->irq_queue, &wait);
|
DestroyEvent(wait.evnt);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
now = ktime_get_raw_ns();
|
now = ktime_get_raw_ns();
|
||||||
trace_i915_gem_request_wait_end(req);
|
trace_i915_gem_request_wait_end(req);
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||||
|
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
|
#include <linux/circ_buf.h>
|
||||||
#include <drm/drmP.h>
|
#include <drm/drmP.h>
|
||||||
#include <drm/i915_drm.h>
|
#include <drm/i915_drm.h>
|
||||||
#include "i915_drv.h"
|
#include "i915_drv.h"
|
||||||
@ -1444,7 +1445,7 @@ static void intel_get_hpd_pins(u32 *pin_mask, u32 *long_mask,
|
|||||||
*pin_mask |= BIT(i);
|
*pin_mask |= BIT(i);
|
||||||
|
|
||||||
// if (!intel_hpd_pin_to_port(i, &port))
|
// if (!intel_hpd_pin_to_port(i, &port))
|
||||||
continue;
|
// continue;
|
||||||
|
|
||||||
if (long_pulse_detect(port, dig_hotplug_reg))
|
if (long_pulse_detect(port, dig_hotplug_reg))
|
||||||
*long_mask |= BIT(i);
|
*long_mask |= BIT(i);
|
||||||
@ -1594,8 +1595,8 @@ static void gen6_rps_irq_handler(struct drm_i915_private *dev_priv, u32 pm_iir)
|
|||||||
|
|
||||||
static bool intel_pipe_handle_vblank(struct drm_device *dev, enum pipe pipe)
|
static bool intel_pipe_handle_vblank(struct drm_device *dev, enum pipe pipe)
|
||||||
{
|
{
|
||||||
// if (!drm_handle_vblank(dev, pipe))
|
if (!drm_handle_vblank(dev, pipe))
|
||||||
// return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -2281,6 +2282,9 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg)
|
|||||||
ret = IRQ_HANDLED;
|
ret = IRQ_HANDLED;
|
||||||
I915_WRITE(GEN8_DE_PIPE_IIR(pipe), pipe_iir);
|
I915_WRITE(GEN8_DE_PIPE_IIR(pipe), pipe_iir);
|
||||||
|
|
||||||
|
if (pipe_iir & GEN8_PIPE_VBLANK &&
|
||||||
|
intel_pipe_handle_vblank(dev, pipe))
|
||||||
|
/* intel_check_page_flip(dev, pipe)*/;
|
||||||
|
|
||||||
if (INTEL_INFO(dev_priv)->gen >= 9)
|
if (INTEL_INFO(dev_priv)->gen >= 9)
|
||||||
flip_done = pipe_iir & GEN9_PIPE_PLANE1_FLIP_DONE;
|
flip_done = pipe_iir & GEN9_PIPE_PLANE1_FLIP_DONE;
|
||||||
@ -2419,7 +2423,7 @@ static void i915_reset_and_wakeup(struct drm_device *dev)
|
|||||||
atomic_inc(&dev_priv->gpu_error.reset_counter);
|
atomic_inc(&dev_priv->gpu_error.reset_counter);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
atomic_set_mask(I915_WEDGED, &error->reset_counter);
|
atomic_or(I915_WEDGED, &error->reset_counter);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -3009,6 +3013,7 @@ static void i915_hangcheck_elapsed(struct work_struct *work)
|
|||||||
// return i915_handle_error(dev, true);
|
// return i915_handle_error(dev, true);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ibx_irq_reset(struct drm_device *dev)
|
static void ibx_irq_reset(struct drm_device *dev)
|
||||||
{
|
{
|
||||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||||
@ -3933,6 +3938,7 @@ static bool i915_handle_vblank(struct drm_device *dev,
|
|||||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||||
u32 flip_pending = DISPLAY_PLANE_FLIP_PENDING(plane);
|
u32 flip_pending = DISPLAY_PLANE_FLIP_PENDING(plane);
|
||||||
|
|
||||||
|
if (!intel_pipe_handle_vblank(dev, pipe))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if ((iir & flip_pending) == 0)
|
if ((iir & flip_pending) == 0)
|
||||||
|
@ -55,6 +55,9 @@ struct i915_params i915 __read_mostly = {
|
|||||||
.edp_vswing = 0,
|
.edp_vswing = 0,
|
||||||
.enable_guc_submission = false,
|
.enable_guc_submission = false,
|
||||||
.guc_log_level = -1,
|
.guc_log_level = -1,
|
||||||
|
.fbsize = 16,
|
||||||
|
.log_file = NULL,
|
||||||
|
.cmdline_mode = NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
module_param_named(modeset, i915.modeset, int, 0400);
|
module_param_named(modeset, i915.modeset, int, 0400);
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
|
|
||||||
#include <linux/dmi.h>
|
#include <linux/dmi.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
//#include <linux/input.h>
|
#include <linux/input.h>
|
||||||
#include <linux/i2c.h>
|
#include <linux/i2c.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
@ -8065,7 +8065,7 @@ i9xx_get_initial_plane_config(struct intel_crtc *crtc,
|
|||||||
fb->modifier[0]);
|
fb->modifier[0]);
|
||||||
|
|
||||||
// plane_config->size = fb->pitches[0] * aligned_height;
|
// plane_config->size = fb->pitches[0] * aligned_height;
|
||||||
plane_config->size = i915_fbsize*1024*1024;
|
plane_config->size = i915.fbsize*1024*1024;
|
||||||
|
|
||||||
DRM_DEBUG_KMS("pipe/plane %c/%d with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n",
|
DRM_DEBUG_KMS("pipe/plane %c/%d with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n",
|
||||||
pipe_name(pipe), plane, fb->width, fb->height,
|
pipe_name(pipe), plane, fb->width, fb->height,
|
||||||
@ -9131,7 +9131,7 @@ skylake_get_initial_plane_config(struct intel_crtc *crtc,
|
|||||||
fb->modifier[0]);
|
fb->modifier[0]);
|
||||||
|
|
||||||
// plane_config->size = fb->pitches[0] * aligned_height;
|
// plane_config->size = fb->pitches[0] * aligned_height;
|
||||||
plane_config->size = i915_fbsize*1024*1024;
|
plane_config->size = i915.fbsize*1024*1024;
|
||||||
|
|
||||||
DRM_DEBUG_KMS("pipe %c with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n",
|
DRM_DEBUG_KMS("pipe %c with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n",
|
||||||
pipe_name(pipe), fb->width, fb->height,
|
pipe_name(pipe), fb->width, fb->height,
|
||||||
@ -9230,7 +9230,7 @@ ironlake_get_initial_plane_config(struct intel_crtc *crtc,
|
|||||||
fb->modifier[0]);
|
fb->modifier[0]);
|
||||||
|
|
||||||
// plane_config->size = fb->pitches[0] * aligned_height;
|
// plane_config->size = fb->pitches[0] * aligned_height;
|
||||||
plane_config->size = i915_fbsize*1024*1024;
|
plane_config->size = i915.fbsize*1024*1024;
|
||||||
|
|
||||||
DRM_DEBUG_KMS("pipe %c with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n",
|
DRM_DEBUG_KMS("pipe %c with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n",
|
||||||
pipe_name(pipe), fb->width, fb->height,
|
pipe_name(pipe), fb->width, fb->height,
|
||||||
@ -13250,8 +13250,7 @@ static int intel_atomic_commit(struct drm_device *dev,
|
|||||||
|
|
||||||
/* FIXME: add subpixel order */
|
/* FIXME: add subpixel order */
|
||||||
|
|
||||||
// drm_atomic_helper_wait_for_vblanks(dev, state);
|
drm_atomic_helper_wait_for_vblanks(dev, state);
|
||||||
|
|
||||||
drm_atomic_helper_cleanup_planes(dev, state);
|
drm_atomic_helper_cleanup_planes(dev, state);
|
||||||
|
|
||||||
if (any_ms)
|
if (any_ms)
|
||||||
@ -14826,7 +14825,7 @@ void intel_modeset_init(struct drm_device *dev)
|
|||||||
int sprite, ret;
|
int sprite, ret;
|
||||||
enum pipe pipe;
|
enum pipe pipe;
|
||||||
struct intel_crtc *crtc;
|
struct intel_crtc *crtc;
|
||||||
ENTER();
|
|
||||||
drm_mode_config_init(dev);
|
drm_mode_config_init(dev);
|
||||||
|
|
||||||
dev->mode_config.min_width = 0;
|
dev->mode_config.min_width = 0;
|
||||||
@ -14949,9 +14948,6 @@ ENTER();
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
LEAVE();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void intel_enable_pipe_a(struct drm_device *dev)
|
static void intel_enable_pipe_a(struct drm_device *dev)
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
#include <linux/sysrq.h>
|
#include <linux/sysrq.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/fb.h>
|
#include <linux/fb.h>
|
||||||
//#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
//#include <linux/vga_switcheroo.h>
|
//#include <linux/vga_switcheroo.h>
|
||||||
|
|
||||||
#include <drm/drmP.h>
|
#include <drm/drmP.h>
|
||||||
|
@ -80,7 +80,6 @@ static int usecs_to_scanlines(const struct drm_display_mode *adjusted_mode,
|
|||||||
*/
|
*/
|
||||||
void intel_pipe_update_start(struct intel_crtc *crtc)
|
void intel_pipe_update_start(struct intel_crtc *crtc)
|
||||||
{
|
{
|
||||||
ENTER();
|
|
||||||
struct drm_device *dev = crtc->base.dev;
|
struct drm_device *dev = crtc->base.dev;
|
||||||
const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode;
|
const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode;
|
||||||
enum pipe pipe = crtc->pipe;
|
enum pipe pipe = crtc->pipe;
|
||||||
|
@ -34,6 +34,7 @@ void __stdcall restore_cursor(int x, int y)
|
|||||||
void disable_mouse(void)
|
void disable_mouse(void)
|
||||||
{};
|
{};
|
||||||
|
|
||||||
|
struct mutex cursor_lock;
|
||||||
|
|
||||||
static char *manufacturer_name(unsigned char *x)
|
static char *manufacturer_name(unsigned char *x)
|
||||||
{
|
{
|
||||||
@ -47,6 +48,17 @@ static char *manufacturer_name(unsigned char *x)
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int count_connector_modes(struct drm_connector* connector)
|
||||||
|
{
|
||||||
|
struct drm_display_mode *mode;
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
list_for_each_entry(mode, &connector->modes, head)
|
||||||
|
count++;
|
||||||
|
|
||||||
|
return count;
|
||||||
|
};
|
||||||
|
|
||||||
static int set_mode(struct drm_device *dev, struct drm_connector *connector,
|
static int set_mode(struct drm_device *dev, struct drm_connector *connector,
|
||||||
struct drm_crtc *crtc, videomode_t *reqmode, bool strict)
|
struct drm_crtc *crtc, videomode_t *reqmode, bool strict)
|
||||||
{
|
{
|
||||||
@ -54,6 +66,7 @@ static int set_mode(struct drm_device *dev, struct drm_connector *connector,
|
|||||||
|
|
||||||
struct drm_mode_config *config = &dev->mode_config;
|
struct drm_mode_config *config = &dev->mode_config;
|
||||||
struct drm_display_mode *mode = NULL, *tmpmode;
|
struct drm_display_mode *mode = NULL, *tmpmode;
|
||||||
|
struct drm_connector *tmpc;
|
||||||
struct drm_framebuffer *fb = NULL;
|
struct drm_framebuffer *fb = NULL;
|
||||||
struct drm_mode_set set;
|
struct drm_mode_set set;
|
||||||
const char *con_name;
|
const char *con_name;
|
||||||
@ -65,6 +78,14 @@ ENTER();
|
|||||||
|
|
||||||
drm_modeset_lock_all(dev);
|
drm_modeset_lock_all(dev);
|
||||||
|
|
||||||
|
list_for_each_entry(tmpc, &dev->mode_config.connector_list, head)
|
||||||
|
{
|
||||||
|
const struct drm_connector_funcs *f = tmpc->funcs;
|
||||||
|
if(tmpc == connector)
|
||||||
|
continue;
|
||||||
|
f->dpms(tmpc, DRM_MODE_DPMS_OFF);
|
||||||
|
};
|
||||||
|
|
||||||
list_for_each_entry(tmpmode, &connector->modes, head)
|
list_for_each_entry(tmpmode, &connector->modes, head)
|
||||||
{
|
{
|
||||||
if( (tmpmode->hdisplay == reqmode->width) &&
|
if( (tmpmode->hdisplay == reqmode->width) &&
|
||||||
@ -95,8 +116,18 @@ ENTER();
|
|||||||
|
|
||||||
do_set:
|
do_set:
|
||||||
|
|
||||||
|
|
||||||
con_name = connector->name;
|
con_name = connector->name;
|
||||||
|
|
||||||
|
char con_edid[128];
|
||||||
|
|
||||||
|
memcpy(con_edid, connector->edid_blob_ptr->data, 128);
|
||||||
|
DRM_DEBUG_KMS("Manufacturer: %s Model %x Serial Number %u\n",
|
||||||
|
manufacturer_name(con_edid + 0x08),
|
||||||
|
(unsigned short)(con_edid[0x0A] + (con_edid[0x0B] << 8)),
|
||||||
|
(unsigned int)(con_edid[0x0C] + (con_edid[0x0D] << 8)
|
||||||
|
+ (con_edid[0x0E] << 16) + (con_edid[0x0F] << 24)));
|
||||||
|
|
||||||
DRM_DEBUG_KMS("set mode %d %d: crtc %d connector %s\n",
|
DRM_DEBUG_KMS("set mode %d %d: crtc %d connector %s\n",
|
||||||
reqmode->width, reqmode->height, crtc->base.id,
|
reqmode->width, reqmode->height, crtc->base.id,
|
||||||
con_name);
|
con_name);
|
||||||
@ -180,16 +211,135 @@ LEAVE();
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int count_connector_modes(struct drm_connector* connector)
|
static int set_mode_ex(struct drm_device *dev,
|
||||||
|
struct drm_connector *connector, struct drm_display_mode *mode)
|
||||||
|
{
|
||||||
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||||
|
struct drm_connector *tmpc;
|
||||||
|
struct drm_mode_config *config = &dev->mode_config;
|
||||||
|
struct drm_framebuffer *fb = NULL;
|
||||||
|
struct drm_mode_set set;
|
||||||
|
char con_edid[128];
|
||||||
|
int stride;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ENTER();
|
||||||
|
|
||||||
|
drm_modeset_lock_all(dev);
|
||||||
|
|
||||||
|
list_for_each_entry(tmpc, &dev->mode_config.connector_list, head)
|
||||||
|
{
|
||||||
|
const struct drm_connector_funcs *f = tmpc->funcs;
|
||||||
|
if(tmpc == connector)
|
||||||
|
continue;
|
||||||
|
f->dpms(tmpc, DRM_MODE_DPMS_OFF);
|
||||||
|
};
|
||||||
|
|
||||||
|
drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
|
||||||
|
|
||||||
|
fb = connector->encoder->crtc->primary->fb;
|
||||||
|
if(fb == NULL)
|
||||||
|
fb = main_framebuffer;
|
||||||
|
|
||||||
|
fb->width = mode->hdisplay;
|
||||||
|
fb->height = mode->vdisplay;;
|
||||||
|
|
||||||
|
main_fb_obj->tiling_mode = I915_TILING_X;
|
||||||
|
|
||||||
|
if( main_fb_obj->tiling_mode == I915_TILING_X)
|
||||||
|
{
|
||||||
|
if(IS_GEN3(dev))
|
||||||
|
for (stride = 512; stride < mode->hdisplay * 4; stride <<= 1);
|
||||||
|
else
|
||||||
|
stride = ALIGN(mode->hdisplay * 4, 512);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
stride = ALIGN(mode->hdisplay * 4, 64);
|
||||||
|
}
|
||||||
|
|
||||||
|
fb->pitches[0] =
|
||||||
|
fb->pitches[1] =
|
||||||
|
fb->pitches[2] =
|
||||||
|
fb->pitches[3] = stride;
|
||||||
|
|
||||||
|
main_fb_obj->stride = stride;
|
||||||
|
|
||||||
|
fb->bits_per_pixel = 32;
|
||||||
|
fb->depth = 24;
|
||||||
|
|
||||||
|
connector->encoder->crtc->enabled = true;
|
||||||
|
|
||||||
|
i915_gem_object_put_fence(main_fb_obj);
|
||||||
|
|
||||||
|
memcpy(con_edid, connector->edid_blob_ptr->data, 128);
|
||||||
|
DRM_DEBUG_KMS("set mode %dx%d: crtc %d connector %s\n"
|
||||||
|
"monitor: %s model %x serial number %u\n",
|
||||||
|
fb->width, fb->height,
|
||||||
|
connector->encoder->crtc->base.id, connector->name,
|
||||||
|
manufacturer_name(con_edid + 0x08),
|
||||||
|
(unsigned short)(con_edid[0x0A] + (con_edid[0x0B] << 8)),
|
||||||
|
(unsigned int)(con_edid[0x0C] + (con_edid[0x0D] << 8)
|
||||||
|
+ (con_edid[0x0E] << 16) + (con_edid[0x0F] << 24)));
|
||||||
|
|
||||||
|
DRM_DEBUG_KMS("use framebuffer %p %dx%d pitch %d format %x\n",
|
||||||
|
fb,fb->width,fb->height,fb->pitches[0],fb->pixel_format);
|
||||||
|
|
||||||
|
set.crtc = connector->encoder->crtc;
|
||||||
|
set.x = 0;
|
||||||
|
set.y = 0;
|
||||||
|
set.mode = mode;
|
||||||
|
set.connectors = &connector;
|
||||||
|
set.num_connectors = 1;
|
||||||
|
set.fb = fb;
|
||||||
|
|
||||||
|
ret = drm_mode_set_config_internal(&set);
|
||||||
|
if ( !ret )
|
||||||
|
{
|
||||||
|
struct drm_crtc *crtc = os_display->crtc;
|
||||||
|
|
||||||
|
os_display->width = fb->width;
|
||||||
|
os_display->height = fb->height;
|
||||||
|
os_display->vrefresh = drm_mode_vrefresh(mode);
|
||||||
|
|
||||||
|
sysSetScreen(fb->width, fb->height, fb->pitches[0]);
|
||||||
|
|
||||||
|
os_display->connector = connector;
|
||||||
|
os_display->crtc = connector->encoder->crtc;
|
||||||
|
os_display->supported_modes = count_connector_modes(connector);
|
||||||
|
|
||||||
|
crtc->cursor_x = os_display->width/2;
|
||||||
|
crtc->cursor_y = os_display->height/2;
|
||||||
|
|
||||||
|
select_cursor_kms(os_display->cursor);
|
||||||
|
|
||||||
|
DRM_DEBUG_KMS("new mode %d x %d pitch %d\n",
|
||||||
|
fb->width, fb->height, fb->pitches[0]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
DRM_ERROR(" failed to set mode %d_%d on crtc %p\n",
|
||||||
|
fb->width, fb->height, connector->encoder->crtc);
|
||||||
|
|
||||||
|
drm_modeset_unlock_all(dev);
|
||||||
|
|
||||||
|
LEAVE();
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int set_cmdline_mode(struct drm_device *dev, struct drm_connector *connector)
|
||||||
{
|
{
|
||||||
struct drm_display_mode *mode;
|
struct drm_display_mode *mode;
|
||||||
int count = 0;
|
int retval;
|
||||||
|
|
||||||
list_for_each_entry(mode, &connector->modes, head)
|
mode = drm_mode_create_from_cmdline_mode(dev, &connector->cmdline_mode);
|
||||||
{
|
if(mode == NULL)
|
||||||
count++;
|
return EINVAL;
|
||||||
};
|
|
||||||
return count;
|
retval = set_mode_ex(dev, connector, mode);
|
||||||
|
|
||||||
|
drm_mode_destroy(dev, mode);
|
||||||
|
return retval;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct drm_crtc *get_possible_crtc(struct drm_device *dev, struct drm_encoder *encoder)
|
static struct drm_crtc *get_possible_crtc(struct drm_device *dev, struct drm_encoder *encoder)
|
||||||
@ -210,18 +360,14 @@ static struct drm_crtc *get_possible_crtc(struct drm_device *dev, struct drm_enc
|
|||||||
return NULL;
|
return NULL;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int choose_config(struct drm_device *dev, struct drm_connector **boot_connector,
|
static int check_connector(struct drm_device *dev, struct drm_connector *connector)
|
||||||
struct drm_crtc **boot_crtc)
|
|
||||||
{
|
{
|
||||||
struct drm_connector_helper_funcs *connector_funcs;
|
const struct drm_connector_helper_funcs *connector_funcs;
|
||||||
struct drm_connector *connector;
|
|
||||||
struct drm_encoder *encoder;
|
struct drm_encoder *encoder;
|
||||||
struct drm_crtc *crtc;
|
struct drm_crtc *crtc;
|
||||||
|
|
||||||
list_for_each_entry(connector, &dev->mode_config.connector_list, head)
|
|
||||||
{
|
|
||||||
if( connector->status != connector_status_connected)
|
if( connector->status != connector_status_connected)
|
||||||
continue;
|
return -EINVAL;
|
||||||
|
|
||||||
encoder = connector->encoder;
|
encoder = connector->encoder;
|
||||||
|
|
||||||
@ -234,7 +380,7 @@ static int choose_config(struct drm_device *dev, struct drm_connector **boot_con
|
|||||||
{
|
{
|
||||||
DRM_DEBUG_KMS("CONNECTOR %s ID: %d no active encoders\n",
|
DRM_DEBUG_KMS("CONNECTOR %s ID: %d no active encoders\n",
|
||||||
connector->name, connector->base.id);
|
connector->name, connector->base.id);
|
||||||
continue;
|
return -EINVAL;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -244,26 +390,62 @@ static int choose_config(struct drm_device *dev, struct drm_connector **boot_con
|
|||||||
|
|
||||||
if(crtc != NULL)
|
if(crtc != NULL)
|
||||||
{
|
{
|
||||||
*boot_connector = connector;
|
encoder->crtc = crtc;
|
||||||
*boot_crtc = crtc;
|
|
||||||
|
|
||||||
DRM_DEBUG_KMS("CONNECTOR %s ID:%d status:%d ENCODER %p ID: %d CRTC %p ID:%d\n",
|
|
||||||
connector->name, connector->base.id, connector->status,
|
|
||||||
encoder, encoder->base.id, crtc, crtc->base.id );
|
|
||||||
char con_edid[128];
|
|
||||||
|
|
||||||
memcpy(con_edid, connector->edid_blob_ptr->data, 128);
|
|
||||||
printf("Manufacturer: %s Model %x Serial Number %u\n",
|
|
||||||
manufacturer_name(con_edid + 0x08),
|
|
||||||
(unsigned short)(con_edid[0x0A] + (con_edid[0x0B] << 8)),
|
|
||||||
(unsigned int)(con_edid[0x0C] + (con_edid[0x0D] << 8)
|
|
||||||
+ (con_edid[0x0E] << 16) + (con_edid[0x0F] << 24)));
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
DRM_DEBUG_KMS("No CRTC for encoder %d\n", encoder->base.id);
|
DRM_DEBUG_KMS("No CRTC for encoder %d\n", encoder->base.id);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct drm_connector* get_cmdline_connector(struct drm_device *dev, const char *cmdline)
|
||||||
|
{
|
||||||
|
struct drm_connector *connector;
|
||||||
|
|
||||||
|
list_for_each_entry(connector, &dev->mode_config.connector_list, head)
|
||||||
|
{
|
||||||
|
int name_len = __builtin_strlen(connector->name);
|
||||||
|
|
||||||
|
if (name_len == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (__builtin_strncmp(connector->name, cmdline, name_len))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if(check_connector(dev, connector) == 0)
|
||||||
|
return connector;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int choose_config(struct drm_device *dev, struct drm_connector **boot_connector,
|
||||||
|
struct drm_crtc **boot_crtc)
|
||||||
|
{
|
||||||
|
const struct drm_connector_helper_funcs *connector_funcs;
|
||||||
|
struct drm_connector *connector = NULL;
|
||||||
|
struct drm_encoder *encoder = NULL;
|
||||||
|
struct drm_crtc *crtc = NULL;
|
||||||
|
|
||||||
|
if((i915.cmdline_mode != NULL) && (*i915.cmdline_mode != 0))
|
||||||
|
{
|
||||||
|
connector = get_cmdline_connector(dev, i915.cmdline_mode);
|
||||||
|
if(connector != NULL)
|
||||||
|
{
|
||||||
|
*boot_connector = connector;
|
||||||
|
*boot_crtc = connector->encoder->crtc;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
list_for_each_entry(connector, &dev->mode_config.connector_list, head)
|
||||||
|
{
|
||||||
|
if(check_connector(dev, connector) == 0)
|
||||||
|
{
|
||||||
|
*boot_connector = connector;
|
||||||
|
*boot_crtc = connector->encoder->crtc;
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
@ -275,10 +457,6 @@ static int get_boot_mode(struct drm_connector *connector, videomode_t *usermode)
|
|||||||
|
|
||||||
list_for_each_entry(mode, &connector->modes, head)
|
list_for_each_entry(mode, &connector->modes, head)
|
||||||
{
|
{
|
||||||
DRM_DEBUG_KMS("check mode w:%d h:%d %dHz\n",
|
|
||||||
mode->hdisplay, mode->vdisplay,
|
|
||||||
drm_mode_vrefresh(mode));
|
|
||||||
|
|
||||||
if( os_display->width == mode->hdisplay &&
|
if( os_display->width == mode->hdisplay &&
|
||||||
os_display->height == mode->vdisplay &&
|
os_display->height == mode->vdisplay &&
|
||||||
drm_mode_vrefresh(mode) == 60)
|
drm_mode_vrefresh(mode) == 60)
|
||||||
@ -305,14 +483,12 @@ int init_display_kms(struct drm_device *dev, videomode_t *usermode)
|
|||||||
|
|
||||||
ENTER();
|
ENTER();
|
||||||
|
|
||||||
mutex_lock(&dev->struct_mutex);
|
|
||||||
mutex_lock(&dev->mode_config.mutex);
|
mutex_lock(&dev->mode_config.mutex);
|
||||||
|
|
||||||
ret = choose_config(dev, &connector, &crtc);
|
ret = choose_config(dev, &connector, &crtc);
|
||||||
if(ret)
|
if(ret)
|
||||||
{
|
{
|
||||||
DRM_DEBUG_KMS("No active connectors!\n");
|
|
||||||
mutex_unlock(&dev->mode_config.mutex);
|
mutex_unlock(&dev->mode_config.mutex);
|
||||||
|
DRM_DEBUG_KMS("No active connectors!\n");
|
||||||
return -1;
|
return -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -334,8 +510,11 @@ ENTER();
|
|||||||
os_display->ddev = dev;
|
os_display->ddev = dev;
|
||||||
os_display->connector = connector;
|
os_display->connector = connector;
|
||||||
os_display->crtc = crtc;
|
os_display->crtc = crtc;
|
||||||
|
|
||||||
os_display->supported_modes = count_connector_modes(connector);
|
os_display->supported_modes = count_connector_modes(connector);
|
||||||
|
mutex_unlock(&dev->mode_config.mutex);
|
||||||
|
|
||||||
|
mutex_init(&cursor_lock);
|
||||||
|
mutex_lock(&dev->struct_mutex);
|
||||||
|
|
||||||
ifl = safe_cli();
|
ifl = safe_cli();
|
||||||
{
|
{
|
||||||
@ -359,6 +538,17 @@ ENTER();
|
|||||||
};
|
};
|
||||||
safe_sti(ifl);
|
safe_sti(ifl);
|
||||||
|
|
||||||
|
mutex_unlock(&dev->struct_mutex);
|
||||||
|
|
||||||
|
ret = -1;
|
||||||
|
|
||||||
|
if(connector->cmdline_mode.specified == true)
|
||||||
|
ret = set_cmdline_mode(dev, connector);
|
||||||
|
|
||||||
|
if(ret !=0)
|
||||||
|
{
|
||||||
|
mutex_lock(&dev->mode_config.mutex);
|
||||||
|
|
||||||
if( (usermode->width == 0) ||
|
if( (usermode->width == 0) ||
|
||||||
(usermode->height == 0))
|
(usermode->height == 0))
|
||||||
{
|
{
|
||||||
@ -372,11 +562,10 @@ ENTER();
|
|||||||
usermode->freq = drm_mode_vrefresh(mode);
|
usermode->freq = drm_mode_vrefresh(mode);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
mutex_unlock(&dev->mode_config.mutex);
|
mutex_unlock(&dev->mode_config.mutex);
|
||||||
mutex_unlock(&dev->struct_mutex);
|
|
||||||
|
|
||||||
set_mode(dev, os_display->connector, os_display->crtc, usermode, false);
|
set_mode(dev, os_display->connector, os_display->crtc, usermode, false);
|
||||||
|
};
|
||||||
|
|
||||||
#ifdef __HWA__
|
#ifdef __HWA__
|
||||||
err = init_bitmaps();
|
err = init_bitmaps();
|
||||||
@ -384,10 +573,70 @@ ENTER();
|
|||||||
|
|
||||||
LEAVE();
|
LEAVE();
|
||||||
|
|
||||||
return 0;
|
return ret;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
int set_cmdline_mode_ext(struct drm_device *dev, const char *cmdline)
|
||||||
|
{
|
||||||
|
struct drm_connector_helper_funcs *connector_funcs;
|
||||||
|
struct drm_connector *connector;
|
||||||
|
struct drm_cmdline_mode cmd_mode;
|
||||||
|
struct drm_display_mode *mode;
|
||||||
|
char *mode_option;
|
||||||
|
int retval = 0;
|
||||||
|
char con_edid[128];
|
||||||
|
|
||||||
|
ENTER();
|
||||||
|
if((cmdline == NULL) || (*cmdline == 0))
|
||||||
|
return EINVAL;
|
||||||
|
|
||||||
|
mutex_lock(&dev->mode_config.mutex);
|
||||||
|
connector = get_cmdline_connector(dev, cmdline);
|
||||||
|
mutex_unlock(&dev->mode_config.mutex);
|
||||||
|
|
||||||
|
if(connector == NULL)
|
||||||
|
return EINVAL;
|
||||||
|
|
||||||
|
mode_option = __builtin_strchr(cmdline,':');
|
||||||
|
if(mode_option == NULL)
|
||||||
|
return EINVAL;
|
||||||
|
|
||||||
|
mode_option++;
|
||||||
|
|
||||||
|
__builtin_memset(&cmd_mode, 0, sizeof(cmd_mode));
|
||||||
|
|
||||||
|
if( !drm_mode_parse_command_line_for_connector(mode_option, connector, &cmd_mode))
|
||||||
|
return EINVAL;
|
||||||
|
|
||||||
|
DRM_DEBUG_KMS("cmdline mode for connector %s %dx%d@%dHz%s%s%s\n",
|
||||||
|
connector->name,
|
||||||
|
cmd_mode.xres, cmd_mode.yres,
|
||||||
|
cmd_mode.refresh_specified ? cmd_mode.refresh : 60,
|
||||||
|
cmd_mode.rb ? " reduced blanking" : "",
|
||||||
|
cmd_mode.margins ? " with margins" : "",
|
||||||
|
cmd_mode.interlace ? " interlaced" : "");
|
||||||
|
|
||||||
|
mode = drm_mode_create_from_cmdline_mode(dev, &cmd_mode);
|
||||||
|
if(mode == NULL)
|
||||||
|
return EINVAL;
|
||||||
|
|
||||||
|
memcpy(con_edid, connector->edid_blob_ptr->data, 128);
|
||||||
|
DRM_DEBUG_KMS("connector: %s monitor: %s model %x serial number %u\n",
|
||||||
|
connector->name,
|
||||||
|
manufacturer_name(con_edid + 0x08),
|
||||||
|
(unsigned short)(con_edid[0x0A] + (con_edid[0x0B] << 8)),
|
||||||
|
(unsigned int)(con_edid[0x0C] + (con_edid[0x0D] << 8)
|
||||||
|
+ (con_edid[0x0E] << 16) + (con_edid[0x0F] << 24)));
|
||||||
|
|
||||||
|
retval = set_mode_ex(dev, connector, mode);
|
||||||
|
|
||||||
|
drm_mode_destroy(dev, mode);
|
||||||
|
|
||||||
|
LEAVE();
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
int get_videomodes(videomode_t *mode, int *count)
|
int get_videomodes(videomode_t *mode, int *count)
|
||||||
{
|
{
|
||||||
int err = -1;
|
int err = -1;
|
||||||
@ -571,9 +820,10 @@ cursor_t* __stdcall select_cursor_kms(cursor_t *cursor)
|
|||||||
cursor_t *old;
|
cursor_t *old;
|
||||||
|
|
||||||
old = os_display->cursor;
|
old = os_display->cursor;
|
||||||
os_display->cursor = cursor;
|
|
||||||
|
|
||||||
// intel_crtc->cursor_bo = cursor->cobj;
|
mutex_lock(&cursor_lock);
|
||||||
|
|
||||||
|
os_display->cursor = cursor;
|
||||||
|
|
||||||
if (!dev_priv->info.cursor_needs_physical)
|
if (!dev_priv->info.cursor_needs_physical)
|
||||||
intel_crtc->cursor_addr = i915_gem_obj_ggtt_offset(cursor->cobj);
|
intel_crtc->cursor_addr = i915_gem_obj_ggtt_offset(cursor->cobj);
|
||||||
@ -583,6 +833,7 @@ cursor_t* __stdcall select_cursor_kms(cursor_t *cursor)
|
|||||||
intel_crtc->base.cursor->state->crtc_w = 64;
|
intel_crtc->base.cursor->state->crtc_w = 64;
|
||||||
intel_crtc->base.cursor->state->crtc_h = 64;
|
intel_crtc->base.cursor->state->crtc_h = 64;
|
||||||
intel_crtc->base.cursor->state->rotation = 0;
|
intel_crtc->base.cursor->state->rotation = 0;
|
||||||
|
mutex_unlock(&cursor_lock);
|
||||||
|
|
||||||
move_cursor_kms(cursor, crtc->cursor_x, crtc->cursor_y);
|
move_cursor_kms(cursor, crtc->cursor_x, crtc->cursor_y);
|
||||||
return old;
|
return old;
|
||||||
|
@ -9,7 +9,10 @@
|
|||||||
#include <linux/mod_devicetable.h>
|
#include <linux/mod_devicetable.h>
|
||||||
#include <linux/pci.h>
|
#include <linux/pci.h>
|
||||||
|
|
||||||
|
#include "getopt.h"
|
||||||
|
|
||||||
#include "bitmap.h"
|
#include "bitmap.h"
|
||||||
|
#include "i915_kos32.h"
|
||||||
|
|
||||||
#define DRV_NAME "i915 v4.4"
|
#define DRV_NAME "i915 v4.4"
|
||||||
|
|
||||||
@ -17,91 +20,21 @@
|
|||||||
#define I915_DEV_INIT 1
|
#define I915_DEV_INIT 1
|
||||||
#define I915_DEV_READY 2
|
#define I915_DEV_READY 2
|
||||||
|
|
||||||
|
static int my_atoi(char **cmd);
|
||||||
struct pci_device {
|
static char* parse_mode(char *p, videomode_t *mode);
|
||||||
uint16_t domain;
|
|
||||||
uint8_t bus;
|
|
||||||
uint8_t dev;
|
|
||||||
uint8_t func;
|
|
||||||
uint16_t vendor_id;
|
|
||||||
uint16_t device_id;
|
|
||||||
uint16_t subvendor_id;
|
|
||||||
uint16_t subdevice_id;
|
|
||||||
uint32_t device_class;
|
|
||||||
uint8_t revision;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct cmdtable
|
|
||||||
{
|
|
||||||
char *key;
|
|
||||||
int size;
|
|
||||||
int *val;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define CMDENTRY(key, val) {(key), (sizeof(key)-1), &val}
|
|
||||||
void parse_cmdline(char *cmdline, struct cmdtable *table, char *log, videomode_t *mode);
|
|
||||||
|
|
||||||
|
|
||||||
int oops_in_progress;
|
|
||||||
int i915_fbsize = 16;
|
|
||||||
struct drm_device *main_device;
|
|
||||||
struct drm_file *drm_file_handlers[256];
|
|
||||||
videomode_t usermode;
|
|
||||||
|
|
||||||
void cpu_detect1();
|
void cpu_detect1();
|
||||||
int kmap_init();
|
int kmap_init();
|
||||||
|
|
||||||
int _stdcall display_handler(ioctl_t *io);
|
|
||||||
int init_agp(void);
|
|
||||||
|
|
||||||
void get_pci_info(struct pci_device *dev);
|
|
||||||
int i915_getparam(struct drm_device *dev, void *data,
|
|
||||||
struct drm_file *file_priv);
|
|
||||||
|
|
||||||
int i915_mask_update(struct drm_device *dev, void *data,
|
|
||||||
struct drm_file *file);
|
|
||||||
|
|
||||||
struct cmdtable cmdtable[]= {
|
|
||||||
CMDENTRY("-FB=", i915_fbsize),
|
|
||||||
/* CMDENTRY("-pm=", i915.powersave), */
|
|
||||||
CMDENTRY("-rc6=", i915.enable_rc6),
|
|
||||||
CMDENTRY("-fbc=", i915.enable_fbc),
|
|
||||||
CMDENTRY("-ppgt=", i915.enable_ppgtt),
|
|
||||||
{NULL, 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
static char log[256];
|
|
||||||
|
|
||||||
unsigned long volatile jiffies;
|
unsigned long volatile jiffies;
|
||||||
|
int oops_in_progress;
|
||||||
struct workqueue_struct *system_wq;
|
|
||||||
int driver_wq_state;
|
|
||||||
|
|
||||||
int x86_clflush_size;
|
int x86_clflush_size;
|
||||||
unsigned int tsc_khz;
|
unsigned int tsc_khz;
|
||||||
|
struct workqueue_struct *system_wq;
|
||||||
int i915_modeset = 1;
|
int driver_wq_state;
|
||||||
|
struct drm_device *main_device;
|
||||||
typedef union __attribute__((packed))
|
struct drm_file *drm_file_handlers[256];
|
||||||
{
|
videomode_t usermode;
|
||||||
uint32_t val;
|
extern int __getopt_initialized;
|
||||||
struct
|
|
||||||
{
|
|
||||||
uint8_t state;
|
|
||||||
uint8_t code;
|
|
||||||
uint16_t ctrl_key;
|
|
||||||
};
|
|
||||||
}oskey_t;
|
|
||||||
|
|
||||||
static inline oskey_t get_key(void)
|
|
||||||
{
|
|
||||||
oskey_t val;
|
|
||||||
asm volatile("int $0x40":"=a"(val):"a"(2));
|
|
||||||
return val;
|
|
||||||
};
|
|
||||||
|
|
||||||
void i915_dpms(struct drm_device *dev, int mode);
|
|
||||||
|
|
||||||
void i915_driver_thread()
|
void i915_driver_thread()
|
||||||
{
|
{
|
||||||
@ -186,7 +119,7 @@ u32 __attribute__((externally_visible)) drvEntry(int action, char *cmdline)
|
|||||||
{
|
{
|
||||||
static pci_dev_t device;
|
static pci_dev_t device;
|
||||||
const struct pci_device_id *ent;
|
const struct pci_device_id *ent;
|
||||||
|
char *safecmdline;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
if(action != 1)
|
if(action != 1)
|
||||||
@ -199,29 +132,97 @@ u32 __attribute__((externally_visible)) drvEntry(int action, char *cmdline)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
printf("\n%s build %s %s\nusage: i915 [options]\n"
|
printf("\n%s build %s %s\nusage: i915 [options]\n"
|
||||||
"-FB=<0-9> Set framebuffer size in megabytes (default: 16)\n",
|
"-f\n"
|
||||||
"-pm=<0,1> Enable powersavings, fbc, downclocking, etc. (default: 1 - true)\n",
|
"--fbsize <0-9> Set framebuffer size in megabytes (default: 16)\n",
|
||||||
DRV_NAME, __DATE__, __TIME__);
|
DRV_NAME, __DATE__, __TIME__);
|
||||||
|
|
||||||
printf("-rc6=<-1,0-7> Enable power-saving render C-state 6.\n"
|
printf("--rc6 <-1,0-7> Enable power-saving render C-state 6.\n"
|
||||||
" Different stages can be selected via bitmask values\n"
|
" Different stages can be selected via bitmask values\n"
|
||||||
" (0 = disable; 1 = enable rc6; 2 = enable deep rc6; 4 = enable deepest rc6).\n"
|
" (0 = disable; 1 = enable rc6; 2 = enable deep rc6;\n"
|
||||||
" For example, 3 would enable rc6 and deep rc6, and 7 would enable everything.\n"
|
" 4 = enable deepest rc6).\n"
|
||||||
|
" For example, 3 would enable rc6 and deep rc6,\n"
|
||||||
|
" and 7 would enable everything.\n"
|
||||||
" default: -1 (use per-chip default)\n");
|
" default: -1 (use per-chip default)\n");
|
||||||
printf("-fbc=<-1,0,1> Enable frame buffer compression for power savings\n"
|
printf("--fbc <-1,0,1> Enable frame buffer compression for power savings\n"
|
||||||
" (default: -1 (use per-chip default))\n");
|
" (default: -1 (use per-chip default))\n");
|
||||||
printf("-ppgt=<0,1> Enable PPGTT (default: true)\n");
|
printf("-l\n"
|
||||||
|
"--log <path> path to log file\n");
|
||||||
|
printf("-m\n"
|
||||||
|
"--mode <WxHxHz> set videomode\n");
|
||||||
|
printf("-v\n"
|
||||||
|
"--video <CONNECTOR>:<xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m][eDd]\n"
|
||||||
|
" set videomode for CONNECTOR\n");
|
||||||
|
|
||||||
printf("-l<path> path to log file\n");
|
|
||||||
printf("-m<WxHxHz> set videomode\n");
|
|
||||||
|
|
||||||
printf("cmdline %s\n", cmdline);
|
|
||||||
if( cmdline && *cmdline )
|
if( cmdline && *cmdline )
|
||||||
parse_cmdline(cmdline, cmdtable, log, &usermode);
|
|
||||||
|
|
||||||
if( *log && !dbg_open(log))
|
|
||||||
{
|
{
|
||||||
printf("Can't open %s\nExit\n", log);
|
int argc, i, c;
|
||||||
|
char **argv;
|
||||||
|
|
||||||
|
safecmdline = __builtin_strdup(cmdline);
|
||||||
|
printf("cmdline %s\n", safecmdline);
|
||||||
|
|
||||||
|
argc = split_cmdline(safecmdline, NULL);
|
||||||
|
argv = __builtin_malloc((argc+1)*sizeof(char*));
|
||||||
|
split_cmdline(safecmdline, argv);
|
||||||
|
argv[argc] = NULL;
|
||||||
|
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
static struct option long_options[] =
|
||||||
|
{
|
||||||
|
{"log", required_argument, 0, 'l'},
|
||||||
|
{"mode", required_argument, 0, 'm'},
|
||||||
|
{"fbsize",required_argument, 0, 'f'},
|
||||||
|
{"video", required_argument, 0, 'v'},
|
||||||
|
{"rc6", required_argument, 0, OPTION_RC6},
|
||||||
|
{"fbc", required_argument, 0, OPTION_FBC},
|
||||||
|
{0, 0, 0, 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
int option_index = 0;
|
||||||
|
|
||||||
|
c = getopt_long (argc, argv, "f:l:m:v:",
|
||||||
|
long_options, &option_index);
|
||||||
|
|
||||||
|
if (c == -1)
|
||||||
|
break;
|
||||||
|
|
||||||
|
switch(c)
|
||||||
|
{
|
||||||
|
case OPTION_RC6:
|
||||||
|
i915.enable_rc6 = my_atoi(&optarg);
|
||||||
|
printf("i915.rc6 = %d\n",i915.enable_rc6);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OPTION_FBC:
|
||||||
|
i915.enable_fbc = my_atoi(&optarg);
|
||||||
|
printf("i915.fbc = %d\n",i915.enable_fbc);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'f':
|
||||||
|
i915.fbsize = my_atoi(&optarg);
|
||||||
|
printf("i915.fbsize =%d\n",i915.fbsize);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'l':
|
||||||
|
i915.log_file = optarg;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'm':
|
||||||
|
parse_mode(optarg, &usermode);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'v':
|
||||||
|
i915.cmdline_mode = optarg;
|
||||||
|
printf("i915.cmdline_mode =%s\n",i915.cmdline_mode);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if( i915.log_file && !dbg_open(i915.log_file))
|
||||||
|
{
|
||||||
|
printf("Can't open %s\nExit\n", i915.log_file);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -230,7 +231,6 @@ u32 __attribute__((externally_visible)) drvEntry(int action, char *cmdline)
|
|||||||
}
|
}
|
||||||
|
|
||||||
cpu_detect1();
|
cpu_detect1();
|
||||||
// dbgprintf("\ncache line size %d\n", x86_clflush_size);
|
|
||||||
|
|
||||||
err = enum_pci_devices();
|
err = enum_pci_devices();
|
||||||
if( unlikely(err != 0) )
|
if( unlikely(err != 0) )
|
||||||
@ -272,6 +272,54 @@ u32 __attribute__((externally_visible)) drvEntry(int action, char *cmdline)
|
|||||||
return err;
|
return err;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int do_command_line(const char* usercmd)
|
||||||
|
{
|
||||||
|
char *cmdline;
|
||||||
|
int argc, i, c;
|
||||||
|
char **argv;
|
||||||
|
|
||||||
|
if( (usercmd == NULL) || (*usercmd == 0) )
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
cmdline = __builtin_strdup(usercmd);
|
||||||
|
printf("cmdline %s\n", cmdline);
|
||||||
|
|
||||||
|
argc = split_cmdline(cmdline, NULL);
|
||||||
|
argv = __builtin_malloc((argc+1)*sizeof(char*));
|
||||||
|
split_cmdline(cmdline, argv);
|
||||||
|
argv[argc] = NULL;
|
||||||
|
|
||||||
|
__getopt_initialized = 0;
|
||||||
|
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
static struct option long_options[] =
|
||||||
|
{
|
||||||
|
{"video", required_argument, 0, 'v'},
|
||||||
|
{0, 0, 0, 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
int option_index = 0;
|
||||||
|
|
||||||
|
c = getopt_long (argc, argv, "v:",
|
||||||
|
long_options, &option_index);
|
||||||
|
|
||||||
|
if (c == -1)
|
||||||
|
break;
|
||||||
|
|
||||||
|
switch(c)
|
||||||
|
{
|
||||||
|
case 'v':
|
||||||
|
printf("cmdline_mode %s\n",optarg);
|
||||||
|
set_cmdline_mode_ext(main_device, optarg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
__builtin_free(argv);
|
||||||
|
__builtin_free(cmdline);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
#define CURRENT_API 0x0200 /* 2.00 */
|
#define CURRENT_API 0x0200 /* 2.00 */
|
||||||
#define COMPATIBLE_API 0x0100 /* 1.00 */
|
#define COMPATIBLE_API 0x0100 /* 1.00 */
|
||||||
@ -284,7 +332,7 @@ u32 __attribute__((externally_visible)) drvEntry(int action, char *cmdline)
|
|||||||
#define SRV_ENUM_MODES 1
|
#define SRV_ENUM_MODES 1
|
||||||
#define SRV_SET_MODE 2
|
#define SRV_SET_MODE 2
|
||||||
#define SRV_GET_CAPS 3
|
#define SRV_GET_CAPS 3
|
||||||
|
#define SRV_CMDLINE 4
|
||||||
|
|
||||||
#define SRV_GET_PCI_INFO 20
|
#define SRV_GET_PCI_INFO 20
|
||||||
#define SRV_I915_GET_PARAM 21
|
#define SRV_I915_GET_PARAM 21
|
||||||
@ -349,7 +397,6 @@ int _stdcall display_handler(ioctl_t *io)
|
|||||||
// inp, io->inp_size, io->out_size );
|
// inp, io->inp_size, io->out_size );
|
||||||
check_output(4);
|
check_output(4);
|
||||||
// check_input(*outp * sizeof(videomode_t));
|
// check_input(*outp * sizeof(videomode_t));
|
||||||
if( i915_modeset)
|
|
||||||
retval = get_videomodes((videomode_t*)inp, outp);
|
retval = get_videomodes((videomode_t*)inp, outp);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -357,7 +404,6 @@ int _stdcall display_handler(ioctl_t *io)
|
|||||||
// dbgprintf("SRV_SET_MODE inp %x inp_size %x\n",
|
// dbgprintf("SRV_SET_MODE inp %x inp_size %x\n",
|
||||||
// inp, io->inp_size);
|
// inp, io->inp_size);
|
||||||
check_input(sizeof(videomode_t));
|
check_input(sizeof(videomode_t));
|
||||||
if( i915_modeset )
|
|
||||||
retval = set_user_mode((videomode_t*)inp);
|
retval = set_user_mode((videomode_t*)inp);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -365,6 +411,10 @@ int _stdcall display_handler(ioctl_t *io)
|
|||||||
retval = get_driver_caps((hwcaps_t*)inp);
|
retval = get_driver_caps((hwcaps_t*)inp);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case SRV_CMDLINE:
|
||||||
|
retval = do_command_line((char*)inp);
|
||||||
|
break;
|
||||||
|
|
||||||
case SRV_GET_PCI_INFO:
|
case SRV_GET_PCI_INFO:
|
||||||
get_pci_info((struct pci_device *)inp);
|
get_pci_info((struct pci_device *)inp);
|
||||||
retval = 0;
|
retval = 0;
|
||||||
@ -779,7 +829,7 @@ static int my_atoi(char **cmd)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
char* parse_mode(char *p, videomode_t *mode)
|
static char* parse_mode(char *p, videomode_t *mode)
|
||||||
{
|
{
|
||||||
char c;
|
char c;
|
||||||
|
|
||||||
@ -806,89 +856,6 @@ char* parse_mode(char *p, videomode_t *mode)
|
|||||||
return p;
|
return p;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static char* parse_path(char *p, char *log)
|
|
||||||
{
|
|
||||||
char c;
|
|
||||||
|
|
||||||
while( (c = *p++) == ' ');
|
|
||||||
p--;
|
|
||||||
while((c = *p++) && (c != ' '))
|
|
||||||
*log++ = c;
|
|
||||||
|
|
||||||
*log = 0;
|
|
||||||
|
|
||||||
return p;
|
|
||||||
};
|
|
||||||
|
|
||||||
void parse_cmdline(char *cmdline, struct cmdtable *table, char *log, videomode_t *mode)
|
|
||||||
{
|
|
||||||
char *p = cmdline;
|
|
||||||
char *p1;
|
|
||||||
int val;
|
|
||||||
char c = *p++;
|
|
||||||
|
|
||||||
if( table )
|
|
||||||
{
|
|
||||||
while(table->key)
|
|
||||||
{
|
|
||||||
if(p1 = strstr(cmdline, table->key))
|
|
||||||
{
|
|
||||||
p1+= table->size;
|
|
||||||
*table->val = my_atoi(&p1);
|
|
||||||
}
|
|
||||||
table++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while( c )
|
|
||||||
{
|
|
||||||
if( c == '-')
|
|
||||||
{
|
|
||||||
switch(*p++)
|
|
||||||
{
|
|
||||||
case 'l':
|
|
||||||
p = parse_path(p, log);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'm':
|
|
||||||
p = parse_mode(p, mode);
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
c = *p++;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
char *strstr(const char *cs, const char *ct)
|
|
||||||
{
|
|
||||||
int d0, d1;
|
|
||||||
register char *__res;
|
|
||||||
__asm__ __volatile__(
|
|
||||||
"movl %6,%%edi\n\t"
|
|
||||||
"repne\n\t"
|
|
||||||
"scasb\n\t"
|
|
||||||
"notl %%ecx\n\t"
|
|
||||||
"decl %%ecx\n\t" /* NOTE! This also sets Z if searchstring='' */
|
|
||||||
"movl %%ecx,%%edx\n"
|
|
||||||
"1:\tmovl %6,%%edi\n\t"
|
|
||||||
"movl %%esi,%%eax\n\t"
|
|
||||||
"movl %%edx,%%ecx\n\t"
|
|
||||||
"repe\n\t"
|
|
||||||
"cmpsb\n\t"
|
|
||||||
"je 2f\n\t" /* also works for empty string, see above */
|
|
||||||
"xchgl %%eax,%%esi\n\t"
|
|
||||||
"incl %%esi\n\t"
|
|
||||||
"cmpb $0,-1(%%eax)\n\t"
|
|
||||||
"jne 1b\n\t"
|
|
||||||
"xorl %%eax,%%eax\n\t"
|
|
||||||
"2:"
|
|
||||||
: "=a" (__res), "=&c" (d0), "=&S" (d1)
|
|
||||||
: "0" (0), "1" (0xffffffff), "2" (cs), "g" (ct)
|
|
||||||
: "dx", "di");
|
|
||||||
return __res;
|
|
||||||
}
|
|
||||||
|
|
||||||
#include <linux/math64.h>
|
#include <linux/math64.h>
|
||||||
|
|
||||||
u64 long_div(u64 dividend, u64 divisor)
|
u64 long_div(u64 dividend, u64 divisor)
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include <linux/hdmi.h>
|
#include <linux/hdmi.h>
|
||||||
#include <linux/seq_file.h>
|
#include <linux/seq_file.h>
|
||||||
#include <linux/fence.h>
|
#include <linux/fence.h>
|
||||||
|
#include "i915_kos32.h"
|
||||||
|
|
||||||
struct file *shmem_file_setup(const char *name, loff_t size, unsigned long flags)
|
struct file *shmem_file_setup(const char *name, loff_t size, unsigned long flags)
|
||||||
{
|
{
|
||||||
@ -847,3 +848,184 @@ ktime_t ktime_get(void)
|
|||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *strdup(const char *str)
|
||||||
|
{
|
||||||
|
size_t len = strlen(str) + 1;
|
||||||
|
char *copy = __builtin_malloc(len);
|
||||||
|
if (copy)
|
||||||
|
{
|
||||||
|
memcpy (copy, str, len);
|
||||||
|
}
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
int split_cmdline(char *cmdline, char **argv)
|
||||||
|
{
|
||||||
|
enum quote_state
|
||||||
|
{
|
||||||
|
QUOTE_NONE, /* no " active in current parm */
|
||||||
|
QUOTE_DELIMITER, /* " was first char and must be last */
|
||||||
|
QUOTE_STARTED /* " was seen, look for a match */
|
||||||
|
};
|
||||||
|
|
||||||
|
enum quote_state state;
|
||||||
|
unsigned int argc;
|
||||||
|
char *p = cmdline;
|
||||||
|
char *new_arg, *start;
|
||||||
|
|
||||||
|
argc = 0;
|
||||||
|
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
/* skip over spaces and tabs */
|
||||||
|
if ( *p )
|
||||||
|
{
|
||||||
|
while (*p == ' ' || *p == '\t')
|
||||||
|
++p;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*p == '\0')
|
||||||
|
break;
|
||||||
|
|
||||||
|
state = QUOTE_NONE;
|
||||||
|
if( *p == '\"' )
|
||||||
|
{
|
||||||
|
p++;
|
||||||
|
state = QUOTE_DELIMITER;
|
||||||
|
}
|
||||||
|
new_arg = start = p;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if( *p == '\"' )
|
||||||
|
{
|
||||||
|
p++;
|
||||||
|
if( state == QUOTE_NONE )
|
||||||
|
{
|
||||||
|
state = QUOTE_STARTED;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
state = QUOTE_NONE;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( *p == ' ' || *p == '\t' )
|
||||||
|
{
|
||||||
|
if( state == QUOTE_NONE )
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( *p == '\0' )
|
||||||
|
break;
|
||||||
|
|
||||||
|
if( *p == '\\' )
|
||||||
|
{
|
||||||
|
if( p[1] == '\"' )
|
||||||
|
{
|
||||||
|
++p;
|
||||||
|
if( p[-2] == '\\' )
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( argv )
|
||||||
|
{
|
||||||
|
*(new_arg++) = *p;
|
||||||
|
}
|
||||||
|
++p;
|
||||||
|
};
|
||||||
|
|
||||||
|
if( argv )
|
||||||
|
{
|
||||||
|
argv[ argc ] = start;
|
||||||
|
++argc;
|
||||||
|
|
||||||
|
/*
|
||||||
|
The *new = '\0' is req'd in case there was a \" to "
|
||||||
|
translation. It must be after the *p check against
|
||||||
|
'\0' because new and p could point to the same char
|
||||||
|
in which case the scan would be terminated too soon.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if( *p == '\0' )
|
||||||
|
{
|
||||||
|
*new_arg = '\0';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*new_arg = '\0';
|
||||||
|
++p;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
++argc;
|
||||||
|
if( *p == '\0' )
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
++p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return argc;
|
||||||
|
};
|
||||||
|
|
||||||
|
char *strstr(const char *cs, const char *ct)
|
||||||
|
{
|
||||||
|
int d0, d1;
|
||||||
|
register char *__res;
|
||||||
|
__asm__ __volatile__(
|
||||||
|
"movl %6,%%edi\n\t"
|
||||||
|
"repne\n\t"
|
||||||
|
"scasb\n\t"
|
||||||
|
"notl %%ecx\n\t"
|
||||||
|
"decl %%ecx\n\t" /* NOTE! This also sets Z if searchstring='' */
|
||||||
|
"movl %%ecx,%%edx\n"
|
||||||
|
"1:\tmovl %6,%%edi\n\t"
|
||||||
|
"movl %%esi,%%eax\n\t"
|
||||||
|
"movl %%edx,%%ecx\n\t"
|
||||||
|
"repe\n\t"
|
||||||
|
"cmpsb\n\t"
|
||||||
|
"je 2f\n\t" /* also works for empty string, see above */
|
||||||
|
"xchgl %%eax,%%esi\n\t"
|
||||||
|
"incl %%esi\n\t"
|
||||||
|
"cmpb $0,-1(%%eax)\n\t"
|
||||||
|
"jne 1b\n\t"
|
||||||
|
"xorl %%eax,%%eax\n\t"
|
||||||
|
"2:"
|
||||||
|
: "=a" (__res), "=&c" (d0), "=&S" (d1)
|
||||||
|
: "0" (0), "1" (0xffffffff), "2" (cs), "g" (ct)
|
||||||
|
: "dx", "di");
|
||||||
|
return __res;
|
||||||
|
}
|
||||||
|
|
||||||
|
fb_get_options(const char *name, char **option)
|
||||||
|
{
|
||||||
|
char *opt, *options = NULL;
|
||||||
|
int retval = 1;
|
||||||
|
int name_len;
|
||||||
|
|
||||||
|
if(i915.cmdline_mode == NULL)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
name_len = __builtin_strlen(name);
|
||||||
|
|
||||||
|
if (name_len )
|
||||||
|
{
|
||||||
|
opt = i915.cmdline_mode;
|
||||||
|
if (!__builtin_strncmp(name, opt, name_len) &&
|
||||||
|
opt[name_len] == ':')
|
||||||
|
{
|
||||||
|
options = opt + name_len + 1;
|
||||||
|
retval = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (option)
|
||||||
|
*option = options;
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user